Operator-asked 2026-05-31. The extension's floating button now reflects the URL's actual state in FC BEFORE the click instead of learning it after:
Green ✓ In FabledCurator · Patreon → click opens the FC artist page in a new tab (operator's pick).
Amber + Add Patreon source to {artist} → click adds a new Source against the existing artist. Covers the sidecar-synthetic-only "Dymkens" case from v26.06.01.0.
Blue + Add to FabledCurator → click creates artist + source (current behavior).
No injection on non-artist URLs (/posts/N, /home, etc.).
New GET /api/extension/probe?url=... read-only backend route + ExtensionService.probe. Extension v1.0.5 → 1.0.6 so build.yml's ext-1.0.6 cache miss fires AMO sign-extension and exercises the regenerated AMO keys end-to-end. 6 backend tests covering all states + auth + invalid URL.
8de7ccd — :c-<short_sha> per-commit image tags
Implements the new family release-posture rule (Scribe rulebook rule #46): every main-push build now publishes git.fabledsword.com/bvandeusen/fabledcurator{,-ml}:c-<short_sha> alongside the floating :main / :latest. Rollback to any commit on main is docker pull …:c-<sha> — no release ceremony required. vYY.MM.DD tags become opt-in milestone labels (no .N suffix); tag-push workflow stays as a no-op when you choose to mark one.
Test plan
After merge, the build-web and build-ml jobs each publish three image tags (:main, :latest, :c-<short_sha>).
Visiting a known-subscribed Patreon page shows the green chip; click opens FC's /artist/<slug> in a new tab.
Visiting an unknown Patreon creator shows the blue chip; click adds + flips green on next probe.
Visiting an artist-exists-but-no-real-source URL (sidecar synthetic case) shows the amber chip naming the artist; click adds the real Source.
sign-extension fires on this main-push (cache miss for ext-1.0.6) and the AMO round-trip succeeds — exercises the regenerated keys end-to-end.
## Summary
Two coupled landings:
### `d65f0b2` — Extension probe-and-add (v1.0.6)
Operator-asked 2026-05-31. The extension's floating button now reflects the URL's actual state in FC BEFORE the click instead of learning it after:
- Green `✓ In FabledCurator · Patreon` → click opens the FC artist page in a new tab (operator's pick).
- Amber `+ Add Patreon source to {artist}` → click adds a new Source against the existing artist. Covers the sidecar-synthetic-only "Dymkens" case from v26.06.01.0.
- Blue `+ Add to FabledCurator` → click creates artist + source (current behavior).
- No injection on non-artist URLs (`/posts/N`, `/home`, etc.).
New `GET /api/extension/probe?url=...` read-only backend route + `ExtensionService.probe`. Extension v1.0.5 → 1.0.6 so build.yml's `ext-1.0.6` cache miss fires AMO sign-extension and exercises the regenerated AMO keys end-to-end. 6 backend tests covering all states + auth + invalid URL.
### `8de7ccd` — `:c-<short_sha>` per-commit image tags
Implements the new family release-posture rule (Scribe rulebook rule #46): every main-push build now publishes `git.fabledsword.com/bvandeusen/fabledcurator{,-ml}:c-<short_sha>` alongside the floating `:main` / `:latest`. Rollback to any commit on main is `docker pull …:c-<sha>` — no release ceremony required. `vYY.MM.DD` tags become opt-in milestone labels (no `.N` suffix); tag-push workflow stays as a no-op when you choose to mark one.
## Test plan
- [ ] After merge, the build-web and build-ml jobs each publish three image tags (`:main`, `:latest`, `:c-<short_sha>`).
- [ ] Visiting a known-subscribed Patreon page shows the green chip; click opens FC's `/artist/<slug>` in a new tab.
- [ ] Visiting an unknown Patreon creator shows the blue chip; click adds + flips green on next probe.
- [ ] Visiting an artist-exists-but-no-real-source URL (sidecar synthetic case) shows the amber chip naming the artist; click adds the real Source.
- [ ] sign-extension fires on this main-push (cache miss for `ext-1.0.6`) and the AMO round-trip succeeds — exercises the regenerated keys end-to-end.
Operator-asked 2026-05-31 (during sidecar synthetic anchor cleanup):
"the add source/subscription button idea to the firefox extension so
it can tell me if a source/artist is added or not and offer an option
to add it if it isn't." Plan tracked in Scribe task #507.
## Backend
- `ExtensionService.probe(url)` — read-only resolution. Reuses
`_derive` for platform+slug, then 2 SELECTs. Returns one of:
- `source_match` (exact (artist, platform, url) Source exists)
- `artist_match` (artist exists, this URL isn't a Source yet;
collapses the sidecar-synthetic-only case from v26.06.01.0)
- `new` (neither exists)
- `unknown_platform` (URL didn't match any artist-page regex)
- `GET /api/extension/probe?url=...` route with `X-Extension-Key`
auth posture matching `/quick-add-source`. Read-only, side-effect
free.
- 6 backend tests in tests/test_api_extension.py covering each state
+ auth + invalid URL.
## Extension
- `api.js`: `probeSource(url)` mirroring `quickAddSource` shape.
- `background.js`: `PROBE_SOURCE` + `OPEN_ARTIST_PAGE` handlers. The
latter strips the `/api` suffix from configured `apiUrl` (placeholder
format per options.html) and opens `${base}/artist/{slug}` in a new
tab via `browser.tabs.create`.
- `content-script.js`: probe-first render — on page-load and SPA
navigation, asks the backend for the URL's state and renders the
chip in the matching color/copy on FIRST paint instead of flashing
generic "Add" and updating after. Click handler branches:
`source_match` → OPEN_ARTIST_PAGE; `artist_match`/`new` → existing
ADD_AS_SOURCE flow (then re-probes so the chip flips green
immediately, no wait for next nav).
- `content-script.css`: three state-color modifiers
(--new, --artist-match, --source-match) on the FC parchment-on-slate
palette. Sage for already-added, amber for artist-exists, accent
orange for new.
## Versioning
- `extension/manifest.json` + `extension/package.json` → 1.0.6.
build.yml's sign-extension job will fire on push to main since no
`ext-1.0.6` Forgejo/Gitea release exists yet — exercises the
regenerated AMO keys end-to-end.
## Behavior on the sidecar-synthetic case
Filesystem-imported "Dymkens"-style artist with only a sidecar
synthetic Source: probe returns `artist_match` (not `new`), so the
chip reads "+ Add Patreon source to Dymkens" rather than offering to
recreate the artist. Clicking adds the real Source; existing
`_source_for_sidecar` preference logic (v26.06.01.0) routes future
gallery-dl Posts to the real one.
Adds an immutable per-commit docker tag to every main-push build:
`git.fabledsword.com/bvandeusen/fabledcurator{,-ml}:c-<short_sha>`,
alongside the existing floating `:main` + `:latest`. Implements the
new family release-posture rule "Tags are milestones, not gates —
commit-SHA images are the rollback unit" so rollback to any commit
on main is `docker pull …:c-<sha>` with no release ceremony required.
Behavior change summary:
- main-push: was {:main, :latest} → now {:main, :latest, :c-<short_sha>}
- tag-push (opt-in vYY.MM.DD only, no .N): unchanged
- safety-net dev: unchanged
No code changes; the rule is about how the tag list is constructed.
Tag-push workflows stay as-is — vYY.MM.DD milestone cuts can still
fire them when the operator wants a labeled checkpoint.
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.
Summary
Two coupled landings:
d65f0b2— Extension probe-and-add (v1.0.6)Operator-asked 2026-05-31. The extension's floating button now reflects the URL's actual state in FC BEFORE the click instead of learning it after:
✓ In FabledCurator · Patreon→ click opens the FC artist page in a new tab (operator's pick).+ Add Patreon source to {artist}→ click adds a new Source against the existing artist. Covers the sidecar-synthetic-only "Dymkens" case from v26.06.01.0.+ Add to FabledCurator→ click creates artist + source (current behavior)./posts/N,/home, etc.).New
GET /api/extension/probe?url=...read-only backend route +ExtensionService.probe. Extension v1.0.5 → 1.0.6 so build.yml'sext-1.0.6cache miss fires AMO sign-extension and exercises the regenerated AMO keys end-to-end. 6 backend tests covering all states + auth + invalid URL.8de7ccd—:c-<short_sha>per-commit image tagsImplements the new family release-posture rule (Scribe rulebook rule #46): every main-push build now publishes
git.fabledsword.com/bvandeusen/fabledcurator{,-ml}:c-<short_sha>alongside the floating:main/:latest. Rollback to any commit on main isdocker pull …:c-<sha>— no release ceremony required.vYY.MM.DDtags become opt-in milestone labels (no.Nsuffix); tag-push workflow stays as a no-op when you choose to mark one.Test plan
:main,:latest,:c-<short_sha>)./artist/<slug>in a new tab.ext-1.0.6) and the AMO round-trip succeeds — exercises the regenerated keys end-to-end.Adds an immutable per-commit docker tag to every main-push build: `git.fabledsword.com/bvandeusen/fabledcurator{,-ml}:c-<short_sha>`, alongside the existing floating `:main` + `:latest`. Implements the new family release-posture rule "Tags are milestones, not gates — commit-SHA images are the rollback unit" so rollback to any commit on main is `docker pull …:c-<sha>` with no release ceremony required. Behavior change summary: - main-push: was {:main, :latest} → now {:main, :latest, :c-<short_sha>} - tag-push (opt-in vYY.MM.DD only, no .N): unchanged - safety-net dev: unchanged No code changes; the rule is about how the tag list is constructed. Tag-push workflows stay as-is — vYY.MM.DD milestone cuts can still fire them when the operator wants a labeled checkpoint.