Skip to content

chore(release): promote 0.19.2 - #615

Merged
tomymaritano merged 11 commits into
mainfrom
develop
Aug 26, 2026
Merged

chore(release): promote 0.19.2#615
tomymaritano merged 11 commits into
mainfrom
develop

Conversation

@tomymaritano

Copy link
Copy Markdown
Collaborator

Promote 0.19.2 so the next AppImage installs first-party catalog cards via Worker bundleUrl (no GitHub API 403 on limestone/walnut/ash).

develop is ahead of v0.19.1 with fix: only (#612 Browse live extras + first-party install, #614 GraphQL 403 → REST). ci: #613 (sync GH_TOKEN onto the Worker) does not bump. semantic-release will cut 0.19.2, not 0.20.0.

Merge with a merge commit. Do not squash. Squashing drops the fix history and semantic-release will not bump.

CI is the gate. Do not bump package.json. Do not push a tag. Do not Run workflow. Release + Build & Publish + deploy-api.yml start from this merge.

No OFFICIAL_THEMES refill. No public marketplace. Themes picker is still Default + installed packs; browse-from-Themes is a follow-up.

HEAD: 4ae8fb4.

tomymaritano and others added 9 commits August 25, 2026 14:04
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary

Build & Publish for v0.19.1 compiled mac/win/linux and uploaded
installers, then the **publish** job failed with `release not found`
(`gh release edit v0.19.1 --draft=false`).

Draft GitHub Releases stay untagged until they are published, so `GET
/repos/.../releases/tags/v0.19.1` 404s. `gh release edit $TAG` uses that
endpoint (plus a GraphQL fallback that can miss untagged drafts). The
same command worked for v0.19.0 and failed for v0.19.1.

The publish job now resolves the numeric release id from the list
endpoint (includes drafts) and `PATCH`es `draft=false` by id. Meta
records that id when the draft already exists.

v0.19.1 itself is already published (installers were on the draft; it
was undrafted by id). This PR is so the next cut does not die on the
same lookup.

## Type of Change

- [x] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update

## Related Issues

Failed run: https://github.com/dripnex/app/actions/runs/32853368634 (job
97822265140)

## Checklist

- [x] I've read [CONTRIBUTING.md](../CONTRIBUTING.md)
- [ ] Tests pass locally (`pnpm test`) — workflow YAML only; `python3`
yaml parse succeeded; typecheck ran on push
- [ ] Build succeeds (`pnpm build`) — not required for this CI-only
change
- [x] PR targets `develop` branch (not `main`)

## What changed

- `meta` outputs `release_id` from `GET /releases` (drafts included).
- `publish` PATCHes that id with `draft=false` and `tag_name`, with a
short retry if the id is not known yet.

## QA

Do not re-run Build & Publish for v0.19.1: Latest is already 0.19.1 with
AppImage/dmg/exe. Confirm the next promote's publish job logs `Published
vX.Y.Z -> https://github.com/dripnex/app/releases/tag/vX.Y.Z` instead of
`release not found`.
<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-7ed11e95-3857-4f12-bd9c-e1fd773d4ba5?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-7ed11e95-3857-4f12-bd9c-e1fd773d4ba5&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Bug Fixes**
  - Improved automated release publishing reliability.
- Existing draft releases are now identified and published more
consistently.
  - Added retry handling for temporary release lookup delays.
- The workflow now reports a clear failure when no matching release can
be found.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary

`sync-develop` was skipped when Build & Publish failed to undraft
v0.19.1. `main` (`e8bea28`, tag v0.19.1) is not an ancestor of
`develop`, so the next promote would sit at **BEHIND**.

This PR merge-commits `main` into `develop`. **Merge commit only. Do not
squash.** A squash replays the content as a new commit and does not
establish ancestry.

## Type of Change

- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [x] Documentation update

Not a product change — topology only (`chore(release): merge main into
develop`).

## Related Issues

Follow-up after v0.19.1 publish. PR #607 (publish-by-id) is already on
develop.

## Checklist

- [x] I've read [CONTRIBUTING.md](../CONTRIBUTING.md)
- [ ] Tests pass locally (`pnpm test`) — no code changes
- [ ] Build succeeds (`pnpm build`) — no code changes
- [x] PR targets `develop` branch (not `main`)

## Merge instructions

Use a **merge commit** (`gh pr merge --merge`). Do not squash. After
merge, `git merge-base --is-ancestor e8bea28 origin/develop` must be
true.
<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-7ed11e95-3857-4f12-bd9c-e1fd773d4ba5?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-7ed11e95-3857-4f12-bd9c-e1fd773d4ba5&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary

#608 was squash-merged by auto-merge, so `e8bea28` (`v0.19.1`) is still
**not** an ancestor of `develop`. This PR is a real merge commit
(`eaa3405` parents: `cbf0e5b` + `e8bea28`).

**Merge commit only. Do not squash.** Squashing this PR would fail the
same way #608 did.

## Type of Change

- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [x] Documentation update

Topology only. No product or `package.json` changes.

## Checklist

- [x] I've read [CONTRIBUTING.md](../CONTRIBUTING.md)
- [ ] Tests pass locally (`pnpm test`) — no code changes
- [ ] Build succeeds (`pnpm build`) — no code changes
- [x] PR targets `develop` branch (not `main`)

## Merge instructions

`gh pr merge --merge` (merge commit). After merge, `git merge-base
--is-ancestor e8bea28 origin/develop` must be true.
<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-7ed11e95-3857-4f12-bd9c-e1fd773d4ba5?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-7ed11e95-3857-4f12-bd9c-e1fd773d4ba5&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary

Release back-merges must be **merge commits** so `main` becomes an
ancestor of `develop`. Auto-merge only skipped `chore/backmerge-*`.
Cloud Agent branches have to use `cursor/`, so #608 and #609 were
squash-merged and `e8bea28` (`v0.19.1`) is still missing from `develop`.

Skip `cursor/backmerge-*` the same way.

## Type of Change

- [x] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update

## Checklist

- [x] I've read [CONTRIBUTING.md](../CONTRIBUTING.md)
- [ ] Tests pass locally (`pnpm test`) — workflow YAML only
- [ ] Build succeeds (`pnpm build`) — not required
- [x] PR targets `develop` branch (not `main`)

Squash-merge is correct for this PR.
<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-7ed11e95-3857-4f12-bd9c-e1fd773d4ba5?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-7ed11e95-3857-4f12-bd9c-e1fd773d4ba5&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by:  Tomás Maritano <tomymaritano@gmail.com>
Back-merge of v0.19.1 so main stays an ancestor of develop and the next promotion PR is not stuck at BEHIND.

Merge commit only. Do not squash.
)

<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary

QA 0.19.1 Browse listed 21 cards (Vim → Sakura, Stamp last) while `curl
GET https://api.dripnex.app/plugins` on the same box returned 30
including limestone. That 21-card order is the API **seed** with `stamp`
already in Turso (`mergeBySlug` appends the DB row), not
`COMMUNITY_CATALOG` (18 items, Stamp 4th, no Dune). Electron rendered
the isolate it hit; another isolate had a complete GitHub scan.

This PR:

1. **API:** Prefer one GraphQL org query over N+1 `releases/latest`.
Store a complete list in the Cloudflare Cache API (shared across
isolates) so a cold isolate does not fall back to the 21-row seed. `GET
/plugins` sends `Cache-Control: private, no-store`. Incomplete scans
still never cache as success.
2. **Desktop Browse:** Map every `GET /plugins` row (no slug allowlist).
Query both registry hosts and keep the longest list so a seed isolate
cannot hide limestone. Install from the catalog `bundleUrl` when
present.
3. **Other package:** `dripnex/theme-*` and `dripnex/plugin-*` resolve
via `GET /plugins/:slug` (Worker `bundleUrl`). Direct GitHub tarball
URLs still work. Third-party `owner/repo` still uses GitHub API.
4. **First-party slug squat (security):** `POST /plugins` cannot claim
reserved official slugs (`theme-*`, `plugin-*`, seed plugins). List and
detail ignore Turso rows for those slugs. Desktop Install only follows
`https://github.com/dripnex/{theme|plugin}-*/releases/download/...` for
first-party packs.
5. **Official-looking community row (security):** `POST /plugins` cannot
set `repositoryUrl` to a dripnex `theme-*` / `plugin-*` repo (GitHub
owner/repo compared case-insensitively) or `bundleUrl` to an official
tarball. List/detail hide those rows. Browse drops a non-reserved slug
whose GitHub link is a dripnex pack, so Install cannot show
`dripnex/theme-limestone` while downloading an attacker archive.

Does not add palettes to `OFFICIAL_THEMES` (stays empty). Does not
expand `FIRST_PARTY_PACKAGES`. No desktop version bump.

## Type of Change

- [x] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update

## Related Issues

QA 0.19.1 AppImage Browse extras missing while live `GET /plugins` is
30.

Cursor Security Reviewer: HIGH slug squat on `4a4e7d2`; MEDIUM
official-looking community `bundleUrl` on `84bba8b`; MEDIUM mixed-case
`Theme-*` repo bypass on `bb6ba74`.

## Checklist

- [x] I've read [CONTRIBUTING.md](../CONTRIBUTING.md)
- [x] Tests pass locally (`pnpm --filter @dripnex/api test --
tests/plugins.test.ts` — 42 passed; desktop catalog/install/first-party
tests — 45 passed)
- [x] API + desktop typecheck passed
- [x] PR targets `develop` branch (not `main`)

## QA test plan

**API (fixes 0.19.1 Browse without a new AppImage)** after deploy to
production (`workflow_dispatch` on Deploy API from this branch/develop —
the workflow does not run on `develop` push):

- `GET https://api.dripnex.app/plugins` includes `theme-limestone`,
`theme-walnut`, `theme-ash` (`total` ≥ 30).
- Restart the 0.19.1 AppImage (same or fresh data dir) → Plugins →
Install should list extras.
- `POST /plugins` with slug `theme-limestone` (authenticated) returns
403.
- `POST /plugins` with slug `limestone` and `repositoryUrl`
`https://github.com/dripnex/theme-limestone` returns 403.
- `POST /plugins` with slug `limestone-case` and `repositoryUrl`
`https://github.com/dripnex/Theme-limestone` returns 403.

**Desktop (next AppImage):** Other package `dripnex/theme-limestone`
installs via the Worker, not `GitHub returned 403`. Direct tarball URL
still works. A community card cannot display a dripnex pack repo (any
casing) while Install follows a foreign `bundleUrl`.

Do not promote develop → main for this. Deploy API independently via
`workflow_dispatch`.

<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-521939b4-d6e4-47c6-8603-e211de72b48e?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-521939b4-d6e4-47c6-8603-e211de72b48e&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Improved plugin discovery with broader, more reliable catalog results.
* Added support for trusted direct bundle installation from the plugin
browser.
  * Added automatic discovery of first-party packs and themes.

* **Security**
  * Prevented impersonation of official packs and themes.
  * Blocked untrusted or malicious download URLs.
* Reserved official names are now protected from community listings and
publishing.

* **Reliability**
  * Added fallback handling and caching for plugin catalog discovery.
* Improved resilience when registry or GitHub services are unavailable.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary

Adds a `workflow_dispatch`-only workflow that copies repo secret
`GH_TOKEN` onto the production Cloudflare Worker as `GITHUB_TOKEN`.
Tomás authorized reusing that repo secret for this purpose.

The job:
- Uses Node 22 (`actions/setup-node` pinned to tag `v5` SHA
`a0853c24544627f65ddf259abe73b1d18a591444`)
- Authenticates wrangler with existing `CLOUDFLARE_API_TOKEN` and
`CLOUDFLARE_ACCOUNT_ID` (step-scoped)
- Reads `TOKEN` from `secrets.GH_TOKEN` on the steps that need it (never
echoed; GitHub masks it)
- Fails if `TOKEN` is empty
- Pipes via `printf '%s' "$TOKEN" | npx wrangler@4.98.0 secret put
GITHUB_TOKEN --name readied-api-production`
- Sets `permissions: contents: read` only
- Serializes overlapping runs with `concurrency.group:
sync-worker-github-token` and `cancel-in-progress: false`

Production script name is `readied-api-production`
(`packages/api/wrangler.toml` `env.production`). This does not deploy,
promote, bump versions, or tag.

After this PR merges to `develop` (default branch), run it from the
browser: **Actions → Sync Worker GitHub Token → Run workflow**.

## Type of Change

- [ ] Bug fix
- [x] New feature
- [ ] Breaking change
- [ ] Documentation update

## Related Issues

N/A — ops follow-up for Browse first-party GitHub token on the
production Worker.

## Checklist

- [x] I've read [CONTRIBUTING.md](../CONTRIBUTING.md)
- [ ] Tests pass locally (`pnpm test`) — YAML-only change; no app tests
- [ ] Build succeeds (`pnpm build`) — not applicable
- [x] PR targets `develop` branch (not `main`)

## Screenshots

N/A

<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-67dab42a-0c1c-4189-aa3c-ff541e710cb4?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-67dab42a-0c1c-4189-aa3c-ff541e710cb4&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Added a manually triggered workflow to securely synchronize the GitHub
access token with the production service.
* Added validation to ensure the required token and deployment
credentials are available before synchronization.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary

Production `GET /plugins` stayed on the 21-row seed after `GITHUB_TOKEN`
was set because GraphQL `403`/`429` was treated as an incomplete scan
and returned immediately via `rememberFailure` without trying REST.

Fine-grained / limited PATs often 403 GraphQL `organization {
repositories }` while REST `GET /orgs/dripnex/repos` + `releases/latest`
still work (also observed unauthenticated GraphQL 403 with REST 200).

`discoverDripnexPacks` now calls `discoverViaRest` when GraphQL is
`incomplete` **or** `unavailable`:

- GraphQL `ok` still short-circuits (no REST)
- REST `ok` → `rememberSuccess` (live extras)
- REST incomplete/unavailable → existing `rememberFailure` (last-good
Cache API / memory, else null → seed)

Incomplete GraphQL 403 is never written as a successful last-good list.

## Type of Change

- [x] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update

## Related Issues

Fixes Browse live extras remaining at seed total 21 after Worker
`GITHUB_TOKEN` sync (Actions run 32901545847).

## Checklist

- [x] I've read [CONTRIBUTING.md](../CONTRIBUTING.md)
- [x] Tests pass locally (`pnpm --filter @dripnex/api exec vitest run
tests/plugins.test.ts` — 50 passed)
- [ ] Build succeeds (`pnpm build`)
- [x] PR targets `develop` branch (not `main`)

No desktop changes. No `OFFICIAL_THEMES` edits. No version bump, tag, or
deploy dispatch.

<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-58891f62-5eab-450c-9585-87f62b29431d?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-58891f62-5eab-450c-9585-87f62b29431d&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown

Review Change Stack

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9c56b323-5b1f-448b-8b71-90b7bb3c6994

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary

Settings → Themes only showed Default after Browse-installing satellite
packs (`dripnex/theme-dune`, limestone, walnut, ash, …). Those packs
ship `manifest.json` + `dist/index.js` and call `registerTheme()` in
`activate()` — they do not ship `theme.json`. Settings has no
PluginHost, so `activate()` never ran there and `parseInstalledThemes`
only read `scan().themes` (always `[]`).

This harvests `registerTheme` from scanned plugin source in the renderer
(including Settings) so installed packs appear in the picker and
selecting one sets `activeThemeId`. `OFFICIAL_THEMES` stays empty;
Default (`tokens.css`) stays first; retired bundled `dripnex-*` ids
still fall back to Default.

## Type of Change

- [x] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update

## Related Issues

Follow-up to #604 (empty official palettes). Theme.json on satellites is
a later pack-contract change, not this PR.

## Checklist

- [x] I've read [CONTRIBUTING.md](../CONTRIBUTING.md)
- [x] Tests pass locally (`pnpm test`)
- [ ] Build succeeds (`pnpm build`)
- [x] PR targets `develop` branch (not `main`)

## What changed

- `parseInstalledThemes` still prefers `theme.json` when present.
- If `scan().themes` is empty, load `dist/index.js` and collect palettes
from `context.registerTheme` via a stub PluginContext (no Settings
PluginHost).
- Malformed `theme.json` / throwing `activate()` skips that pack and
does not crash the picker.
- Picker order is Default (id `null`) then harvested palettes.

## Tests

- JS-registered pack (`themes: []`, `registerTheme` in `activate`)
appears; selecting it sets `activeThemeId` to `dripnex-dune`.
- Default remains first (`themePickerIds`).
- Empty `OFFICIAL_THEMES`, retired-id fallback, missing/malformed
`theme.json` do not crash.
- Disabled packs are skipped; `theme.json` still wins when both exist.

## Screenshots

N/A — desktop Settings picker; covered by unit tests that replay the QA
scan shape.
<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-b1ff19c4-64b6-4c04-9831-43072ee62099?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-b1ff19c4-64b6-4c04-9831-43072ee62099&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
@tomymaritano
tomymaritano enabled auto-merge August 26, 2026 01:59
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
## Summary

Settings → Themes now has **In use** and **Available palettes**. Click
Install on Limestone (or any `category === "theme"` pack) to download
the GitHub release tarball, move the card to In use, and activate it —
without leaving Themes. Other package stays on Plugins → Install.

Continues #616 (JS `registerTheme` harvest already on develop).
`OFFICIAL_THEMES` stays `[]`.

## Type of Change

- [x] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update

## Related Issues

Follow-up to #616 / #604. Theme.json on satellites is still a later
pack-contract change.

## Checklist

- [x] I've read [CONTRIBUTING.md](../CONTRIBUTING.md)
- [x] Tests pass locally (`pnpm test`)
- [ ] Build succeeds (`pnpm build`)
- [x] PR targets `develop` branch (not `main`)

## What changed

- **In use:** Default (`tokens.css`) first, then installed packs
(including JS `registerTheme` palettes). Click selects; selected =
outline.
- **Available palettes:** live GET `/plugins` rows with `category ===
"theme"` that are not installed. Heading + hint. Card is name,
one-liner, `v{version}`, primary Install. No fake preview. No Plugins
redirect.
- Install always uses registry `bundleUrl` via `installFromUrl`. Never
api.github.com git/contents.
- Success: `{Name} installed.` + `requestReload` /
`dripnex:plugins:refresh` + activate. Fail: `Couldn't install {Name}.
Use Plugins → Install → Other package if this keeps failing.` Card stays
Available.
- Catalog fail: inline `Couldn't load palettes.` + Retry; fallback
`COMMUNITY_CATALOG` now includes extras past Fog (Sakura, Limestone,
Walnut, Ash, Quartz, Cove, Velvet, Ink, Pine, Saffron, Dune, Noir).

## Tests

- Default first; JS-registered pack appears in In use and leaves
Available.
- Available lists uninstalled theme-category rows.
- Install target is the GitHub release `bundleUrl`.
- Fallback catalog includes extras past Fog.

## Screenshots

N/A — desktop Settings; covered by unit tests.
<!-- CURSOR_AGENT_PR_BODY_END -->

<div><a
href="https://cursor.com/agents/bc-b1ff19c4-64b6-4c04-9831-43072ee62099?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-web-light.png"><img
alt="Open in Web" width="114" height="28"
src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a
href="https://cursor.com/background-agent?bcId=bc-b1ff19c4-64b6-4c04-9831-43072ee62099&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source
media="(prefers-color-scheme: light)"
srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img
alt="Open in Cursor" width="131" height="28"
src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div>

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
@tomymaritano

Copy link
Copy Markdown
Collaborator Author

Updated scope after #616 + #617 landed on develop:

develop is now at 4556de3. CI is re-running on this updated head. Merge commit only; do not squash.

@tomymaritano
tomymaritano merged commit 615619a into main Aug 26, 2026
17 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 0.19.2 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants