From 979f593eb7b3399f504a3b2bf42d1bed1537e3b3 Mon Sep 17 00:00:00 2001 From: KeyInfo Bot Date: Fri, 26 Jun 2026 00:01:19 +0800 Subject: [PATCH] Sync third-party and MCP marketplace plugins Constraint: Public skills are published only by explicit administrator action unless they are tracked third-party market sources. Confidence: high Scope-risk: narrow Directive: Keep private/internal skills out of the public marketplace and preserve normal incremental market Git history. Tested: Marketplace validation passed. --- .agents/plugins/marketplace.json | 24 +-- config/external-sources.lock.json | 20 +- .../codex/.agents/plugins/marketplace.json | 24 +-- .../plugins/mcp-playwright/MCP_SOURCE.json | 2 +- .../next-skills/THIRD_PARTY_SOURCE.json | 4 +- .../next-cache-components-adoption/SKILL.md | 185 ++++++++++++------ .../oh-my-codex/.codex-plugin/plugin.json | 2 +- .../oh-my-codex/THIRD_PARTY_SOURCE.json | 4 +- .../ppt-master/THIRD_PARTY_SOURCE.json | 4 +- .../scripts/svg_finalize/flatten_tspan.py | 20 +- .../scripts/svg_to_pptx/drawingml_elements.py | 22 ++- .../plugins/shadcn/THIRD_PARTY_SOURCE.json | 4 +- plugins/codex/plugins/ui-ux-pro-max/README.md | 18 +- .../ui-ux-pro-max/THIRD_PARTY_SOURCE.json | 4 +- .../ui-ux-pro-max/scripts/design_system.py | 13 +- 15 files changed, 223 insertions(+), 127 deletions(-) diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json index e600a7759..ecb81dc9a 100644 --- a/.agents/plugins/marketplace.json +++ b/.agents/plugins/marketplace.json @@ -208,18 +208,6 @@ }, "category": "开发工具" }, - { - "name": "oh-my-codex", - "source": { - "source": "local", - "path": "./plugins/codex/plugins/oh-my-codex" - }, - "policy": { - "installation": "AVAILABLE", - "authentication": "ON_INSTALL" - }, - "category": "开发工具" - }, { "name": "frontend-slides", "source": { @@ -268,6 +256,18 @@ }, "category": "知识库与检索" }, + { + "name": "oh-my-codex", + "source": { + "source": "local", + "path": "./plugins/codex/plugins/oh-my-codex" + }, + "policy": { + "installation": "AVAILABLE", + "authentication": "ON_INSTALL" + }, + "category": "开发工具" + }, { "name": "ui-ux-pro-max", "source": { diff --git a/config/external-sources.lock.json b/config/external-sources.lock.json index 569bd1fd3..de1f232e3 100644 --- a/config/external-sources.lock.json +++ b/config/external-sources.lock.json @@ -15,8 +15,8 @@ "repo": "https://github.com/Yeachan-Heo/oh-my-codex.git", "ref": "main", "adapter": "codex-plugin", - "commit": "4dde22a58a87ada9d86d26981bf58eeb55a42bc7", - "syncedAt": "2026-06-21T16:00:01Z" + "commit": "e9e3bcc720d964d3673cadb8136394ac103cc091", + "syncedAt": "2026-06-25T16:00:00Z" }, { "id": "ui-ux-pro-max", @@ -24,8 +24,8 @@ "repo": "https://github.com/nextlevelbuilder/ui-ux-pro-max-skill.git", "ref": "main", "adapter": "claude-skill", - "commit": "bdf1179bcf641cca49ee7a5f76df14c3015fd38c", - "syncedAt": "2026-06-24T15:59:59Z" + "commit": "318e0b2e4069b578c729228455328a1ca88f640d", + "syncedAt": "2026-06-25T16:00:00Z" }, { "id": "shadcn", @@ -33,8 +33,8 @@ "repo": "https://github.com/shadcn-ui/ui.git", "ref": "main", "adapter": "claude-skill", - "commit": "549852bffcad7718b92bf40ea44b94a4e627511a", - "syncedAt": "2026-06-24T15:59:59Z" + "commit": "35983528c233250b990f6172f1a60df228409a37", + "syncedAt": "2026-06-25T16:00:00Z" }, { "id": "frontend-slides", @@ -69,8 +69,8 @@ "repo": "https://github.com/hugohe3/ppt-master.git", "ref": "main", "adapter": "claude-skill", - "commit": "7647212fabf12d16c2e90525d0f3f6229ec058a3", - "syncedAt": "2026-06-24T15:59:59Z" + "commit": "850ad1be2474f5d8930fa2b61105453b99391600", + "syncedAt": "2026-06-25T16:00:00Z" }, { "id": "next-skills", @@ -78,8 +78,8 @@ "repo": "https://github.com/vercel/next.js.git", "ref": "canary", "adapter": "skill-collection", - "commit": "72c26d1442602c9ab000354b7addb63841884a91", - "syncedAt": "2026-06-24T15:59:59Z" + "commit": "b0dde9cf271e07b2380575be766ef8f5e451e857", + "syncedAt": "2026-06-25T16:00:00Z" } ] } diff --git a/plugins/codex/.agents/plugins/marketplace.json b/plugins/codex/.agents/plugins/marketplace.json index 31753e2c7..104bc479a 100644 --- a/plugins/codex/.agents/plugins/marketplace.json +++ b/plugins/codex/.agents/plugins/marketplace.json @@ -208,18 +208,6 @@ }, "category": "开发工具" }, - { - "name": "oh-my-codex", - "source": { - "source": "local", - "path": "./plugins/oh-my-codex" - }, - "policy": { - "installation": "AVAILABLE", - "authentication": "ON_INSTALL" - }, - "category": "开发工具" - }, { "name": "frontend-slides", "source": { @@ -268,6 +256,18 @@ }, "category": "知识库与检索" }, + { + "name": "oh-my-codex", + "source": { + "source": "local", + "path": "./plugins/oh-my-codex" + }, + "policy": { + "installation": "AVAILABLE", + "authentication": "ON_INSTALL" + }, + "category": "开发工具" + }, { "name": "ui-ux-pro-max", "source": { diff --git a/plugins/codex/plugins/mcp-playwright/MCP_SOURCE.json b/plugins/codex/plugins/mcp-playwright/MCP_SOURCE.json index d69998f4e..ef7e3b50e 100644 --- a/plugins/codex/plugins/mcp-playwright/MCP_SOURCE.json +++ b/plugins/codex/plugins/mcp-playwright/MCP_SOURCE.json @@ -3,5 +3,5 @@ "name": "playwright浏览器自动化操作", "version": "20260605", "keySource": "none", - "syncedAt": "2026-06-24T16:01:19Z" + "syncedAt": "2026-06-25T16:01:19Z" } diff --git a/plugins/codex/plugins/next-skills/THIRD_PARTY_SOURCE.json b/plugins/codex/plugins/next-skills/THIRD_PARTY_SOURCE.json index 3e3b1f694..48198e025 100644 --- a/plugins/codex/plugins/next-skills/THIRD_PARTY_SOURCE.json +++ b/plugins/codex/plugins/next-skills/THIRD_PARTY_SOURCE.json @@ -2,8 +2,8 @@ "sourceId": "next-skills", "repo": "https://github.com/vercel/next.js.git", "ref": "canary", - "commit": "72c26d1442602c9ab000354b7addb63841884a91", + "commit": "b0dde9cf271e07b2380575be766ef8f5e451e857", "adapter": "skill-collection", "sourcePath": "skills", - "syncedAt": "2026-06-24T15:59:59Z" + "syncedAt": "2026-06-25T16:00:00Z" } diff --git a/plugins/codex/plugins/next-skills/skills/next-cache-components-adoption/SKILL.md b/plugins/codex/plugins/next-skills/skills/next-cache-components-adoption/SKILL.md index 2000368d9..b97291075 100644 --- a/plugins/codex/plugins/next-skills/skills/next-cache-components-adoption/SKILL.md +++ b/plugins/codex/plugins/next-skills/skills/next-cache-components-adoption/SKILL.md @@ -5,85 +5,106 @@ description: "启用 Next.js Cache Components 并修复阻塞路由。" # next-cache-components-adoption -Enable Cache Components on an app and walk it to a clean build. This skill **sequences** the work; per-error recipes live in the dev overlay fix cards, stack traces, and `/docs/messages/blocking-prerender-*` pages. +Enable Cache Components on an app and walk it to a passing build. This skill sequences the work; per-error recipes live in the dev overlay fix cards and the build's terminal output. The [migrating to Cache Components guide](https://nextjs.org/docs/app/guides/migrating-to-cache-components) is the canonical reference for the concepts and per-API recipes this skill applies — consult it whenever the skill steps reference a pattern (`"use cache"`, `cacheLife`, `` placement, etc.) and you want the full explanation. ## requires -Confirm each item before starting milestone A. The skill won't apply cleanly if any are unmet. - - **App Router project.** Cache Components is an App Router feature; `cacheComponents: true` does nothing for `pages/` routes. If the project has a `pages/` or `src/pages/` tree but no `app/` or `src/app/` tree, stop and tell the user — Pages → App migration is its own project, not part of this skill. A hybrid app (both `pages/` and `app/`) is fine: the flag affects the `app/` routes; `pages/` routes are unaffected and don't need opt-outs. - **Next.js 16.3 or later.** That release is where the pieces this skill relies on land: top-level `cacheComponents`, `export const instant`, the dev-overlay instant-navigation validation warnings, and the `cache-components-instant-false` codemod. If `next --version` reports below 16.3, upgrade first: - `npx @next/codemod@latest upgrade latest` to apply the version-to-version codemods. - Read the relevant [version upgrade guide](https://nextjs.org/docs/app/guides/upgrading) (e.g. [Version 16](https://nextjs.org/docs/app/guides/upgrading/version-16)) for what the codemod doesn't cover. -- **No incompatible config keys.** `cacheComponents: true` errors on any file that still exports `dynamic`, `revalidate`, or `fetchCache`. That covers pages and layouts, route handlers (`route.ts`), and metadata routes (`opengraph-image`, `icon`, `apple-icon`, `sitemap`, `manifest`, `robots`). The renamed `experimental.dynamicIO` / `experimental.useCache` should also be migrated. Resolve them via the [migration guide's "Enable Cache Components" section](https://nextjs.org/docs/app/guides/migrating-to-cache-components#enable-cache-components) before starting. +- **No incompatible config keys.** `cacheComponents: true` errors on any file that still exports `dynamic`, `revalidate`, or `fetchCache`, and on `experimental.dynamicIO` (renamed). `experimental.useCache` still works as a deprecated alias but should be migrated for clarity. **Translate, don't delete.** Each export encodes behavior the route needs to keep doing; migrate each one to its Cache Components equivalent via the [migration guide's per-key sections](https://nextjs.org/docs/app/guides/migrating-to-cache-components#enable-cache-components). If a value can't be cleanly translated yet, leave a `// TODO: Cache Components adoption — restore revalidate = 3600` comment so the loop picks it up. ### notes -- **No green baseline before the flag.** If the app already uses `"use cache"`, the pre-flag build errors with `please enable the feature flag cacheComponents`. Enabling the flag is the first step of milestone A, not a thing to do _after_ getting green; the green baseline comes from milestone A (blanket the opt-outs in), not from before it. Note this in your starting summary so it doesn't read as a regression. +- **No green baseline before the flag.** If the app already uses `"use cache"`, the pre-flag build errors with `please enable the feature flag cacheComponents`. Enabling the flag is the first thing you do (in Incremental, before the codemod; in Direct, before fixing routes) — not a thing to do _after_ getting green. Note this in your starting summary so it doesn't read as a regression. - **Offline docs.** Offline copies of guide links live under `node_modules/next/dist/docs/`, with the directory layout numbered for ordering (e.g. `node_modules/next/dist/docs/01-app/02-guides/migrating-to-cache-components.md`). The trailing filename matches the slug. If you can't predict the numbered prefix, `find node_modules/next/dist/docs -name '.md'` resolves it. The `/docs/messages/*` error pages are not bundled. If offline docs are missing entirely, run `npx @next/codemod@latest agents-md` to write a version-matched index into `AGENTS.md` / `CLAUDE.md`. ## the shape of the work -Adoption has two milestones. Each is shippable on its own: +There's one loop: walk the route tree top-down, one feature at a time, adopting each route against `next dev` + a browser. The build is a final check for each feature, not the working surface. -- **A. Green build.** `next build` passes with `cacheComponents: true` — blanket `instant = false` if needed. Setup for B. (steps 1–2.) -- **B. Remove `instant = false`.** **This is the loop where adoption happens.** Walk the route tree top-down, one subtree at a time, removing each opt-out and either making the route prerenderable or documenting it as a deliberate Block — checking in with the user at each subtree boundary. Expect to spend most of the time here. (steps 2–3.) +The choice in step 1 is whether to silence the validation errors first or fix them as you go. Either way the loop is the same: -**Adoption is complete after B.** Further optimization — making navigations instant, adopting Partial Prefetching, locking the result in with e2e tests, growing static shells — is covered by the linked guides in [further reading](#further-reading). Point the user at them; this skill doesn't walk through them. +- **With a quiet pre-step (Incremental).** Run the codemod to opt every page and layout out of validation. The build passes immediately, you ship that as its own PR, and then start the loop — removing one opt-out at a time and adopting that route. Picks the work apart into small reviewable PRs. +- **Without (Direct).** Enable `cacheComponents` and start the loop on whatever the build flags first. Same loop, but every fix sits on one branch until adoption is complete. -**End of every milestone: summarize and ask.** Tell the user which routes changed and how (cached / wrapped in `` / opted out as a documented Block), what they should sanity-check, and ask whether to open a PR before continuing. Each milestone is a real checkpoint, not a step inside one agent run. Don't silently roll on. +In both, the per-route success bar is the same: **dev loop reports no errors AND `next build` passes**. Check in with the user after every feature. Expect to spend most of the time in the loop, not in the pre-step. ## background -`cacheComponents: true` requires every route to be prerenderable. A route that reads request-time data outside `` is "blocking" and **fails the build**. `export const instant = false` marks a route as allowed to block, which clears it in both dev and build; on a layout it covers the whole subtree beneath it. +`cacheComponents: true` requires every route to be prerenderable. A route that reads request-time data outside `` is "blocking" and fails the build. `export const instant = false` marks a route as allowed to block, which clears it in both dev and build; on a layout it covers the whole subtree beneath it. Reads wrapped in a [`"use cache"`](https://nextjs.org/docs/app/api-reference/directives/use-cache) function count as cache boundaries, not blocking reads. -**`instant = false` does not clear sync-IO errors.** Unstable values evaluated at module/render time — `new Date()`, `Date.now()`, `Math.random()`, `crypto.randomUUID()` — still fail the prerender (`blocking-prerender-current-time` / `-random` / `-crypto`) even with the opt-out, because they produce a different result on every render and can't be baked into a static shell. So the blanket codemod gets the build green **only if no shared layout or page calls one of these directly**; if one does, you must fix it regardless of `instant = false`. Follow the fix cards on the error page itself — they own the per-API recipe. This most often bites in a shared layout, where one `new Date()` blocks every route under it. +Three classes of blocker bite agents in this order: -## surfacing errors +1. **Request-time reads** (`cookies()`, `headers()`, `await params`, `await searchParams`). All four block when awaited at the top of a page or layout. `params` and `searchParams` often get missed because they're not framed as "request data" the way cookies and headers are. The fix is to push the read into a ``-wrapped child — and for `params`/`searchParams`, forward the promise into the child and await it there; don't `await` at the page top. +2. **Sync-IO at module/render time** (`new Date()`, `Date.now()`, `Math.random()`, `crypto.randomUUID()`). These fail the build even with `instant = false` — the opt-out doesn't suppress them. If they're in a shared layout, they block every route under it. The codemod can't fix them; you have to translate each one (cache it with `"use cache"` if it's stable, or wrap it in `await connection()` + `` if it's per-request) before the build can pass. Grep the whole repo for these calls before running anything else. +3. **`"use cache"` files that read request data.** A file with a top-level `"use cache"` directive can't export `instant`; combining the two errors with `Only async functions are allowed to be exported in a "use cache" file.` and means the directive was wrong for that route. Remove it before running the codemod. -Two surfaces; they show different things. +## working surfaces -**`next build` — detection only.** Use it to confirm milestone A (green build) and to spot-check milestone B (no route opted out). It stops at the first blocking route, so it's poor for sizing the work. Two flags help when iterating: `--debug-build-paths` builds only the routes you name (comma-separated glob patterns of **file paths relative to the project root**, e.g. `--debug-build-paths="app/admin/**/page.tsx"` or `--debug-build-paths="app/(marketing)/about/page.tsx"` — not URL paths; `--debug-build-paths=/admin` matches nothing and silently exits 0) and `--debug-prerender` (dev-only) prints a fuller stack trace so the error names the originating file and line. +### finding blocking routes -**`next dev` — the working surface.** Visit a route; its blocking errors surface in the dev overlay with full stack traces and fix cards linking the per-error docs. Work one route at a time — errors don't accumulate in one place. The route itself still returns HTTP 200, so don't gate on status codes; read the overlay (or `.next-dev.log` if you can't drive a browser yet). +Prefer `next dev` over `next build` while you work. -**Verifying a fix at runtime.** A green build or a cleared overlay isn't proof the route actually behaves — Cache Components is a runtime concern (a static shell with streamed data). Load the route in a real browser, wait for streaming to settle, and confirm it renders. Three ways, in order of preference: +- **`next dev`** — the working surface. Visit a route; its blocking errors surface in the dev overlay with full stack traces and fix cards linking the per-error docs. Work one route at a time — errors don't accumulate in one place. The route itself still returns HTTP 200, so read the overlay (or `.next-dev.log`), not status codes. A cleared overlay is one half of route-clean — the other half is browser verification (see [step 2](#step-2-the-inner-loop-remove-opt-outs-one-feature-at-a-time)) and a passing build for that route. +- **`next build`** — detection only. The build is `next dev`'s authoritative check, not its replacement. Use it as the last gate on each feature in the loop (a passing build is part of the per-route success bar) and as the final verification across the whole app. In Incremental, the build also confirms the pre-step (codemod opted every route out, no shared layout still has a sync-IO blocker) before you ship that PR. Don't reach for the build instead of the dev loop while you're working a route — even when the build surfaces a clean compile error, you still don't know what ended up in the static shell vs streamed; the build's clean error messages are the seductive part. By default the build stops at the first blocking route, so it's also poor for sizing the work. Two flags help when iterating: `--debug-build-paths` builds only the routes you name (comma-separated glob patterns of file paths relative to the project root, e.g. `--debug-build-paths="app/admin/**/page.tsx"` — not URL paths; `--debug-build-paths="app/(marketing)/about/page.tsx"` — not `/about`; `--debug-build-paths="app/admin"` matches nothing and silently builds zero routes), and `--debug-prerender` disables the early exit so the build continues past the first prerender failure, reports every blocking route, and prints a fuller stack trace that names the originating file and line. -1. **The [`next-dev-loop`](https://github.com/vercel/next.js/tree/canary/skills/next-dev-loop) skill** is the fastest path: it cross-checks `/_next/mcp` against the live browser. Install if your agent doesn't have it: +Every blocking error has a docs page — open it. Both the dev overlay and the build terminal print a `https://nextjs.org/docs/messages/` link with each error. That page is the canonical recipe for the fix; the inline message is a summary. Fetch the link for every distinct error you encounter, even if you think you know the pattern — the recipes evolve, and the same error class can have different correct fixes depending on what the route reads. Don't improvise from the inline message alone. (`/docs/messages/*` pages aren't bundled offline; if you have no network, fall back to the per-API guides under `node_modules/next/dist/docs/` and note the limitation when you report back.) + +### verifying each fix at runtime + +A passing build or a cleared overlay isn't proof the route actually behaves — Cache Components is a runtime concern (a static shell with streamed data). Verify after every fix, not only at the end. + +In preference order: + +1. **[`next-dev-loop`](https://github.com/vercel/next.js/tree/canary/skills/next-dev-loop) — strongly preferred.** Cross-checks `/_next/mcp` against the live browser via `agent-browser` and surfaces both compile and runtime issues in one pass. The diagnostics (React tree, suspense boundaries, console + network) are orders of magnitude richer than poking at `next dev` by hand. + + Install it before starting the loop. Don't wait until you hit something `next dev` alone can't explain. Run: ```bash npx skills add https://github.com/vercel/next.js/tree/canary/skills/next-dev-loop ``` - It has its own hard prerequisites (Turbopack and `agent-browser >= 0.27.0`) and will tell you how to set those up. + The skill requires `agent-browser >= 0.27.0` and walks you through it. -2. **A browser you can drive yourself** (Playwright, agent-browser, any browser-automation tool). `next-dev-loop` is an accelerator, not a prerequisite. + **Requires Turbopack.** If `package.json`'s `dev` script passes `--webpack`, flag it to the user and ask whether there's a reason to stay on webpack. If not, switch to Turbopack (the Next.js 16.3+ default). If they want to keep webpack, skip this install and use the [build-only loop](#the-loop-build-only-fallback) instead. -3. **No browser at all?** Ask the user. Either ask them to drive the dev server and report what the overlay shows, or commit the milestone you've reached and hand off. **Don't silently stop at A or B and call it done** — the runtime behavior won't surface in the build. Be explicit about what you couldn't verify. + You don't need permission to install `next-dev-loop` itself. It's a tool, like installing a dev dependency. If a user is on the line, briefly tell them you're installing it for verification. In a non-interactive run (CI, dashboard, sandbox), install it without asking — "can't prompt the user" is not a reason to skip. The only legitimate skip is a real technical blocker: no network, no npm, read-only filesystem, a stated no-new-deps policy, or a webpack-only dev script. If you skip, name the specific blocker in your final report. -Verify after every fix, not only at the end. Don't fall back to grepping source or trusting the build alone. +2. **A browser you can drive yourself.** Playwright, `agent-browser` directly, any browser-automation tool. Use only when `next-dev-loop` is genuinely blocked. You'll miss the framework-side checks (`/_next/mcp`), so DOM assertions alone don't catch every regression — be more cautious about what you call "verified." + +3. **Build-only.** If you can't run a dev server at all, the build is your only signal. `○ (Static)` routes with no `` are fully verified by the build (nothing streamed to test). `◐ (Partial Prerender)` routes are only shell-verified — flag them when you report back. + +4. **No tooling at all.** Ask the user to run the dev server (or build) and report what they see, or commit the milestone you've reached and hand off. ## step 1: choose a strategy -Ask the user; don't assume. **In a non-interactive run** (no way to prompt), default to **Blanket** for a multi-route app and **Direct** for a single-route or handful-of-routes app, and say so when you start. +Ask the user. Phrase it as a PR-shape question, not a sizing call. Never use the internal labels (Incremental, Direct, milestone A) when talking to the user — those are your own scaffolding. Ask in terms of PRs and features, e.g.: _"Do you want me to first open a PR that turns on Cache Components and opts every route out of validation, then handle the actual route adoptions feature-by-feature in follow-up PRs? Or do everything on one branch?"_ Even on a tiny app, the incremental path still has value (review-sized PR, revertible, the `// TODO: Cache Components adoption` markers double as your work queue for next session). Don't pick on their behalf. -- **Blanket** — run the codemod to opt every page and layout out, get a clean build immediately, **merge that**, then remove the opt-outs feature by feature in follow-up PRs. Use for large apps, team repos (a long-lived failing branch blocks others), or when you can't land every route in one PR. -- **Direct** — enable the flag and fix every route in place in one pass. Use for small or solo apps where one PR is realistic. +In a non-interactive run, default to **Incremental** for a multi-route app and **Direct** for a handful-of-routes app, and say so when you start. -### blanket +- **Incremental** — quiet pre-step + the loop. Run the codemod to opt every page and layout out of validation, get the build passing, stop and check in with the user (see [end of the pre-step](#end-of-the-pre-step-check-in)), then enter [step 2's loop](#step-2-the-inner-loop-remove-opt-outs-one-feature-at-a-time) and ship each feature as a follow-up PR. +- **Direct** — skip the pre-step. Enable `cacheComponents` and go straight to [step 2's loop](#step-2-the-inner-loop-remove-opt-outs-one-feature-at-a-time); the build's blocking routes are the work queue. + +### incremental + +Before invoking the codemod, fix the sync-IO blockers it can't. Grep the whole repo for `new Date()`, `Date.now()`, `Math.random()`, and `crypto.randomUUID()` (not only `app/**/layout.{js,jsx,ts,tsx}` — the read might live in any component imported by a layout). Translate each match using the recipe from its `blocking-prerender-*` error card: cache stable values with `"use cache"`; wrap per-request values in `await connection()` + ``. A layout with two distinct reads (e.g. a copyright year and a "last updated" stamp) usually needs two distinct fixes. + +The codemod refuses to run on a dirty working tree. Commit or stash unrelated work first, or pass `--force` to let its edits land alongside your WIP. Common false positive: if you recently upgraded Next.js, `package.json` and the lockfile will already be dirty — commit those first. + +Use the `@canary` channel, not `@latest`. The `cache-components-instant-false` transform isn't in the stable `@next/codemod` release; `@next/codemod@latest` errors with `Invalid transform choice`. ```bash npx @next/codemod@canary cache-components-instant-false ./app ``` -If `@next/codemod@latest` reports `Invalid transform choice`, try `@canary` — new transforms land there first. The codemod refuses to run on a dirty working tree; commit or stash unrelated work first, or pass `--force` to override (the codemod's own edits then land alongside your WIP). +Inserts `export const instant = false` (with a `// TODO: Cache Components adoption` comment) into every `app/**/{page,layout,default}` file, skipping files that already declare `instant` and any module marked `"use client"` or `"use server"`. Then set `cacheComponents: true`. The TODO comments are the work queue for the loop. -Inserts `export const instant = false` (with a `// TODO: Cache Components adoption` comment) into every `app/**/{page,layout,default}` file, skipping files that already declare `instant` and any module marked `"use client"` or `"use server"`. Then set `cacheComponents: true`. The TODO comments are the work queue for milestone B. - -**If the codemod isn't available** (older `@next/codemod`, sandboxed environment, offline run), reproduce it by hand: for every `app/**/{page,layout,default}.{js,jsx,ts,tsx}` that isn't `"use client"` or `"use server"` and doesn't already declare or export `instant` in any form, insert the three-line block below after the file's import statements (or at the top, if there are none): +If the codemod isn't available (older `@next/codemod`, sandboxed environment, offline run), reproduce it by hand: for every `app/**/{page,layout,default}.{js,jsx,ts,tsx}` that isn't `"use client"` or `"use server"` and doesn't already declare `instant`, insert this after the imports: ```ts // TODO: Cache Components adoption. Refactor this route so this opt-out can be removed. @@ -91,62 +112,102 @@ Inserts `export const instant = false` (with a `// TODO: Cache Components adopti export const instant = false ``` -Then set `cacheComponents: true`. The result is the same as what the codemod produces. +The codemod opts every segment out, not only the root, on purpose. Resolution is top-down, first-explicit-config-wins: the highest `instant = false` decides the whole subtree. With an opt-out on every segment, removing one segment's opt-out validates only that segment; descendants keep their own opt-outs and stay green. If only the root were opted out, removing it would re-arm validation for the entire app at once. -The codemod opts **every** segment out, not only the root, on purpose. Resolution is top-down, first-explicit-config-wins: the **highest** `instant = false` in a route's tree decides the whole subtree, and deeper ones are never read. If you only opted the root layout out, removing it would re-arm validation for the entire app at once. With an opt-out on every segment, removing one segment's opt-out validates only **that** segment — its descendants keep their own opt-outs and stay green, so the blast radius is one segment at a time. +Because the highest opt-out wins, remove them top-down (root layout first, then descend). Removing a leaf's opt-out does nothing while an ancestor still holds one. -Because the highest opt-out wins, **remove them top-down** (root first, then descend). Removing a leaf's opt-out does nothing while an ancestor still holds one. +Confirm the pre-step with `next build`. The build is the proof, not the codemod run — a shared layout that calls `new Date()` / `Math.random()` directly still fails regardless of the opt-out (see [background](#background)). -**Confirm milestone A with a build.** Run `next build` and make sure it completes with no blocking-route errors before you call the green build done. The codemod gets you most of the way, but a shared layout that calls `new Date()` / `Math.random()` directly still fails regardless of the opt-out (see "background" above), so the build is the proof, not the codemod run. +After the build passes, confirm the root layout got an opt-out (`grep -n "export const instant" app/layout.*`). The root layout renders every route, including framework routes like `/_not-found`, so if it was missed, add `export const instant = false` to it by hand. -After running the codemod, **confirm the root layout got an opt-out** (`grep -n "export const instant" app/layout.*`). The root layout is the one segment that must be covered: it renders every route, including framework routes like `/_not-found`, so if it still reads `cookies()` without an opt-out the build fails on `/_not-found` even though no other route changed. If it was missed, add `export const instant = false` to it by hand. +Synthetic routes like `/_not-found` have no user file — when they block, fix the root layout's opt-out, not the synthetic route. Client Components (`"use client"`) get no opt-out (it's a build error — `E1344` — to export `instant` from them) and rarely block on their own; when a client route blocks, fix the server-side data in its ancestor layout. -**Never add `instant = false` to a synthetic route** like `/_not-found` — there is no user file for it, and the directive wouldn't apply. When `/_not-found` (or another framework route) blocks, the cause is the **root layout** it renders through; fix the opt-out there. +### end of the pre-step: check in -**Client Components (`"use client"` pages/layouts) get no opt-out** — the codemod skips them on purpose. `instant` is a Server Component route segment config; exporting it from a client module is a build error (`E1344`). They don't need one anyway: a client page is covered by its nearest server layout's opt-out, and a client page can't read server request data (`cookies()`, `headers()`, `await params`) itself, so it rarely blocks on its own. If a route with a client page still blocks, the cause is server-side data in an ancestor layout — fix the opt-out or the read there, not on the client page. +Incremental only. Stop here before starting step 2 — the pre-step is the shippable PR. Talk to the user in their language; don't say "milestone A" or "Incremental"; talk about adoption, PRs, and what the app does now. Tell them: + +- What you did: turned on Cache Components, ran the codemod that opts every page and layout out of the new validation (or did it by hand), fixed any blockers the codemod can't (list them), confirmed the build passes. +- What changed: every page and layout in `app/` now exports `instant = false` with a `// TODO: Cache Components adoption` comment, except client components and any that already had an `instant` export. +- What to sanity-check: the diff is mostly mechanical (new exports + comments). The build passes. Routes still behave exactly as they did before — the opt-outs preserve current behavior; no rendering changes yet. +- The question: "Want to open this as its own PR before we start adopting Cache Components route by route? Or keep going on this branch?" Wait for the answer. + +Moving to step 2 without checking in defeats the point of taking the incremental path. ### direct -Set `cacheComponents: true` and collect the errors. The reported routes are the work queue; there are no opt-outs to remove. +Set `cacheComponents: true` and move to [step 2](#step-2-the-inner-loop-remove-opt-outs-one-feature-at-a-time). The build's blocking routes are the work queue. -## step 2: remove opt-outs, one subtree at a time +## step 2: the inner loop, remove opt-outs one feature at a time -The route tree is the work queue. Pick one subtree (`app/dashboard/**`, or a top-level app if the repo has several — marketing, app, docs), finish it end-to-end, ship it, then start the next. Each subtree is an independent, mergeable change. Don't fan out across the whole app in one pass — the point of milestone A's blanket was to make the loop incremental, not optional. +A "feature" is a single product surface — `app/settings/profile/**`, `app/posts/[slug]/**` — not a whole top-level app like `app/dashboard/**`. Finish one end-to-end before starting the next. -Within a subtree, walk **top-down** (layouts before the pages beneath them, root layout first). The root layout is often the hardest (it wraps `` / `` and frequently reads `cookies()`), but it shadows every route including framework routes like `/_not-found`, so it has to come off before anything below it can be validated. (Direct path: there are no opt-outs to remove — fix each failing route; if a hand-written opt-out on an ancestor shadows it, remove that first.) +Within a feature, walk top-down (layouts before pages, root layout first). Removing a layout's opt-out before its descendants exposes the layout's own blocking reads. (Direct: there are no opt-outs to remove — fix each failing route; if a hand-written opt-out on an ancestor shadows it, remove that first.) -**A green build mid-walk doesn't mean the layout is clean.** Removing a layout's opt-out while its descendant pages still have theirs keeps the build green — each page shadows the inherited validation. The layout's actual blocking reads only surface once nothing below it shadows them. So after a layout is opt-out-free, **keep going** down the subtree; if the layout has an inherent blocker, the first page you uncover will be the one to surface it. Don't call a subtree done at the layout boundary. +A passing build mid-walk doesn't mean the layout is clean. Removing a layout's opt-out while its descendant pages still have theirs keeps the build passing — each page shadows the inherited validation. The layout's actual blocking reads only surface once nothing below it shadows them. Don't call a feature done at the layout boundary. -For each route in the subtree: +Use the **with-a-browser** loop unless a browser is genuinely unreachable. The [`next-dev-loop`](#verifying-each-fix-at-runtime) skill is the source of truth for what counts as "browser available" and how to install it. -1. Remove its `instant = false` (Blanket) or target the failing route (Direct). -2. Reload it in dev or rebuild only that route. If it's clean, the route was already prerenderable — move on. -3. If it still blocks, read the error in the dev overlay and apply the fix it points at. When the call gets ambiguous — you're not sure which fix fits, the blocking code looks security-sensitive, or the user might want to keep the route blocking on purpose — read **[references/per-page-decisions.md](./references/per-page-decisions.md)** before editing. Those cases are user check-in moments, not agent judgment calls. -4. Re-check the route. If your fix touched shared code (a layout, a sidebar component), re-check sibling routes too — a shared-shell change can fix the route you're on and break a sibling. Then move to the next route. +### the loop, with a browser (preferred) -Keep a todo list of the subtree's routes and work it to completion; don't truncate. When every route in the subtree is clean, move to **step 3** to verify and hand the subtree off to the user. +Per route: -## step 3: verify the subtree +- Remove the opt-out (Incremental) or target the failing route (Direct). +- Reload in dev. Overlay clean? Skip to verify. Overlay still red? Fix. +- Fix — fetch the docs page linked from the error (`https://nextjs.org/docs/messages/`), apply the recipe from there. The inline overlay text is a summary; the docs page is the source of truth. +- Verify in the browser. Confirm the visible content on first paint is what you intended in the shell — not stuck on a fallback, not silently streaming everything out of an empty shell. +- Re-check siblings if the fix touched shared code (a layout, a sidebar component). A shared-shell change can fix the route you're on and break a sibling. -A checklist, not new adoption work. This is where the user signs off on the subtree before you start the next. +### the loop, build-only (fallback) + +Used when there's no way to drive a browser — CI, sandbox, the user has no `next dev` running and you can't start one. Weaker signal: confirms the build passes and the route prerenders, but not what ended up in the static shell vs streamed. + +Per route: + +- Remove the opt-out (Incremental) or target the failing route (Direct). +- Rebuild with `--debug-build-paths app//**` (only that route) or `--debug-prerender` (full build, but past the first failure). Route green? Move on. Still blocking? Fix. +- Fix — fetch the docs page linked from the error (`https://nextjs.org/docs/messages/`), apply the recipe from there. +- Re-check siblings if the fix touched shared code. +- Flag the route as build-only-verified when you hand the feature off. Each `◐` route still needs a browser pass before the feature is done. + +### loop notes + +- The [three blocker classes from background](#background) often get missed when fixing in place. Caching a downstream fetch (`getThing(id)`) doesn't clear an `await params` at the top of the page body — push the param promise into the ``-wrapped child. +- Ambiguous calls are user check-ins, not agent judgment. When you're not sure which fix fits, the blocking code looks security-sensitive, or the user might want to keep the route blocking on purpose — read [references/per-page-decisions.md](./references/per-page-decisions.md) before editing. +- Don't narrate the refactor with comments. The only comment the codemod (or you) should leave is `// TODO: Cache Components adoption` on opt-outs, and the user's existing comments. Don't annotate every `` boundary or `"use cache"` call with what it does — the code says that. Drop a comment only when the _why_ isn't clear from the code (e.g. a deliberate Block with a reason). + +Keep a todo list of the feature's routes. When every route in the feature is clean, move to step 3. + +## step 3: verify the feature + +Checklist before checking in with the user: - `next build` completes without blocking-route errors. -- No bare `// TODO: Cache Components adoption` opt-outs are left in the subtree (`grep` to confirm). Any `instant = false` left behind must be a **deliberate, documented Block** — its comment rewritten to a reason (see [references/per-page-decisions.md](./references/per-page-decisions.md) → "when to leave a Block in place"), not the original `// TODO`. -- Drive each route in dev, not only the build. Visit it, wait for streaming to settle, confirm every `` fallback resolves to its real content (not stuck on a skeleton or a blank). A green build with zero opt-outs is not the same as a working route. Query the live DOM if a tool's snapshot looks stale before reporting a route as broken. -- **Show the user the rendered result.** A screenshot or the visible content you observed, per route. The build can't tell whether the streamed-in loading state, the fallback, or the final layout matches what the user wants. Adoption changes the _experience_, so the person who owns the product should sign off on each piece. +- No bare `// TODO: Cache Components adoption` opt-outs in the feature (`grep` to confirm). Any `instant = false` left behind is a deliberate, documented Block — comment rewritten to a reason (see [references/per-page-decisions.md](./references/per-page-decisions.md) → "when to leave a Block in place"). +- Each route visited in the browser: confirm the static shell renders first and every `` fallback resolves to its real content. Capture both states if you can — the fallback (mid-stream) and the final paint — so you have a streaming-experience demo to show the user. Throttle the network in the browser if streaming is too fast to observe. -**Expect some routes to still print `ƒ` (Dynamic) in the build's route table — that is success, not a regression.** A route comes out `ƒ` when it does request-time work through the documented escape hatch (e.g. a layout that `await connection()` for `new Date()`); the page is no longer _opted out_, it is genuinely dynamic. Don't rip the escape hatch back out chasing a `◐`. The inverse also holds: `instant = false` does **not** force a route to be `ƒ`. The glyph reflects what the route does at prerender time, not which validation knobs it exports. +Then check in with the user. Same rule as the pre-step: speak their language. Don't say "milestone B" or "feature‑by‑feature loop"; talk about the feature you adopted and what the user will see. -When the subtree passes and the user is happy with each route, **summarize and ask**: open a PR and move to the next subtree, or stop here? +- What you did: which routes you touched, and the user-visible result per route (e.g. "the post page now streams the article body behind a skeleton while the layout stays static"). +- What changed: opt-outs removed, fallbacks added, caching boundaries introduced. +- Show, don't tell. If the browser is running, drive the route live for the user so they see the static shell → fallback → final content sequence in real time. If you can't drive a live browser, attach the before/after screenshots you captured instead. +- The question: "Want to open this feature as a PR and move on to the next, or stop here?" Wait for the answer. -Milestone B is done only when **every** subtree is clean — every remaining `instant = false` sits under a reason comment, no bare TODOs are left (`grep -rln "TODO: Cache Components adoption" app` returns nothing). **Adoption is complete here.** Point the user at [further reading](#further-reading) if they want to push the experience further, or stop and ship. +**Trivial features can skip the check-in.** If adopting a feature only meant removing its `// TODO: Cache Components adoption` opt-out (no `` added, no `'use cache'` introduced, no render order change), the user sees nothing different. Move on to the next feature without stopping; mention it in passing the next time you do check in. + +When the loop has run on every feature — every remaining `instant = false` sits under a reason comment, `grep -rln "TODO: Cache Components adoption" app` returns nothing — point the user at [further reading](#further-reading) if they want to push the experience further, or stop and ship. + +### route table glyphs + +`ƒ` → `◐` is the adoption landing. `◐ (Partial Prerender)` means a static shell prerenders and the request-time content streams in — the goal state for any route that reads `cookies()`, `headers()`, `params`, or `searchParams`. Some routes legitimately stay `ƒ` when they do request-time work through a documented escape hatch (e.g. a layout that uses `await connection()`); the page is no longer _opted out_, it's genuinely dynamic. Don't rip the escape hatch back out chasing a `◐`. The inverse holds: `instant = false` does not force a route to be `ƒ`. The glyph reflects what the route does at prerender time, not which validation knobs it exports. + +`◐` tells you a shell exists, not what's in it. A `` boundary placed too high (e.g. wrapping the entire page body, or `` around the article content) pushes the visible content out of the static shell into the streamed payload; the build still reports `◐` because _some_ shell prerendered (often only `` with framework markup). The route table can't tell you what's in the shell; a browser can. If the shell is empty and everything streams, pull the `` boundary down closer to the actual dynamic read. ## further reading -Adoption ends at milestone B. The work below is optional and lives in the docs — link the user to them and let them decide which to take on next. Don't walk these through inside this skill. +The work below is optional and lives in the docs — link the user to them and let them decide which to take on next. Don't walk these through inside this skill. -- **[Instant navigation](https://nextjs.org/docs/app/guides/instant-navigation)** — dev-only validation warnings the overlay raises on client navigation. Same shape as the blocking-prerender errors you cleared in step 2; the guide covers the per-warning details. Recommend it next if the user wants navigations to actually be instant (a green build doesn't guarantee that — a `` above the shared layout caught the page-load case but doesn't cover client navigation). -- **[Adopting Partial Prefetching](https://nextjs.org/docs/app/guides/adopting-partial-prefetching)** — walks an audit of `` calls driven by the dev overlay's `link-prefetch-partial` warning, then flips the `partialPrefetching` config. **Walk the audit first, with the flag off** — flipping it before the audit makes every route count as adopted, so the warnings never fire and the per-link signal is lost. The biggest payoff of Cache Components: `` prefetches only the static App Shell by default. Recommended after instant navigation, since its fixes feed directly into how much of each route the shell can prefetch. -- **[Prefetching](https://nextjs.org/docs/app/guides/prefetching)** and **[Runtime prefetching](https://nextjs.org/docs/app/guides/runtime-prefetching)** — broader prefetching reference. Runtime prefetching extends the static shell with per-session content; reach for it when a route's shell is too thin to be useful and Partial Prefetching alone doesn't cover the gap. -- **[Locking the result in with e2e tests](https://nextjs.org/docs/app/guides/instant-navigation#prevent-regressions-with-e2e-tests)** — the `@next/playwright` [`instant()`](https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config/instant#testing-instant-navigation) helper asserts on the UI that's available immediately on navigation, so regressions surface in CI. Recommend it once a route is instant: `next-dev-loop` confirms it _now_; an `instant()` test keeps it that way. -- **[`next-cache-components-optimizer`](https://github.com/vercel/next.js/tree/canary/skills/next-cache-components-optimizer)** — a separate skill that grows each route's static shell so more of the page prerenders and less streams in. Pure optimization, not part of adoption. +- [Instant navigation](https://nextjs.org/docs/app/guides/instant-navigation) — dev-only validation warnings the overlay raises on client navigation. Same shape as the blocking-prerender errors you cleared in step 2; the guide covers the per-warning details. Recommend it next if the user wants navigations to actually be instant (a passing build doesn't guarantee that — a `` above the shared layout caught the page-load case but doesn't cover client navigation). +- [Adopting Partial Prefetching](https://nextjs.org/docs/app/guides/adopting-partial-prefetching) — walks an audit of `` calls driven by the dev overlay's `link-prefetch-partial` warning, then flips the `partialPrefetching` config. Walk the audit first, with the flag off — flipping it before the audit makes every route count as adopted, so the warnings never fire and the per-link signal is lost. The biggest payoff of Cache Components: `` prefetches only the static App Shell by default. Recommended after instant navigation, since its fixes feed directly into how much of each route the shell can prefetch. +- [Prefetching](https://nextjs.org/docs/app/guides/prefetching) and [Runtime prefetching](https://nextjs.org/docs/app/guides/runtime-prefetching) — broader prefetching reference. Runtime prefetching extends the static shell with per-session content; reach for it when a route's shell is too thin to be useful and Partial Prefetching alone doesn't cover the gap. +- [Locking the result in with e2e tests](https://nextjs.org/docs/app/guides/instant-navigation#prevent-regressions-with-e2e-tests) — the `@next/playwright` [`instant()`](https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config/instant#testing-instant-navigation) helper asserts on the UI that's available immediately on navigation, so regressions surface in CI. Recommend it once a route is instant: `next-dev-loop` confirms it _now_; an `instant()` test keeps it that way. +- [`next-cache-components-optimizer`](https://github.com/vercel/next.js/tree/canary/skills/next-cache-components-optimizer) — a separate skill that grows each route's static shell so more of the page prerenders and less streams in. Pure optimization, not part of adoption. diff --git a/plugins/codex/plugins/oh-my-codex/.codex-plugin/plugin.json b/plugins/codex/plugins/oh-my-codex/.codex-plugin/plugin.json index d08c455fb..fb6654ac5 100644 --- a/plugins/codex/plugins/oh-my-codex/.codex-plugin/plugin.json +++ b/plugins/codex/plugins/oh-my-codex/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "oh-my-codex", - "version": "0.18.14", + "version": "0.18.15", "description": "oh-my-codex 是 Codex CLI 的多 Agent 编排、结构化工作流、插件级 hooks、MCP 和 HUD 扩展插件。", "author": { "name": "Yeachan Heo", diff --git a/plugins/codex/plugins/oh-my-codex/THIRD_PARTY_SOURCE.json b/plugins/codex/plugins/oh-my-codex/THIRD_PARTY_SOURCE.json index 63c0d6606..188ba52fb 100644 --- a/plugins/codex/plugins/oh-my-codex/THIRD_PARTY_SOURCE.json +++ b/plugins/codex/plugins/oh-my-codex/THIRD_PARTY_SOURCE.json @@ -2,8 +2,8 @@ "sourceId": "oh-my-codex", "repo": "https://github.com/Yeachan-Heo/oh-my-codex.git", "ref": "main", - "commit": "4dde22a58a87ada9d86d26981bf58eeb55a42bc7", + "commit": "e9e3bcc720d964d3673cadb8136394ac103cc091", "adapter": "codex-plugin", "sourcePath": "plugins/oh-my-codex", - "syncedAt": "2026-06-21T16:00:01Z" + "syncedAt": "2026-06-25T16:00:00Z" } diff --git a/plugins/codex/plugins/ppt-master/THIRD_PARTY_SOURCE.json b/plugins/codex/plugins/ppt-master/THIRD_PARTY_SOURCE.json index dd28e86f7..4ef6c0fb1 100644 --- a/plugins/codex/plugins/ppt-master/THIRD_PARTY_SOURCE.json +++ b/plugins/codex/plugins/ppt-master/THIRD_PARTY_SOURCE.json @@ -2,8 +2,8 @@ "sourceId": "ppt-master", "repo": "https://github.com/hugohe3/ppt-master.git", "ref": "main", - "commit": "7647212fabf12d16c2e90525d0f3f6229ec058a3", + "commit": "850ad1be2474f5d8930fa2b61105453b99391600", "adapter": "claude-skill", "sourcePath": "skills/ppt-master", - "syncedAt": "2026-06-24T15:59:59Z" + "syncedAt": "2026-06-25T16:00:00Z" } diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_finalize/flatten_tspan.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_finalize/flatten_tspan.py index 68b1cb30f..43ce18f7d 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_finalize/flatten_tspan.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_finalize/flatten_tspan.py @@ -186,6 +186,15 @@ DY_TOLERANCE_PX = 0.5 # Cap on dy / base ratio. Anything beyond this (e.g. a 5x gap) is rejected # as a real section break that shouldn't merge into one text frame. MAX_DY_MULTIPLIER = 3.0 +LIST_MARKER_RE = re.compile( + r"^\s*(?:[•·・]\s*|[-–—*]\s+|\d+[.)、]\s+|[((]\d+[))]\s*)\S+" +) + + +def _starts_with_list_marker(line_group: list[ET.Element]) -> bool: + """Return True when a visual line starts with an ordered/unordered marker.""" + text = "".join(collect_text_content(tspan) for tspan in line_group) + return bool(LIST_MARKER_RE.match(text)) def _tspan_has_positional_descendant(tspan: ET.Element) -> bool: @@ -296,7 +305,7 @@ def _classify_paragraph_block( extras: list[float] = [0.0] # first line never has space-before soft_breaks: list[bool] = [False] # first line starts a paragraph - for d in dy_values[1:]: + for idx, d in enumerate(dy_values[1:], start=1): if d + DY_TOLERANCE_PX < base: return None # below base — line overlap, not a paragraph if d > base * MAX_DY_MULTIPLIER + DY_TOLERANCE_PX: @@ -305,8 +314,13 @@ def _classify_paragraph_block( if extra < 0: extra = 0.0 # dy at the base line-height = soft break (SVG was simulating wrap); - # dy strictly greater than base = hard paragraph break. - is_soft = abs(extra) <= DY_TOLERANCE_PX + # dy strictly greater than base = hard paragraph break. List markers + # also start a fresh paragraph so bullet/ordered items do not merge + # into the previous item when exported to PowerPoint. + is_soft = ( + abs(extra) <= DY_TOLERANCE_PX + and not _starts_with_list_marker(line_groups[idx]) + ) extras.append(0.0 if is_soft else extra) soft_breaks.append(is_soft) diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_to_pptx/drawingml_elements.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_to_pptx/drawingml_elements.py index 895b84833..05227920e 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_to_pptx/drawingml_elements.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_to_pptx/drawingml_elements.py @@ -921,9 +921,21 @@ def _estimate_run_text_width(run: dict[str, Any]) -> float: return base_width + letter_spacing_px * max(len(text) - 1, 0) -def _estimate_text_runs_width(runs: list[dict[str, Any]]) -> float: - """Estimate a line of text runs with renderer headroom.""" +def _estimate_text_runs_width( + runs: list[dict[str, Any]], + *, + include_headroom: bool = True, +) -> float: + """Estimate a line of text runs. + + ``include_headroom`` is useful for single-line auto-fit boxes where a + renderer that measures text slightly wider would otherwise wrap. Paragraph + boxes use this value as a wrapping constraint, so adding headroom there + stretches the merged text frame beyond the author's source line width. + """ width = sum(_estimate_run_text_width(run) for run in runs) + if not include_headroom: + return width if any(_is_serif_run(run) for run in runs): return width * 1.35 return width * 1.12 @@ -1202,7 +1214,7 @@ def convert_text(elem: ET.Element, ctx: ConvertContext) -> ShapeResult | None: if not line_runs: continue visual_line_widths.append( - _estimate_text_runs_width(line_runs) + _estimate_text_runs_width(line_runs, include_headroom=False) ) soft_break = child.get('data-paragraph-soft-break') == '1' if soft_break and paragraph_runs: @@ -1371,8 +1383,8 @@ def convert_text(elem: ET.Element, ctx: ConvertContext) -> ShapeResult | None: # Paragraph mode: wrap="square" so text reflows when the user resizes, # but NO spAutoFit — otherwise PowerPoint expands the frame to fit a # long joined-up on one line, blowing past the canvas. The cx we - # write below (longest SVG line) is the design target width; - # PowerPoint wraps long paragraphs inside this width. + # write below is the longest source SVG line without single-line renderer + # headroom; PowerPoint wraps long paragraphs inside this design width. # Single-line text keeps wrap="none" + spAutoFit for tight fidelity. if paragraph_runs is not None: body_pr_xml = ( diff --git a/plugins/codex/plugins/shadcn/THIRD_PARTY_SOURCE.json b/plugins/codex/plugins/shadcn/THIRD_PARTY_SOURCE.json index f496c527b..f0c8e78f3 100644 --- a/plugins/codex/plugins/shadcn/THIRD_PARTY_SOURCE.json +++ b/plugins/codex/plugins/shadcn/THIRD_PARTY_SOURCE.json @@ -2,8 +2,8 @@ "sourceId": "shadcn", "repo": "https://github.com/shadcn-ui/ui.git", "ref": "main", - "commit": "549852bffcad7718b92bf40ea44b94a4e627511a", + "commit": "35983528c233250b990f6172f1a60df228409a37", "adapter": "claude-skill", "sourcePath": "skills/shadcn", - "syncedAt": "2026-06-24T15:59:59Z" + "syncedAt": "2026-06-25T16:00:00Z" } diff --git a/plugins/codex/plugins/ui-ux-pro-max/README.md b/plugins/codex/plugins/ui-ux-pro-max/README.md index 6a1f1adde..1df71809d 100755 --- a/plugins/codex/plugins/ui-ux-pro-max/README.md +++ b/plugins/codex/plugins/ui-ux-pro-max/README.md @@ -154,7 +154,7 @@ Each rule includes: - **161 Color Palettes** - Industry-specific palettes aligned 1:1 with the 161 product types - **57 Font Pairings** - Curated typography combinations with Google Fonts imports - **25 Chart Types** - Recommendations for dashboards and analytics -- **16 Tech Stacks** - React, Next.js, Astro, Vue, Nuxt.js, Nuxt UI, Svelte, SwiftUI, React Native, Flutter, HTML+Tailwind, shadcn/ui, Jetpack Compose, Angular, Laravel, JavaFX +- **17 Tech Stacks** - React, Next.js, Astro, Vue, Nuxt.js, Nuxt UI, Svelte, SwiftUI, React Native, Flutter, HTML+Tailwind, shadcn/ui, Jetpack Compose, Angular, Laravel, Three.js, JavaFX - **99 UX Guidelines** - Best practices, anti-patterns, and accessibility rules - **161 Reasoning Rules** - Industry-specific design system generation (NEW in v2.0) @@ -304,8 +304,8 @@ uipro init --ai cursor --global # Install to ~/.cursor/skills/ ```bash uipro versions # List available versions -uipro update # Update to latest version -uipro init --offline # Skip GitHub download, use bundled assets +uipro update # Refresh skill files from installed CLI package +uipro init --offline # Compatibility flag; installs bundled templates uipro uninstall # Remove skill (auto-detect platform) uipro uninstall --ai claude # Remove specific platform uipro uninstall --global # Remove from global install @@ -386,7 +386,7 @@ The skill provides stack-specific guidelines for: | **Vue Ecosystem** | Vue, Nuxt.js, Nuxt UI | | **Angular** | Angular | | **PHP** | Laravel (Blade, Livewire, Inertia.js) | -| **Other Web** | Svelte, Astro | +| **Other Web** | Svelte, Astro, Three.js | | **Desktop** | JavaFX | | **iOS** | SwiftUI | | **Android** | Jetpack Compose | @@ -468,7 +468,7 @@ npm install -g uipro-cli uipro init --ai ``` -This ensures you get the latest templates and correct file structure for your AI assistant. +This ensures you get the latest templates bundled with the installed CLI package and the correct file structure for your AI assistant. Update the npm package first when a new release is published. ### For Contributors @@ -491,12 +491,12 @@ cli/ # CLI installer (generates files from templates) # - templates/ → Platform-specific templates # 4. Sync to CLI and test locally -cp -r src/ui-ux-pro-max/data/* cli/assets/data/ -cp -r src/ui-ux-pro-max/scripts/* cli/assets/scripts/ -cp -r src/ui-ux-pro-max/templates/* cli/assets/templates/ +cd cli +npm run sync:assets +npm run check:assets # 5. Build and test CLI -cd cli && bun run build +bun run build node dist/index.js init --ai claude --offline # Test in a temp folder # 6. Create PR (never push directly to main) diff --git a/plugins/codex/plugins/ui-ux-pro-max/THIRD_PARTY_SOURCE.json b/plugins/codex/plugins/ui-ux-pro-max/THIRD_PARTY_SOURCE.json index 60491d399..94e583805 100644 --- a/plugins/codex/plugins/ui-ux-pro-max/THIRD_PARTY_SOURCE.json +++ b/plugins/codex/plugins/ui-ux-pro-max/THIRD_PARTY_SOURCE.json @@ -2,8 +2,8 @@ "sourceId": "ui-ux-pro-max", "repo": "https://github.com/nextlevelbuilder/ui-ux-pro-max-skill.git", "ref": "main", - "commit": "bdf1179bcf641cca49ee7a5f76df14c3015fd38c", + "commit": "318e0b2e4069b578c729228455328a1ca88f640d", "adapter": "claude-skill", "sourcePath": ".claude/skills/ui-ux-pro-max", - "syncedAt": "2026-06-24T15:59:59Z" + "syncedAt": "2026-06-25T16:00:00Z" } diff --git a/plugins/codex/plugins/ui-ux-pro-max/skills/ui-ux-pro-max/scripts/design_system.py b/plugins/codex/plugins/ui-ux-pro-max/skills/ui-ux-pro-max/scripts/design_system.py index d3152e5fb..f1f714e11 100644 --- a/plugins/codex/plugins/ui-ux-pro-max/skills/ui-ux-pro-max/scripts/design_system.py +++ b/plugins/codex/plugins/ui-ux-pro-max/skills/ui-ux-pro-max/scripts/design_system.py @@ -16,10 +16,18 @@ Usage: import csv import json import os +import sys +import io from datetime import datetime from pathlib import Path from core import search, DATA_DIR +# Force UTF-8 for stdout/stderr to handle emojis/box-drawing chars on Windows (cp1252 default) +if sys.stdout.encoding and sys.stdout.encoding.lower() != 'utf-8': + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') +if sys.stderr.encoding and sys.stderr.encoding.lower() != 'utf-8': + sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8') + # ============ CONFIGURATION ============ REASONING_FILE = "ui-reasoning.csv" @@ -573,8 +581,9 @@ def persist_design_system(design_system: dict, page: str = None, output_dir: str """ base_dir = Path(output_dir) if output_dir else Path.cwd() - # Use project name for project-specific folder - project_name = design_system.get("project_name", "default") + # Use project name for project-specific folder. Coalesce falsy values + # (missing key, explicit None, or "") so the .lower() below can't crash. + project_name = design_system.get("project_name") or "default" project_slug = project_name.lower().replace(' ', '-') design_system_dir = base_dir / "design-system" / project_slug