Commit Graph
236 Commits
Author SHA1 Message Date
flanandClaude Sonnet 4.6 125ce54c7f fix: stale __version__, scheduler import order, quality test coverage
- __init__.py: derive __version__ from importlib.metadata instead of
  a hardcoded "0.1.0" that was six releases out of date
- scheduler.py: move winnow.cli import to module top (no more noqa);
  clean up redundant bool variables in check_models
- tests/test_quality.py: 17 tests covering all five quality check
  functions individually plus assess_quality integration cases

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 05:33:38 +00:00
flanandClaude Sonnet 4.6 f50d3fe1ab refactor: rename logging.py, in-process scheduler, trim .gitignore
- winnow/logging.py → winnow/log_config.py: avoids shadowing the stdlib
  logging module; log file renamed from immich_export.log to winnow.log
- scheduler.py: run main() in-process instead of subprocess.run so
  InsightFace and SigLIP models stay resident in memory across scheduled
  runs (hundreds of MB load, previously reloaded every run)
- .gitignore: replaced 200-line boilerplate with ~30 project-relevant
  patterns; removed Django/Flask/Redis/RabbitMQ/Scrapy/etc. noise
- .python-version: untracked (redundant with requires-python in
  pyproject.toml; kept in .gitignore for local pyenv users)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 05:30:37 +00:00
flanandClaude Sonnet 4.6 af92fe5fcc fix: bugs and code quality in embeddings, jobs, diversity, config
- embeddings: initialize ctx_id=-1 before try block so the except
  handler cannot NameError; move insightface_home out of try for the
  same reason
- embeddings: replace contextlib.redirect_stdout/stderr (Python-level
  only) with fd-level dup2 suppression — actually silences C extension
  noise from InsightFace during model loading
- jobs: fix frigate_count==0 falling through `or` chain; use explicit
  `is not None` check so a real zero is not treated as missing data
- diversity: thread person_id through select_diverse_assets →
  _select_by_embedding → _get_face_bbox / _get_face_confidence /
  _crop_face_from_thumbnail so group-photo assets embed the target
  person's face rather than whichever person is listed first
- config: replace type() hack for ConfigManager with a proper class

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 05:24:35 +00:00
flanandClaude Sonnet 4.6 4cac3d28d2 fix: onnxruntime-gpu is x86_64-only; use onnxruntime on arm64
onnxruntime-gpu has no arm64 wheels (manylinux_2_27_x86_64 /
manylinux_2_28_x86_64 only). uv sync --frozen failed on the arm64
image with exit code 2. Gated onnxruntime-gpu behind the x86_64
marker; arm64 and non-Linux use the CPU onnxruntime package. Added
required-environments so the lockfile is solved for both platforms.
Removed onnxruntime-gpu from override-dependencies (it had no marker
support and blocked arm64 resolution).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.2.9
2026-06-12 05:05:25 +00:00
flanandClaude Sonnet 4.6 21208f8331 docs: update Python version to 3.13 in README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 04:51:08 +00:00
flanandClaude Sonnet 4.6 209e077055 fix: add-apt-repository with GNUPGHOME, true arm64 base; license to AGPLv3
curl|gpg --dearmor was silently dropping the deadsnakes key (gpg exits 0
on bad input), leaving apt unable to find python3.13. Reverted to
add-apt-repository with GNUPGHOME=$(mktemp -d) to isolate gpg from any
pre-existing agent socket. Removed --platform=\$BUILDPLATFORM from the
arm64 base so the image contains real arm64 binaries. License updated
from MIT to AGPL-3.0-or-later.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.2.8
2026-06-12 04:48:28 +00:00
flan e7c1fc5d9b docs: revert Wiki label back to Docs in README 2026-06-12 04:39:31 +00:00
flan 14a36f2aea docs: rename Docs label to Wiki in README 2026-06-12 04:39:02 +00:00
flanandClaude Sonnet 4.6 8ec69b7f56 docs: clean up README badges
Title first, then badges on one consistent line. Removed redundant
Release and Lint badges. Fixed docs links to point to the wiki.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 04:38:01 +00:00
flanandClaude Sonnet 4.6 7bd66c4218 fix: use curl+gpg for deadsnakes PPA, arm64 base back to ubuntu:24.04
Ubuntu 26.04 ships Python 3.14, not 3.13. Reverted arm64 to ubuntu:24.04.
Both architectures now add the deadsnakes PPA by fetching the GPG key via
curl and piping through gpg --dearmor — no gpg-agent, safe under QEMU.
Removes the per-arch conditional and ARG TARGETARCH dependency in RUN commands.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.2.7
2026-06-12 04:36:12 +00:00
github-actions[bot] 57915c67fc chore: update uv.lock 2026-06-12 04:30:25 +00:00
flanandClaude Sonnet 4.6 619a96b8c3 fix: re-declare ARG TARGETARCH in each Dockerfile stage
Docker automatic platform ARGs are only in scope for FROM instructions.
$TARGETARCH in RUN commands was always empty, so the deadsnakes PPA
conditional never ran and python3.13 could not be found on the Ubuntu
22.04 CUDA base.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.2.6
2026-06-12 04:30:00 +00:00
github-actions[bot] a8bdbcdd66 chore: update uv.lock 2026-06-12 04:25:56 +00:00
flanandClaude Sonnet 4.6 9e2a09cda9 chore: bump to v0.2.5, document CUDA 13.3 and torchvision changes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.2.5
2026-06-12 04:25:31 +00:00
flan a3405108c9 build(deps): bump nvidia/cuda to 13.3.0-cudnn-runtime-ubuntu22.04
build(deps): bump nvidia/cuda from 12.9.2-cudnn-runtime-ubuntu22.04 to 13.3.0-cudnn-runtime-ubuntu22.04
2026-06-12 00:21:14 -04:00
dependabot[bot] d563aa9e74 build(deps): bump nvidia/cuda
Bumps nvidia/cuda from 12.9.2-cudnn-runtime-ubuntu22.04 to 13.3.0-cudnn-runtime-ubuntu22.04.

---
updated-dependencies:
- dependency-name: nvidia/cuda
  dependency-version: 13.3.0-cudnn-runtime-ubuntu22.04
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-12 04:20:26 +00:00
flanandClaude Sonnet 4.6 34d4780554 feat: upgrade to Python 3.13, arm64 base to Ubuntu 26.04
All platforms now use Python 3.13. amd64 installs via deadsnakes PPA on
the Ubuntu 22.04 CUDA base; arm64 gets Python 3.13 natively from Ubuntu
26.04. Verified cp313 wheels exist for onnxruntime-gpu 1.26.0 and
torch 2.12.0+cu126. uv.lock regenerated under CPython 3.13.5.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.2.4
2026-06-12 04:18:50 +00:00
flan 67b05502b3 Merge pull request #10 from sudolulo/dependabot/uv/python-deps-9abea99da4
build(deps): bump the python-deps group with 4 updates
2026-06-12 00:14:32 -04:00
flanandClaude Sonnet 4.6 3087d59558 fix: bump arm64 base to Ubuntu 26.04
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 04:04:20 +00:00
flanandClaude Sonnet 4.6 c59acb5e31 fix: use Ubuntu 24.04 for arm64 base to avoid deadsnakes PPA under QEMU
add-apt-repository ppa:deadsnakes/ppa fails on arm64 in GitHub Actions
because QEMU emulation doesn't support the GPG agent. Ubuntu 24.04 ships
Python 3.12 natively so the PPA is not needed. amd64 (CUDA/Ubuntu 22.04
base) still uses the PPA. PPA install is now gated on TARGETARCH=amd64.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 04:02:49 +00:00
dependabot[bot] c8fbbc0431 build(deps): bump docker/setup-buildx-action from 3 to 4
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3 to 4.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-12 03:57:11 +00:00
dependabot[bot] c1cc0dd9c2 build(deps): bump docker/login-action from 3 to 4
Bumps [docker/login-action](https://github.com/docker/login-action) from 3 to 4.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-12 03:57:08 +00:00
dependabot[bot] 57668dabf4 build(deps): bump astral-sh/setup-uv from 4 to 7
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 4 to 7.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](https://github.com/astral-sh/setup-uv/compare/v4...v7)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-12 03:57:05 +00:00
dependabot[bot] 2172b61254 build(deps): bump actions/github-script from 7 to 9
Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 9.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v7...v9)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: '9'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-12 03:57:01 +00:00
dependabot[bot] 10eb7265c1 build(deps): bump actions/checkout from 4 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-12 03:56:58 +00:00
flanandClaude Sonnet 4.6 7b4722d3f2 release: v0.2.3 — security fixes and CI improvements
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.2.3
2026-06-12 03:53:16 +00:00
flanandClaude Sonnet 4.6 444932c369 fix: remove API key from plain-text config file, add workflow permissions
- config.py: stop writing API_KEY to .immich_config.json; direct users
  to .env instead. Resolves CodeQL py/clear-text-storage-sensitive-data.
- test.yml, lint.yml: add permissions: contents: read to satisfy
  actions/missing-workflow-permissions scanner.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 03:51:55 +00:00
flanandClaude Sonnet 4.6 8f2a6d3163 docs: move to GitHub wiki (https://github.com/sudolulo/winnow/wiki)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 03:48:53 +00:00
flanandClaude Sonnet 4.6 b98fc94179 ci: remove lockfile verify race condition
uv lock --check in a separate job races against the update-lockfile
bot. Replace with uv lock inline in release.yml and drop the pre-job
from docker-publish.yml entirely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.2.2
2026-06-12 03:43:05 +00:00
github-actions[bot] 762ee160c3 chore: update uv.lock 2026-06-12 03:34:10 +00:00
flanandClaude Sonnet 4.6 759579fc30 feat: confidence scores, Frigate-authoritative capacity cap
- Store Immich face confidence scores per asset in frigate_uploaded_ids.json
- Add frigate_api.py: query GET /api/faces to count trained images per person
- Record Frigate training count as frigate_count in tracker for offline fallback
- MAX_AUTO_IMAGES cap now uses live Frigate count → cached frigate_count → local uploaded count
- Startup summary shows last known Frigate training count per person
- Migrate by_person entries from flat list to {asset_ids, scores, frigate_count} dict

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 03:33:40 +00:00
dependabot[bot] b6659c2218 build(deps): bump the python-deps group with 4 updates
Bumps the python-deps group with 4 updates: [nvidia-cudnn-cu12](https://developer.nvidia.com/cuda-zone), torch, [ultralytics](https://github.com/ultralytics/ultralytics) and [ruff](https://github.com/astral-sh/ruff).


Updates `nvidia-cudnn-cu12` from 9.10.2.21 to 9.23.1.3

Updates `torch` from 2.12.0 to 2.6.0+cu126

Updates `ultralytics` from 8.4.64 to 8.4.66
- [Release notes](https://github.com/ultralytics/ultralytics/releases)
- [Commits](https://github.com/ultralytics/ultralytics/compare/v8.4.64...v8.4.66)

Updates `ruff` from 0.15.16 to 0.15.17
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.15.16...0.15.17)

---
updated-dependencies:
- dependency-name: nvidia-cudnn-cu12
  dependency-version: 9.23.1.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python-deps
- dependency-name: torch
  dependency-version: 2.6.0+cu126
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python-deps
- dependency-name: ultralytics
  dependency-version: 8.4.66
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: python-deps
- dependency-name: ruff
  dependency-version: 0.15.17
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: python-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-12 02:37:03 +00:00
flanandClaude Sonnet 4.6 0e416176c6 docs: clarify use case includes people who have never been to your property
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.2.1
2026-06-12 02:14:26 +00:00
flanandClaude Sonnet 4.6 e856cba6d7 docs: explain use case for infrequent visitors
Adds context that winnow is especially useful for people who aren't
around enough for Frigate's live detections to supply adequate training
data on their own.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 02:14:16 +00:00
flanandClaude Sonnet 4.6 e4d5f603d8 docs: remove TrueNAS references, make volume paths platform agnostic
- compose.yml: generic /path/to/winnow/... placeholder paths
- docs/setup.md: replace TrueNAS section with generic GPU passthrough guide
- docs/faq.md: remove platform-specific path example
- README.md: soften crop quality disclaimer, remove TrueNAS compose note
- CHANGELOG.md: scrub TrueNAS mentions from release notes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 02:13:29 +00:00
flanandClaude Sonnet 4.6 0a67699db4 docs: add early stage disclaimer and manual review note
Advises users to review Frigate uploads after a run and remove bad
crops manually. Links to GitHub Issues for feedback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 02:12:12 +00:00
flanandClaude Sonnet 4.6 f9b9cea84f docs: add lint fix to 0.2.1 changelog
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 02:11:35 +00:00
flanandClaude Sonnet 4.6 4b6bce9b74 fix: resolve ruff lint errors in scheduler and tests
- scheduler.py: sort import block (I001)
- tests/test_config.py: remove unused os, pytest imports (F401)
- tests/test_upload_tracker.py: remove unused json, os, tempfile imports (F401)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 02:11:16 +00:00
flanandClaude Sonnet 4.6 c3bf81d490 fix: direct venv python in entrypoint, fix INSIGHTFACE_HOME path, add badges
- entrypoint.sh: replace `uv run` with `/app/.venv/bin/python` to skip
  uv's sync check which was re-downloading ruff and rebuilding the package
  on every container startup
- compose.yml, .env.example: fix INSIGHTFACE_HOME /models → /models/.insightface;
  InsightFace appends models/ to root, so /models produced /models/models/buffalo_l
- README.md: add Immich and Frigate badges from upstream
- CHANGELOG.md, pyproject.toml, uv.lock: bump to 0.2.1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 02:10:01 +00:00
flanandClaude Sonnet 4.6 4529a63082 fix: add WORKDIR /app to runtime stage in Dockerfile
Runtime stage was missing WORKDIR, so uv run started from / and
couldn't find the .venv or pyproject.toml, causing "No module named
'winnow'" on container startup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 02:01:32 +00:00
flanandClaude Sonnet 4.6 ec9d2ecd0f chore: remove compose.override.yml from repo, add to .gitignore
Local dev override with machine-specific paths and build context;
not useful to other users.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 02:01:32 +00:00
flan 1df7c99c2e Update README.md 2026-06-11 21:47:10 -04:00
flanandClaude Sonnet 4.6 61204c2eca chore: bump version to 0.2.0, write full changelog
- pyproject.toml: version 0.1.0 → 0.2.0
- CHANGELOG.md: full [0.2.0] entry covering all changes since the fork —
  headless operation, Docker/scheduling, object mode, people filtering,
  quality controls, CI/CD, tests, docs, and all bug fixes
- uv.lock: regenerated after version bump

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.2.0
2026-06-12 01:32:18 +00:00
flanandClaude Sonnet 4.6 b7dc87b05b docs: add wiki, .env.example, and fix stale if-curator references
- Add docs/setup.md, docs/troubleshooting.md, docs/faq.md as user-facing wiki
- Add .env.example with all env vars and inline comments
- Fix compose.override.yml: rename service if-curator → winnow, update volume paths
- Fix CHANGELOG.md: rename if-curator → winnow in release notes
- Link docs from README

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 01:26:24 +00:00
flanandClaude Sonnet 4.6 eea7baa19f refactor: rename project to winnow
- Rename Python package directory if_curator/ → winnow/
- Update all imports, entry points, and CLI references
- Update pyproject.toml: name, scripts, package list, repository URL
- Update Dockerfile, compose.yml, entrypoint.sh, scheduler.py
- Update GitHub Actions workflow image names
- Update README

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 01:07:46 +00:00
flanandClaude Sonnet 4.6 ca7b90f8ef docs: rewrite README from scratch
Describes the full pipeline (fetch → filter → embed → cluster → crop →
upload), explains why diversity matters and how the K-Medoids + FPS
selection works, covers both face and object modes in detail, and
documents all env vars in one place.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 01:02:28 +00:00
flanandClaude Sonnet 4.6 ed8487807b chore: establish authorship — Holden Salomon
- LICENSE: add copyright line for Holden Salomon (retain original)
- pyproject.toml: update authors to Holden Salomon <holden@arch.fyi>
- README: lead with what the software does rather than fork attribution;
  merge split env var tables into one unified reference; add lint/test
  badges; move attribution to footer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 01:00:17 +00:00
flanandClaude Sonnet 4.6 5634dd9e0c ci: add uv/docker/github-actions dependabot + run lint/test on dev
- dependabot.yml: add uv ecosystem (updates pyproject.toml + uv.lock
  together), github-actions ecosystem (keeps action versions current),
  and group all Python deps into one weekly PR
- lint.yml, test.yml: extend triggers to dev branch so ruff and pytest
  run on push/PR to dev, not just main

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 00:44:44 +00:00
flanandClaude Sonnet 4.6 eedbd3180a fix: resolve all linting errors, add tests, bump base image
Linting (ruff):
- cli.py: sort relative imports (I001)
- jobs.py: remove unused get_people import (F401), wrap long line (E501)
- executor.py: remove unused success variable (F841), wrap 4 long lines (E501)

Tests (24 passing):
- tests/test_config.py: config singleton defaults + env var overrides
- tests/test_upload_tracker.py: mark/filter/reset/summary logic
- tests/test_immich_api.py: filter_recent_assets date boundary cases
- tests/test_jobs.py: _resolve_strategy with LIMIT env var and fallbacks
- pyproject.toml: add [tool.pytest.ini_options] testpaths=["tests"] so
  pytest doesn't scan .venv in CI

Security:
- Dockerfile: bump CUDA base from 12.6.3 to 12.9.2 to pick up patched
  Ubuntu packages (fixes Dependabot low-severity alert)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 00:42:38 +00:00
flanandClaude Sonnet 4.6 c861d56a53 feat: expose all interactive CLI options via env vars
- config.py: wire BLUR_THRESHOLD, MIN_CONFIDENCE, MAX_AUTO_IMAGES,
  FACE_MARGIN, USE_FULL_RESOLUTION, ENABLE_FACE_ALIGNMENT to env vars
  (were hardcoded class defaults, inaccessible in AUTO_MODE)
- jobs.py: add LIMIT env var for custom image count in auto mode;
  overrides STRATEGY preset (mirrors interactive Custom Count option)
- compose.yml: document all env vars with inline comments grouped by
  concern — mode/strategy, people filtering, image quality, caching,
  tracker overrides, scheduling

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 00:37:16 +00:00