From 5e6f30c141c36dcfda8a220d7d7a6d07ea55aece Mon Sep 17 00:00:00 2001 From: KeyInfo Bot Date: Thu, 13 Aug 2026 16:40:27 +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 | 12 + README.md | 2 + config/external-sources.json | 66 +++++ config/external-sources.lock.json | 33 ++- .../codex/.agents/plugins/marketplace.json | 12 + .../plugins/caveman/THIRD_PARTY_SOURCE.json | 4 +- .../grill-me/.codex-plugin/plugin.json | 40 +++ plugins/codex/plugins/grill-me/LICENSE | 21 ++ .../plugins/grill-me/THIRD_PARTY_SOURCE.json | 9 + .../plugins/grill-me/skills/grill-me/SKILL.md | 7 + .../skills/grill-me/agents/openai.yaml | 5 + .../plugins/grill-me/skills/grilling/SKILL.md | 22 ++ .../skills/grilling/agents/openai.yaml | 3 + .../plugins/mcp-playwright/MCP_SOURCE.json | 2 +- .../next-skills/THIRD_PARTY_SOURCE.json | 4 +- .../ppt-master/THIRD_PARTY_SOURCE.json | 4 +- .../references/image-layout-patterns.md | 2 +- .../ppt-master/references/svg-effects.md | 12 + .../ppt-master/scripts/confirm_ui/server.py | 12 +- .../scripts/confirm_ui/static/app.js | 266 +++++++++++++++--- .../scripts/confirm_ui/static/catalogs.json | 174 +++++++++++- .../scripts/confirm_ui/static/index.html | 1 + .../ppt-master/scripts/docs/confirm_ui.md | 6 +- .../ppt-master/scripts/svg_editor/server.py | 4 +- .../scripts/svg_editor/static/app.js | 90 +++++- .../scripts/svg_editor/static/index.html | 1 + .../workflows/profiles/beautify-pptx.md | 2 +- .../workflows/stages/live-preview.md | 2 +- .../plugins/shadcn/THIRD_PARTY_SOURCE.json | 4 +- .../superpowers/.codex-plugin/plugin.json | 2 +- plugins/codex/plugins/superpowers/README.md | 87 +++++- .../superpowers/THIRD_PARTY_SOURCE.json | 4 +- .../superpowers/skills/brainstorming/SKILL.md | 113 +++++++- .../skills/brainstorming/visual-companion.md | 9 +- .../finishing-a-development-branch/SKILL.md | 24 ++ .../requesting-code-review/code-reviewer.md | 9 + .../subagent-driven-development/SKILL.md | 113 ++++++-- .../implementer-prompt.md | 12 + .../re-review-prompt.md | 9 + .../task-reviewer-prompt.md | 22 ++ .../skills/using-superpowers/SKILL.md | 1 + .../references/codex-tools.md | 71 ++++- .../references/hermes-tools.md | 56 ++++ .../superpowers/skills/writing-plans/SKILL.md | 3 + .../skills/writing-skills/render-graphs.js | 13 +- plugins/codex/plugins/ui-ux-pro-max/README.md | 17 ++ .../ui-ux-pro-max/THIRD_PARTY_SOURCE.json | 4 +- scripts/sync_external_plugins.ps1 | 21 ++ 48 files changed, 1282 insertions(+), 130 deletions(-) create mode 100644 plugins/codex/plugins/grill-me/.codex-plugin/plugin.json create mode 100644 plugins/codex/plugins/grill-me/LICENSE create mode 100644 plugins/codex/plugins/grill-me/THIRD_PARTY_SOURCE.json create mode 100644 plugins/codex/plugins/grill-me/skills/grill-me/SKILL.md create mode 100644 plugins/codex/plugins/grill-me/skills/grill-me/agents/openai.yaml create mode 100644 plugins/codex/plugins/grill-me/skills/grilling/SKILL.md create mode 100644 plugins/codex/plugins/grill-me/skills/grilling/agents/openai.yaml create mode 100644 plugins/codex/plugins/superpowers/skills/using-superpowers/references/hermes-tools.md diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json index 249f87f4..8336be78 100644 --- a/.agents/plugins/marketplace.json +++ b/.agents/plugins/marketplace.json @@ -40,6 +40,18 @@ }, "category": "Productivity" }, + { + "name": "grill-me", + "source": { + "source": "local", + "path": "./plugins/codex/plugins/grill-me" + }, + "policy": { + "installation": "AVAILABLE", + "authentication": "ON_INSTALL" + }, + "category": "Productivity" + }, { "name": "guizang-ppt-skill", "source": { diff --git a/README.md b/README.md index ec748afc..39f8142f 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ Codex 插件页的大标题按 marketplace 来源分组,不是按插件 `categ 有些插件是 skill 集合,安装一个 `plugin-id` 后会同时提供多个 `$skill-name`。可安装项和安装后可用的 skills 均以 Codex 的实际输出为准。 +例如 `grill-me` 插件会同时安装用户入口 `$grill-me` 和必需的基础能力 `$grilling`;请安装插件整体,不要只复制其中一个 skill 目录。 + 如果插件刚安装到当前 Codex 会话中,启动新的 Codex thread 或新的 Codex 调用后再依赖新增 skills/hooks/MCP/app 配置。 卸载插件: diff --git a/config/external-sources.json b/config/external-sources.json index abd94354..f4fadddf 100644 --- a/config/external-sources.json +++ b/config/external-sources.json @@ -553,6 +553,72 @@ } ] }, + { + "id": "grill-me", + "repo": "https://github.com/mattpocock/skills.git", + "ref": "main", + "adapter": "skill-collection", + "pluginName": "grill-me", + "category": "Productivity", + "skillsPath": "skills/productivity", + "includeSkills": [ + "grill-me", + "grilling" + ], + "sparseCheckout": [ + "skills/productivity/grill-me", + "skills/productivity/grilling", + "LICENSE" + ], + "brandColor": "#DC2626", + "metadata": { + "version": "0.1.0", + "description": "通过持续追问和分轮决策树访谈,帮助用户检验并澄清计划、设计、决策或想法。", + "displayName": "Grill Me", + "author": { + "name": "Matt Pocock", + "url": "https://github.com/mattpocock" + }, + "homepage": "https://github.com/mattpocock/skills/tree/main/skills/productivity/grill-me", + "repository": "https://github.com/mattpocock/skills", + "license": "MIT", + "keywords": [ + "grill-me", + "grilling", + "interview", + "planning", + "decision-making" + ] + }, + "manifestOverrides": { + "interface": { + "displayName": "Grill Me", + "shortDescription": "用分轮追问检验并澄清计划、设计和决策。", + "longDescription": "Grill Me 通过 grilling 基础 skill 构建设计树,按决策依赖分轮提出问题和推荐答案,持续检验计划、设计、决策或想法,直到双方确认没有未说明的假设。插件同时包含 grill-me 和其必需依赖 grilling。", + "developerName": "Matt Pocock", + "category": "Productivity", + "capabilities": [ + "Interactive", + "Read" + ], + "defaultPrompt": [ + "使用 Grill Me 帮我彻底检验这个想法。", + "使用 Grill Me 通过分轮提问帮我澄清这个计划。" + ], + "websiteURL": "https://github.com/mattpocock/skills/tree/main/skills/productivity/grill-me", + "privacyPolicyURL": "https://github.com/mattpocock/skills", + "termsOfServiceURL": "https://github.com/mattpocock/skills", + "brandColor": "#DC2626" + } + }, + "skillDescriptions": { + "grill-me": "在用户明确要求严格追问、压力测试或彻底澄清计划、设计、决策或想法时使用。", + "grilling": "在用户希望通过分轮问题压力测试计划、决策或想法,或使用 grill 相关触发语时使用。" + }, + "includeRootFiles": [ + "LICENSE" + ] + }, { "id": "next-skills", "repo": "https://github.com/vercel/next.js.git", diff --git a/config/external-sources.lock.json b/config/external-sources.lock.json index 124327f7..ebf7082e 100644 --- a/config/external-sources.lock.json +++ b/config/external-sources.lock.json @@ -6,8 +6,8 @@ "repo": "https://github.com/obra/superpowers.git", "ref": "main", "adapter": "codex-plugin", - "commit": "44c9b2d6e889982ac18c27d05a19fefe335194e1", - "syncedAt": "2026-07-29T16:00:04Z" + "commit": "b36e0829c6d0140e93cfef2ca599b1b07d4a7797", + "syncedAt": "2026-08-13T08:38:10Z" }, { "id": "superpowers-zh", @@ -33,8 +33,8 @@ "repo": "https://github.com/nextlevelbuilder/ui-ux-pro-max-skill.git", "ref": "main", "adapter": "claude-skill", - "commit": "abb7f2fd5a083fa1ff55c326a963ff0d95c33f99", - "syncedAt": "2026-08-06T16:00:02Z" + "commit": "97eb2a20032f0833e3d317162208a60385b0f96e", + "syncedAt": "2026-08-13T08:38:10Z" }, { "id": "caveman", @@ -42,8 +42,8 @@ "repo": "https://github.com/JuliusBrussee/caveman.git", "ref": "main", "adapter": "codex-plugin", - "commit": "b2ca50b8809d4dbc9f664b398938fddede320001", - "syncedAt": "2026-08-11T16:00:01Z" + "commit": "613d7f0402fb51bdde0edb6b01853b391a06b765", + "syncedAt": "2026-08-13T08:38:10Z" }, { "id": "taste-skill", @@ -60,8 +60,8 @@ "repo": "https://github.com/shadcn-ui/ui.git", "ref": "main", "adapter": "claude-skill", - "commit": "41bbc12cfd39ed8d9cb8da04275479ee7ecc0612", - "syncedAt": "2026-08-11T16:00:01Z" + "commit": "a85299a9edd2a961e32f01ced86963a852652bd2", + "syncedAt": "2026-08-13T08:38:10Z" }, { "id": "frontend-slides", @@ -96,8 +96,17 @@ "repo": "https://github.com/hugohe3/ppt-master.git", "ref": "main", "adapter": "claude-skill", - "commit": "4e6ecbcb0dc079efebd3c79b775c0f02581509fe", - "syncedAt": "2026-08-11T16:00:01Z" + "commit": "bcc5762d6c770025f37ca459f5d9ea96f1783fc1", + "syncedAt": "2026-08-13T08:38:10Z" + }, + { + "id": "grill-me", + "pluginName": "grill-me", + "repo": "https://github.com/mattpocock/skills.git", + "ref": "main", + "adapter": "skill-collection", + "commit": "84fdeffd12f2ee307994d1eb6feb48173b6e0502", + "syncedAt": "2026-08-13T08:38:10Z" }, { "id": "next-skills", @@ -105,8 +114,8 @@ "repo": "https://github.com/vercel/next.js.git", "ref": "canary", "adapter": "skill-collection", - "commit": "bbec4fe2bd7222aaa9b4de58269d821ab128fab8", - "syncedAt": "2026-08-11T16:00:01Z" + "commit": "fef4c28bba9f080fce9687a7a8ee7ac3784de57e", + "syncedAt": "2026-08-13T08:38:10Z" } ] } diff --git a/plugins/codex/.agents/plugins/marketplace.json b/plugins/codex/.agents/plugins/marketplace.json index 072da4e4..84517efa 100644 --- a/plugins/codex/.agents/plugins/marketplace.json +++ b/plugins/codex/.agents/plugins/marketplace.json @@ -40,6 +40,18 @@ }, "category": "Productivity" }, + { + "name": "grill-me", + "source": { + "source": "local", + "path": "./plugins/grill-me" + }, + "policy": { + "installation": "AVAILABLE", + "authentication": "ON_INSTALL" + }, + "category": "Productivity" + }, { "name": "guizang-ppt-skill", "source": { diff --git a/plugins/codex/plugins/caveman/THIRD_PARTY_SOURCE.json b/plugins/codex/plugins/caveman/THIRD_PARTY_SOURCE.json index d8280abd..39e6520d 100644 --- a/plugins/codex/plugins/caveman/THIRD_PARTY_SOURCE.json +++ b/plugins/codex/plugins/caveman/THIRD_PARTY_SOURCE.json @@ -2,8 +2,8 @@ "sourceId": "caveman", "repo": "https://github.com/JuliusBrussee/caveman.git", "ref": "main", - "commit": "b2ca50b8809d4dbc9f664b398938fddede320001", + "commit": "613d7f0402fb51bdde0edb6b01853b391a06b765", "adapter": "codex-plugin", "sourcePath": "plugins/caveman", - "syncedAt": "2026-08-11T16:00:01Z" + "syncedAt": "2026-08-13T08:38:10Z" } diff --git a/plugins/codex/plugins/grill-me/.codex-plugin/plugin.json b/plugins/codex/plugins/grill-me/.codex-plugin/plugin.json new file mode 100644 index 00000000..e7a27063 --- /dev/null +++ b/plugins/codex/plugins/grill-me/.codex-plugin/plugin.json @@ -0,0 +1,40 @@ +{ + "name": "grill-me", + "version": "0.1.0", + "description": "通过持续追问和分轮决策树访谈,帮助用户检验并澄清计划、设计、决策或想法。", + "author": { + "name": "Matt Pocock", + "url": "https://github.com/mattpocock" + }, + "homepage": "https://github.com/mattpocock/skills/tree/main/skills/productivity/grill-me", + "repository": "https://github.com/mattpocock/skills", + "license": "MIT", + "keywords": [ + "grill-me", + "grilling", + "interview", + "planning", + "decision-making" + ], + "skills": "./skills/", + "interface": { + "displayName": "Grill Me", + "shortDescription": "用分轮追问检验并澄清计划、设计和决策。", + "longDescription": "Grill Me 通过 grilling 基础 skill 构建设计树,按决策依赖分轮提出问题和推荐答案,持续检验计划、设计、决策或想法,直到双方确认没有未说明的假设。插件同时包含 grill-me 和其必需依赖 grilling。", + "developerName": "Matt Pocock", + "category": "Productivity", + "capabilities": [ + "Interactive", + "Read" + ], + "defaultPrompt": [ + "使用 Grill Me 帮我彻底检验这个想法。", + "使用 Grill Me 通过分轮提问帮我澄清这个计划。" + ], + "websiteURL": "https://github.com/mattpocock/skills/tree/main/skills/productivity/grill-me", + "privacyPolicyURL": "https://github.com/mattpocock/skills", + "termsOfServiceURL": "https://github.com/mattpocock/skills", + "brandColor": "#DC2626", + "screenshots": [] + } +} diff --git a/plugins/codex/plugins/grill-me/LICENSE b/plugins/codex/plugins/grill-me/LICENSE new file mode 100644 index 00000000..f1dd2c09 --- /dev/null +++ b/plugins/codex/plugins/grill-me/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Matt Pocock + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins/codex/plugins/grill-me/THIRD_PARTY_SOURCE.json b/plugins/codex/plugins/grill-me/THIRD_PARTY_SOURCE.json new file mode 100644 index 00000000..58979fff --- /dev/null +++ b/plugins/codex/plugins/grill-me/THIRD_PARTY_SOURCE.json @@ -0,0 +1,9 @@ +{ + "sourceId": "grill-me", + "repo": "https://github.com/mattpocock/skills.git", + "ref": "main", + "commit": "84fdeffd12f2ee307994d1eb6feb48173b6e0502", + "adapter": "skill-collection", + "sourcePath": "skills/productivity", + "syncedAt": "2026-08-13T08:38:10Z" +} diff --git a/plugins/codex/plugins/grill-me/skills/grill-me/SKILL.md b/plugins/codex/plugins/grill-me/skills/grill-me/SKILL.md new file mode 100644 index 00000000..5913c282 --- /dev/null +++ b/plugins/codex/plugins/grill-me/skills/grill-me/SKILL.md @@ -0,0 +1,7 @@ +--- +name: grill-me +description: "在用户明确要求严格追问、压力测试或彻底澄清计划、设计、决策或想法时使用。" +disable-model-invocation: true +--- + +Run a `/grilling` session. diff --git a/plugins/codex/plugins/grill-me/skills/grill-me/agents/openai.yaml b/plugins/codex/plugins/grill-me/skills/grill-me/agents/openai.yaml new file mode 100644 index 00000000..4d6fb0c7 --- /dev/null +++ b/plugins/codex/plugins/grill-me/skills/grill-me/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: "Grill Me" + short_description: "Sharpen a plan through interview" +policy: + allow_implicit_invocation: false diff --git a/plugins/codex/plugins/grill-me/skills/grilling/SKILL.md b/plugins/codex/plugins/grill-me/skills/grilling/SKILL.md new file mode 100644 index 00000000..4d5a68ae --- /dev/null +++ b/plugins/codex/plugins/grill-me/skills/grilling/SKILL.md @@ -0,0 +1,22 @@ +--- +name: grilling +description: "在用户希望通过分轮问题压力测试计划、决策或想法,或使用 grill 相关触发语时使用。" +--- + +Interview the user relentlessly until you reach a shared understanding. Map this as a **design tree**: every decision branches into the decisions that hang off it. + +Work the tree in **rounds**. The **frontier** is every decision whose prerequisites are already settled — the questions you can ask _now_ without guessing at answers you haven't heard yet. Ask the whole frontier in one round: number each question and give your recommended answer. Then wait for the user's answers before the next round. + +Each question should be formatted like so: + +``` +❓ **Q1** - ****: + +➡️ +``` + +Each round the user answers reshapes the tree — settled decisions push the frontier outward and unblock questions that depended on them. Recompute the frontier and ask the next round. A question whose answer depends on another question still open in this round belongs to a _later_ round, not this one. + +Finding _facts_ is your job, never the user's. When a frontier question needs a fact from the environment (filesystem, tools, etc.), dispatch a sub-agent to find it — don't ask the user for anything you could look up yourself. Don't block on it: a running exploration is an unsettled prerequisite, so only the questions downstream of it wait for the sub-agent to report — ask the rest of the frontier now. The _decisions_ are the user's — put each to them and wait. + +The session is done when the frontier is empty: every branch of the design tree visited, nothing left silently assumed. Do not act on it until the user confirms you have reached a shared understanding. diff --git a/plugins/codex/plugins/grill-me/skills/grilling/agents/openai.yaml b/plugins/codex/plugins/grill-me/skills/grilling/agents/openai.yaml new file mode 100644 index 00000000..ddbdb961 --- /dev/null +++ b/plugins/codex/plugins/grill-me/skills/grilling/agents/openai.yaml @@ -0,0 +1,3 @@ +interface: + display_name: "Grilling" + short_description: "Stress-test thinking a round of questions at a time" diff --git a/plugins/codex/plugins/mcp-playwright/MCP_SOURCE.json b/plugins/codex/plugins/mcp-playwright/MCP_SOURCE.json index f373bf2e..17406499 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-08-11T16:02:06Z" + "syncedAt": "2026-08-13T08:40:25Z" } diff --git a/plugins/codex/plugins/next-skills/THIRD_PARTY_SOURCE.json b/plugins/codex/plugins/next-skills/THIRD_PARTY_SOURCE.json index b066ff31..4a330a8e 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": "bbec4fe2bd7222aaa9b4de58269d821ab128fab8", + "commit": "fef4c28bba9f080fce9687a7a8ee7ac3784de57e", "adapter": "skill-collection", "sourcePath": "skills", - "syncedAt": "2026-08-11T16:00:01Z" + "syncedAt": "2026-08-13T08:38:10Z" } diff --git a/plugins/codex/plugins/ppt-master/THIRD_PARTY_SOURCE.json b/plugins/codex/plugins/ppt-master/THIRD_PARTY_SOURCE.json index fb2c387f..e8ff7509 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": "4e6ecbcb0dc079efebd3c79b775c0f02581509fe", + "commit": "bcc5762d6c770025f37ca459f5d9ea96f1783fc1", "adapter": "claude-skill", "sourcePath": "skills/ppt-master", - "syncedAt": "2026-08-11T16:00:01Z" + "syncedAt": "2026-08-13T08:38:10Z" } diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/references/image-layout-patterns.md b/plugins/codex/plugins/ppt-master/skills/ppt-master/references/image-layout-patterns.md index 488fc271..5a401656 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/references/image-layout-patterns.md +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/references/image-layout-patterns.md @@ -233,7 +233,7 @@ If motion is enabled, [`animations.md`](./animations.md) owns its implementation | Scene-backed evidence or metrics | `#P2-01` / `#P2-05` + `#M2-01` or `#M2-03`; let the image carry context and native SVG carry information | | One selected region needs explanation | Use `#P2-03` for an outline and caption on one picture; use `#P2-04` when a second same-source picture must magnify the region | | Several sources should read as one object | `#P3-21` + restrained `#M3-01`, or `#P3-20` + a native text/color cell | -| One continuous scene should span detached shapes | `#M1-10` + optional `#M3-05`; keep one-picture topology | +| One continuous scene should span detached shapes | `#M1-10` + optional `#M3-05`; combine `#P1-08` for a triangular image-and-copy split, and keep one-picture topology | | Same-source windows must remain independent | `#M1-11`; add `#C2-01` or `#C2-02` only when consecutive pages use the relationship | | A prepared subject should re-layer over its source | `#A2-03`; keep the base and cutout registered, and insert a native middle layer only when it has a distinct job | | A busy visual needs one focal region | `#M2-05`, or prepared `#A3-01` / `#A3-03` when a native contrast treatment is insufficient | diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/references/svg-effects.md b/plugins/codex/plugins/ppt-master/skills/ppt-master/references/svg-effects.md index 89c22327..900968e0 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/references/svg-effects.md +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/references/svg-effects.md @@ -669,6 +669,18 @@ least two. [`paths.py`](../scripts/svg_to_pptx/drawingml/paths.py); native-object fallback bounds reuse its normalized commands rather than a second path grammar. +**Reference — not a constraint**: use the fewest curve segments and control +points that preserve the intended silhouette. Set endpoints and tangent +directions first; use `S` after `C` or `T` after `Q` when reflected controls +preserve deliberate tangent continuity. + +```xml + + +``` + Command identity, relative coordinates, shorthand, arc parameters, and original handles are not retained. Geometry needs non-zero bounds. Before authoring a freeform, apply [`native-shape-authoring.md`](./native-shape-authoring.md): diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/confirm_ui/server.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/confirm_ui/server.py index f46bdaba..0a250053 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/confirm_ui/server.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/confirm_ui/server.py @@ -130,9 +130,9 @@ _ICON_PREVIEW_SAMPLES = { 'phosphor-duotone': ('house', 'chart-line', 'users', 'target'), } -# Prefer the same memorable entry port as live preview. Normal single-project -# execution releases it between Step 4 and Step 6; concurrent projects advance -# from this base while explicit ``--port`` remains exact. +# Keep the long-standing Confirm UI entry port. Live preview uses a separate +# base range so stale preview tabs cannot address a later Confirm UI process. +# Concurrent Confirm UI sessions advance while explicit ``--port`` remains exact. DEFAULT_PORT = 5050 PUBLIC_HOST = '127.0.0.1' STARTUP_TIMEOUT = 10 @@ -1258,7 +1258,7 @@ def _localized_text_present(candidate: dict, field: str) -> bool: """Return whether a candidate carries non-empty localized prose.""" return any( isinstance(candidate.get(key), str) and bool(candidate[key].strip()) - for key in (field, f'{field}_zh', f'{field}_en', f'{field}_ja') + for key in (field, f'{field}_zh', f'{field}_zh_tw', f'{field}_en', f'{field}_ja') ) @@ -2270,8 +2270,8 @@ def _build_catalogs() -> dict: """Return the static catalog set with the canvas list synced live from ``config.CANVAS_FORMATS`` — the single source of truth for canvas formats — so the confirm page can never drift from the pipeline's real formats. The - set of formats and their dimensions come from config; trilingual labels and - use text are kept from catalogs.json (with a plain fallback for any new id). + set of formats and their dimensions come from config; four-language labels + and use text are kept from catalogs.json (with a plain fallback for new ids). """ data = json.loads(_CATALOGS_PATH.read_text(encoding='utf-8')) try: diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/confirm_ui/static/app.js b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/confirm_ui/static/app.js index cf6bff17..190086f8 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/confirm_ui/static/app.js +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/confirm_ui/static/app.js @@ -560,16 +560,204 @@ on: "开", option_prefix: "方案", error_retry: "出错,请重试" + }, + "zh-TW": { + page_title: "確認設計方案", + topbar_hint: "回答開放問題,或選擇並調整推薦項,然後繼續。", + stage_anchors: "第一階段 · 溝通契約", + stage_final_plan: "第二階段 · 最終方案與製作", + loading: "載入中…", + load_error: "無法載入推薦檔案,需在啟動前寫入。", + btn_confirm: "確認", + btn_confirm_contract: "確認溝通契約並繼續 →", + btn_confirm_final_plan: "確認最終方案 →", + deriving: "正在根據你的選擇生成下游選項…", + template_selection_required: "請選擇自由設計或使用範本;選擇使用範本時,至少選擇一個工作區。", + connection_lost: "確認頁服務連線中斷,正在重試;如果持續失敗,請回到聊天視窗走聊天確認。", + confirmed_title: "✓ 已確認", + confirmed_hint: "選擇已儲存,可關閉此頁並回到聊天視窗。", + lang_toggle_title: "切換語言", + sec_template_choice: "設計基礎", + template_choice_hint: "選擇這份簡報如何建立設計系統。", + template_free_title: "根據目前內容從零設計", + template_free_desc: "不使用可重複使用的範本工作區,由 Strategist 根據目前專案推導視覺系統。", + template_use_title: "使用範本", + template_use_desc: "選擇一個或多個 Brand、Style、Layout、Deck 或指定工作區。", + sec_template_library: "範本組合", + template_library_hint: "每種已註冊範本最多選擇一個;Brand、Style、Layout、Deck 可以組合使用。", + sec_template_explicit: "指定範本", + template_explicit_hint: "本次執行明確提供的精確工作區最多選擇一個;顯示來源路徑供你核對。", + template_kind_brand: "Brand", + template_kind_style: "Style", + template_kind_layout: "Layout", + template_kind_deck: "Deck", + template_source_library: "範本庫", + template_source_explicit: "指定地址", + template_source_path: "來源路徑", + template_select_none: "無", + template_none_registered: "尚無已註冊範本", + template_none_explicit: "本次執行沒有指定範本", + sec_canvas: "畫布格式", + sec_pages: "頁數", + sec_audience: "目標受眾", + sec_communication: "這份簡報要完成什麼", + sec_delivery: "如何使用、之後留下什麼", + sec_narrative: "敘事方向", + sec_visual: "視覺方向", + sec_color: "色彩方案", + sec_icons: "圖示使用", + sec_type: "字型方案", + sec_images: "圖片使用", + sec_image_production: "圖片產製", + sec_proactive_execution: "主動執行", + sec_mode: "生成模式", + sec_refine: "先審閱設計規範", + sec_design_directions: "成套設計方向", + design_directions_hint: "AI 最傾向的成套方案已預設套用;你可以改選其他方案,或在下方微調各項。調整後可用「還原原始方案」還原整套預設。", + direction_active: "已套用", + direction_adjusted: "已調整", + direction_apply_hint: "按一下即可套用這套完整方案。", + direction_restore: "還原原始方案", + scheme_component_options: "專案專屬自訂方案 · 選取卡片後可編輯", + sec_template_application: "範本套用方式", + template_application_hint: "AI 會根據目前內容推薦如何使用已安裝範本;你可以直接用自然語言修改。", + placeholder_template_application: "說明使用、跳過、重複或重排哪些範本頁面/原型,哪些內容必須保留,哪些可以替換或重組。", + sub_mode: "敘事模式", + sub_visual: "視覺風格", + sub_divergence: "材料發散度(多大程度重塑,還是貼近源材料)", + placeholder_divergence: "用你自己的話寫,例如「嚴格貼著文件來」/「在源材料範圍內自由重組並展開」。留空則按平衡處理。", + communication_intent: "這份簡報需要完成什麼?", + communication_intent_hint: "開放回答,可按需組合:告知、解釋、說服、決策、對齊、教學、報告與問責、動員、留檔與交接。必要時說明主次或先後,不需要選擇標籤。", + placeholder_communication_intent: "例如:先報告進展並暴露風險,再推動管理階層決定下一階段投入。", + audience_outcome: "期望的受眾變化 / 成功條件", + placeholder_audience_outcome: "結束後,受眾應該知道、理解、相信、決定或採取什麼行動?", + core_message: "核心資訊 / 決策請求 / 行動", + placeholder_core_message: "即使其他內容沒有被記住,受眾至少需要接住哪些主張、請求或行動?", + delivery_context: "傳遞場景(明確主要模式)", + delivery_context_hint: "區分演講者主導、讀者主導、混合、錄製/自動播放;混合場景要說明哪一種主導,以及還要兼顧什麼次要用途。", + placeholder_delivery_context: "例如:主要為有主講的 20 分鐘管理階層現場評審;次要為會後獨立閱讀的簽核文件。", + artifact_afterlife: "簡報後的成果用途", + placeholder_artifact_afterlife: "例如:簽核、評審、稽核、留檔、交接或重複使用;沒有後續用途時可留空。", + stage1_current_value_hint: "可編輯欄位中是推薦內容。你可以保留、修改或清空;確認時會按目前內容原樣儲存,空白也會保持為空。", + content_divergence_locked_hint: "目前流程要求原文和頁面結構保持不變,因此該欄位已鎖定。", + custom: "自訂", + custom_placeholder: "輸入自訂內容…", + ai_custom_candidate: "AI 自訂方案", + ai_custom_candidate_hint: "始終展示完整內容用於比較;預設不選取,選擇後可編輯。", + custom_behavior_required: "已選擇的 AI 自訂方案不能為空。", + custom_color_required: "請先填寫自訂配色說明,再繼續確認。", + design_system_required: "請先選擇完整的配色與字型方案,再繼續確認。", + mode_behavior_placeholder: "描述敘事階段、標題語氣、頁面節奏和表達姿態。", + visual_style_behavior_placeholder: "描述形狀語言、構圖、裝飾密度、留白、字型氣質和紋理。", + recommended: "推薦", + placeholder_audience: "這份簡報面向誰?", + placeholder_pages: "如:12-15", + hex_override: "自訂色值覆蓋:", + formula_policy: "公式渲染策略", + image_ai_path: "生成配圖來源", + image_strategy: "生成圖風格", + image_strategy_empty: "目前沒有可用的預設風格參考,仍可使用自訂風格。", + image_strategy_required: "請選擇一種生成圖預設,或填寫自訂風格。", + image_strategy_invalid: "所選生成圖預設目前不可用。", + image_strategy_select_placeholder: "選擇生成圖預設…", + image_strategy_recommended_group: "本專案推薦", + image_strategy_all_group: "全部預設風格", + image_strategy_rendering: "渲染風格", + image_strategy_visual: "視覺", + image_strategy_mood: "情緒", + image_strategy_ai_custom: "AI 自訂方案", + image_strategy_ai_custom_desc: "一套全新或綜合多個已有風格的渲染方案;選擇後可以編輯。", + image_strategy_custom_placeholder: "描述生成圖的具體方向、主體、構圖、風格關鍵字或需要避免的內容。", + image_strategy_reference_hint: "參考圖只展示渲染風格;最終 AI 圖片直接繼承上方已選的整套 PPT 配色。", + image_strategy_no_reference: "自訂選擇沒有參考圖。", + image_source_summary: "已選圖片來源", + image_production_hint: "圖片來源和渲染方向已在上方選擇;這裡僅決定實際產製路徑。", + image_usage_notes: "圖片補充要求", + image_usage_notes_placeholder: "例如:優先真實洗手場景;不要卡通病菌;產品照片保持原樣。", + image_usage_required: "請至少選擇一種圖片使用方式。", + image_usage_none_exclusive: "「不使用圖片」不能和其他圖片選項同時選擇。", + proactive_execution_hint: "這些預設開關只在你沒有明確要求時生效;你最新的明確指令始終優先。", + proactive_speaker_notes: "主動生成演講者備註", + proactive_speaker_notes_desc: "預設開啟。無需另行要求,Agent 也會生成演講者備註。", + proactive_custom_animations: "主動生成自訂動畫", + proactive_custom_animations_desc: "預設關閉。策略師的動畫建議仍會保留;開啟後,Agent 可在沒有另行要求時實際製作自訂動畫。", + proactive_narration_audio: "主動生成旁白音訊", + proactive_narration_audio_desc: "預設關閉。這裡保留原始選擇,不改寫演講者備註開關;策略師會在設計規範中解析旁白所需的最終備註狀態。", + font_heading: "標題", + font_body: "正文", + font_selection: "字型選擇", + primary_language_font: "主要語言字型", + english_font: "英文字型", + font_picker_hint: "選擇推薦方案會同步下方字型;修改任一下拉或手動字型後會標記為已自訂。", + other_installed_font: "其他已安裝字型…", + other_font_placeholder: "輸入精確的已安裝字型名稱", + customized: "已自訂", + font_body_size: "正文基準字級", + font_body_size_hint: "所有字級按這個正文基準推導。", + body_size_unit_relation: "SVG px 與 PPT pt 的換算:1px = 0.75pt。", + body_size_pt_hint: "約 {pt} pt(按 1px = 0.75pt 換算;提交仍儲存 px)。", + role_size_pt_hint: "約 {pt} pt", + body_size_hint_canvas: "目前畫布建議 ~{lo}–{hi}px(依有效畫布跨距計算)。", + body_size_hint_purpose: "該閱讀模式推薦 {def}px(單一固定值,非區間)。", + body_size_hint_oor: "(目前數值超出該畫布的常用範圍——請確認單位無誤、是否合適。)", + delivery_purpose: "閱讀模式", + delivery_purpose_hint: "決定資訊主要由頁面還是講者承擔:近讀型用完整句、短段落和細節自洽;演講型一頁一意,以簡短主張和視覺證據為主。", + size_override: "逐角色字級覆蓋:", + size_role_title: "標題", + size_role_subtitle: "副標題", + size_role_annotation: "註解", + custom_typography: "自訂字型方案", + custom_color: "自訂配色", + custom_color_placeholder: "用文字描述配色,如:深藍主色、暖橙強調、白色背景——或直接貼上 HEX 值…", + role_background: "背景", + role_secondary_bg: "次級背景", + role_primary: "主色", + role_accent: "強調", + role_secondary_accent: "次強調", + role_body_text: "正文文字", + cjk: "中文", + latin: "西文", + sample_heading_cjk: "主題方案標題", + sample_heading_latin: "Presentation Title", + sample_body_cjk: "關鍵資訊摘要", + sample_body_latin: "Key message summary", + style_preview_label: "整體形象(配色 + 字型 + 圖示)", + style_preview_body: "· 僅大致形象,非實際版式", + no_icons: "無圖示", + preview_big_title: "大標題", + preview_section_title: "章節標題", + preview_latin_title: "Section Title", + preview_body_intro: "正文內容用於判斷基礎字級、行距和顏色對比。", + preview_latin_body: "Body text sample for checking Latin typography.", + preview_point_1_title: "正文內容", + preview_point_1_text: "這裡展示普通段落的密度和閱讀節奏。", + preview_point_2_title: "要點說明", + preview_point_2_text: "圖示和文字放在一起,判斷真實使用效果。", + preview_point_3_title: "結論建議", + preview_point_3_text: "組合效果需要在簡報場景下保持清晰可讀。", + mode_continuous_desc: "一次性連續生成整份簡報。", + mode_split_desc: "寫完設計規範後停止,另開視窗繼續生成頁面。", + refine_off_desc: "依次生成設計規範和執行鎖,然後自動繼續。", + refine_on_desc: "生成設計規範後暫停;你可在聊天中修改任何部分,明確確認後再生成執行鎖並繼續製作。", + off_default: "關", + on: "開", + option_prefix: "方案", + error_retry: "出錯,請重試" } }; var LANG = (function () { try { var stored = window.localStorage.getItem("ppt_lang"); - if (stored === "zh" || stored === "en" || stored === "ja") return stored; + if (stored === "zh" || stored === "en" || stored === "ja" || + stored === "zh-TW") return stored; } catch (e) { /* ignore */ } var nav = (navigator.language || navigator.userLanguage || "en").toLowerCase(); - if (nav.indexOf("zh") === 0) return "zh"; + if (nav.indexOf("zh") === 0) { + if (/\bhans\b/.test(nav)) return "zh"; + if (/\bhant\b/.test(nav) || /\b(tw|hk|mo)\b/.test(nav)) return "zh-TW"; + return "zh"; + } if (nav.indexOf("ja") === 0) return "ja"; return "en"; })(); @@ -579,37 +767,50 @@ return dict[key] != null ? dict[key] : key; } - // Fallback stays LANG-relative: zh/en users never see Japanese labels, - // ja pages fall back ja → en → zh. - var LANG_FALLBACK = { zh: ["zh", "en", "ja"], en: ["en", "zh", "ja"], ja: ["ja", "en", "zh"] }; + // Preserve the existing locale order, then accept zh_tw-only candidate + // prose from any persisted UI language so browser and server validation agree. + // Entries are FIELD SUFFIXES, not BCP-47 tags: "zh-TW" data lives in + // `_zh_tw` keys, so a hyphenless suffix is used here and in langField(). + var LANG_FALLBACK = { + zh: ["zh", "en", "ja", "zh_tw"], + en: ["en", "zh", "ja", "zh_tw"], + ja: ["ja", "en", "zh", "zh_tw"], + "zh-TW": ["zh_tw", "zh", "en", "ja"] + }; + // Suffix used to look up localized catalog/recommendation fields. + var LANG_FIELD = { "zh-TW": "zh_tw" }; + + function langField(lang) { + return LANG_FIELD[lang] || lang; + } var IMAGE_COMPARISON_LABELS = { rendering: { - "vector-illustration": { zh: "矢量插画", en: "Vector illustration", ja: "ベクターイラスト" }, - flat: { zh: "扁平插画", en: "Flat illustration", ja: "フラットイラスト" }, - "3d-isometric": { zh: "3D 等距", en: "3D isometric", ja: "3Dアイソメトリック" }, - "digital-dashboard": { zh: "数字仪表盘", en: "Digital dashboard", ja: "デジタルダッシュボード" }, - "corporate-photo": { zh: "企业摄影", en: "Corporate photo", ja: "企業写真" }, - blueprint: { zh: "蓝图线稿", en: "Blueprint", ja: "ブループリント" }, - editorial: { zh: "编辑杂志", en: "Editorial", ja: "エディトリアル" }, - "sketch-notes": { zh: "手绘笔记", en: "Sketch notes", ja: "スケッチノート" }, - "ink-notes": { zh: "墨线笔记", en: "Ink notes", ja: "インクノート" }, - chalkboard: { zh: "粉笔黑板", en: "Chalkboard", ja: "チョークボード" }, - watercolor: { zh: "水彩", en: "Watercolor", ja: "水彩" }, - "warm-scene": { zh: "暖调场景", en: "Warm scene", ja: "暖色シーン" }, - "screen-print": { zh: "丝网印刷", en: "Screen print", ja: "スクリーンプリント" }, - "fantasy-animation": { zh: "幻想动画", en: "Fantasy animation", ja: "ファンタジーアニメ" }, - "pixel-art": { zh: "像素艺术", en: "Pixel art", ja: "ピクセルアート" }, - nature: { zh: "自然有机", en: "Nature", ja: "自然・オーガニック" }, - "minimalist-swiss": { zh: "瑞士极简", en: "Minimalist Swiss", ja: "スイスミニマル" }, - glassmorphism: { zh: "玻璃拟态", en: "Glassmorphism", ja: "グラスモーフィズム" }, - "vintage-poster": { zh: "复古海报", en: "Vintage poster", ja: "ヴィンテージポスター" }, - "paper-cut": { zh: "剪纸拼贴", en: "Paper cut", ja: "ペーパーカット" } + "vector-illustration": { zh: "矢量插画", zh_tw: "向量插畫", en: "Vector illustration", ja: "ベクターイラスト" }, + flat: { zh: "扁平插画", zh_tw: "扁平插畫", en: "Flat illustration", ja: "フラットイラスト" }, + "3d-isometric": { zh: "3D 等距", zh_tw: "3D 等距", en: "3D isometric", ja: "3Dアイソメトリック" }, + "digital-dashboard": { zh: "数字仪表盘", zh_tw: "數位儀表板", en: "Digital dashboard", ja: "デジタルダッシュボード" }, + "corporate-photo": { zh: "企业摄影", zh_tw: "企業攝影", en: "Corporate photo", ja: "企業写真" }, + blueprint: { zh: "蓝图线稿", zh_tw: "藍圖線稿", en: "Blueprint", ja: "ブループリント" }, + editorial: { zh: "编辑杂志", zh_tw: "編輯雜誌", en: "Editorial", ja: "エディトリアル" }, + "sketch-notes": { zh: "手绘笔记", zh_tw: "手繪筆記", en: "Sketch notes", ja: "スケッチノート" }, + "ink-notes": { zh: "墨线笔记", zh_tw: "墨線筆記", en: "Ink notes", ja: "インクノート" }, + chalkboard: { zh: "粉笔黑板", zh_tw: "粉筆黑板", en: "Chalkboard", ja: "チョークボード" }, + watercolor: { zh: "水彩", zh_tw: "水彩", en: "Watercolor", ja: "水彩" }, + "warm-scene": { zh: "暖调场景", zh_tw: "暖調場景", en: "Warm scene", ja: "暖色シーン" }, + "screen-print": { zh: "丝网印刷", zh_tw: "絲網印刷", en: "Screen print", ja: "スクリーンプリント" }, + "fantasy-animation": { zh: "幻想动画", zh_tw: "幻想動畫", en: "Fantasy animation", ja: "ファンタジーアニメ" }, + "pixel-art": { zh: "像素艺术", zh_tw: "像素藝術", en: "Pixel art", ja: "ピクセルアート" }, + nature: { zh: "自然有机", zh_tw: "自然有機", en: "Nature", ja: "自然・オーガニック" }, + "minimalist-swiss": { zh: "瑞士极简", zh_tw: "瑞士極簡", en: "Minimalist Swiss", ja: "スイスミニマル" }, + glassmorphism: { zh: "玻璃拟态", zh_tw: "玻璃擬態", en: "Glassmorphism", ja: "グラスモーフィズム" }, + "vintage-poster": { zh: "复古海报", zh_tw: "復古海報", en: "Vintage poster", ja: "ヴィンテージポスター" }, + "paper-cut": { zh: "剪纸拼贴", zh_tw: "剪紙拼貼", en: "Paper cut", ja: "ペーパーカット" } } }; function localized(obj, base) { if (!obj) return ""; - var langKey = base + "_" + LANG; + var langKey = base + "_" + langField(LANG); if (obj[langKey] != null) return obj[langKey]; var order = LANG_FALLBACK[LANG] || LANG_FALLBACK.en; var i; @@ -663,13 +864,13 @@ } function applyStaticTranslations() { - document.documentElement.setAttribute("lang", LANG === "zh" ? "zh-CN" : (LANG === "ja" ? "ja" : "en")); + document.documentElement.setAttribute("lang", LANG === "zh" ? "zh-CN" : (LANG === "zh-TW" ? "zh-TW" : (LANG === "ja" ? "ja" : "en"))); document.querySelectorAll("[data-i18n]").forEach(function (node) { node.textContent = t(node.getAttribute("data-i18n")); }); } - var LANG_NAMES = { zh: "中文", en: "English", ja: "日本語" }; + var LANG_NAMES = { zh: "中文", en: "English", ja: "日本語", "zh-TW": "繁體中文" }; function refreshLangToggle(toggleBtn) { // Custom dropdown (OS-independent): button shows the CURRENT language. @@ -1447,7 +1648,7 @@ } function setUiLanguageAttributes(node) { - node.lang = LANG === "zh" ? "zh-CN" : (LANG === "ja" ? "ja-JP" : "en-US"); + node.lang = LANG === "zh" ? "zh-CN" : (LANG === "zh-TW" ? "zh-TW" : (LANG === "ja" ? "ja-JP" : "en-US")); node.dir = "ltr"; } @@ -3117,7 +3318,7 @@ var signatureMatch = -1; var stateSignature = typographySignature(STATE.typography || {}); if (STATE.typography && STATE.typography.name !== "custom") cands.forEach(function (c, i) { - var sameName = [localized(c, "name"), c.name_zh, c.name_en, c.name_ja] + var sameName = [localized(c, "name"), c.name_zh, c.name_zh_tw, c.name_en, c.name_ja] .some(function (name) { return name === STATE.typography.name; }); if (!sameName && c.name && typeof c.name === "object") { sameName = Object.keys(c.name).some(function (key) { @@ -4187,7 +4388,8 @@ function applyServerLanguage(data) { var requested = data && data.lang; - if (requested !== "zh" && requested !== "en" && requested !== "ja") return; + if (requested !== "zh" && requested !== "en" && requested !== "ja" && + requested !== "zh-TW") return; var hasStored = false; try { hasStored = !!window.localStorage.getItem("ppt_lang"); } catch (e) { /* ignore */ } if (hasStored) return; @@ -4239,7 +4441,7 @@ var chooseLang = function (v) { setMenuOpen(false); toggleBtn.focus(); - if (v !== "ja" && v !== "en" && v !== "zh") return; + if (v !== "ja" && v !== "en" && v !== "zh" && v !== "zh-TW") return; if (v === LANG) return; LANG = v; try { window.localStorage.setItem("ppt_lang", LANG); } catch (e2) { /* ignore */ } diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/confirm_ui/static/catalogs.json b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/confirm_ui/static/catalogs.json index 76e69ec8..a6b7b514 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/confirm_ui/static/catalogs.json +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/confirm_ui/static/catalogs.json @@ -1,15 +1,17 @@ { - "_comment": "Enumerable (finite) option universe for the confirm page. Served by Flask static at /static/catalogs.json; the front-end prefers /api/catalogs when the server provides it. These fields list fixed options and the AI marks one as recommended via the active recommendation stage's `recommend` object. Color, coordinated typography recommendations, and generated-image style remain generative. `fonts` supplies the manual typography dropdowns outside those recommendations; users may still enter another installed font. 'canvas' mirrors scripts/config.py CANVAS_FORMATS — keep in sync. User-facing catalog text supports label_zh/label_en/label_ja, desc_zh/desc_en/desc_ja, group_zh/group_en/group_ja.", + "_comment": "Enumerable (finite) option universe for the confirm page. Served by Flask static at /static/catalogs.json; the front-end prefers /api/catalogs when the server provides it. These fields list fixed options and the AI marks one as recommended via the active recommendation stage's `recommend` object. Color, coordinated typography recommendations, and generated-image style remain generative. `fonts` supplies the manual typography dropdowns outside those recommendations; users may still enter another installed font. 'canvas' mirrors scripts/config.py CANVAS_FORMATS — keep in sync. User-facing catalog text supports label_zh/label_en/label_ja, desc_zh/desc_en/desc_ja, group_zh/group_en/group_ja; Traditional-Chinese variants use the _zh_tw suffix (label_zh_tw, desc_zh_tw, group_zh_tw, use_zh_tw).", "canvas": [ { "id": "ppt169", "label": "PPT 16:9", "label_zh": "PPT 16:9", + "label_zh_tw": "PPT 16:9", "label_en": "PPT 16:9", "label_ja": "PPT 16:9", "dim": "1280×720", "viewbox": "0 0 1280 720", "use_zh": "现代投影 / 在线演示", + "use_zh_tw": "現代投影 / 線上簡報", "use_en": "Modern projectors / online", "use_ja": "現代的なプロジェクター/オンライン発表" }, @@ -17,11 +19,13 @@ "id": "ppt43", "label": "PPT 4:3", "label_zh": "PPT 4:3", + "label_zh_tw": "PPT 4:3", "label_en": "PPT 4:3", "label_ja": "PPT 4:3", "dim": "1024×768", "viewbox": "0 0 1024 768", "use_zh": "传统投影", + "use_zh_tw": "傳統投影", "use_en": "Traditional projectors", "use_ja": "従来型プロジェクター" }, @@ -29,11 +33,13 @@ "id": "wechat", "label": "公众号头图 2.35:1", "label_zh": "公众号头图 2.35:1", + "label_zh_tw": "公眾號頭圖 2.35:1", "label_en": "WeChat Header 2.35:1", "label_ja": "WeChat ヘッダー 2.35:1", "dim": "900×383", "viewbox": "0 0 900 383", "use_zh": "微信公众号文章封面", + "use_zh_tw": "微信公眾號文章封面", "use_en": "WeChat article cover", "use_ja": "WeChat記事のカバー画像" }, @@ -41,11 +47,13 @@ "id": "xiaohongshu", "label": "小红书 3:4", "label_zh": "小红书 3:4", + "label_zh_tw": "小紅書 3:4", "label_en": "RED 3:4", "label_ja": "小紅書(RED)3:4", "dim": "1242×1660", "viewbox": "0 0 1242 1660", "use_zh": "知识分享 / 种草封面", + "use_zh_tw": "知識分享 / 種草封面", "use_en": "Knowledge sharing", "use_ja": "知識共有/おすすめ紹介カバー" }, @@ -53,11 +61,13 @@ "id": "moments", "label": "社交方图 1:1", "label_zh": "社交方图 1:1", + "label_zh_tw": "社交方圖 1:1", "label_en": "Social Square 1:1", "label_ja": "SNS正方形 1:1", "dim": "1080×1080", "viewbox": "0 0 1080 1080", "use_zh": "社交媒体方图", + "use_zh_tw": "社群媒體方圖", "use_en": "Social square", "use_ja": "SNS用正方形画像" }, @@ -65,11 +75,13 @@ "id": "story", "label": "竖屏 9:16", "label_zh": "竖屏 9:16", + "label_zh_tw": "直式 9:16", "label_en": "Vertical 9:16", "label_ja": "縦型 9:16", "dim": "1080×1920", "viewbox": "0 0 1080 1920", "use_zh": "短视频 / 竖屏封面", + "use_zh_tw": "短影片 / 直式封面", "use_en": "Short-video / story cover", "use_ja": "ショート動画/ストーリーカバー" }, @@ -77,11 +89,13 @@ "id": "banner", "label": "横幅 16:9", "label_zh": "横幅 16:9", + "label_zh_tw": "橫幅 16:9", "label_en": "Banner 16:9", "label_ja": "バナー 16:9", "dim": "1920×1080", "viewbox": "0 0 1920 1080", "use_zh": "网页横幅 / 大屏", + "use_zh_tw": "網頁橫幅 / 大螢幕", "use_en": "Web banner / big screen", "use_ja": "Webバナー/大画面" }, @@ -89,11 +103,13 @@ "id": "a4", "label": "A4 1:1.41", "label_zh": "A4 1:1.41", + "label_zh_tw": "A4 1:1.41", "label_en": "A4 1:1.41", "label_ja": "A4 1:1.41", "dim": "1240×1754", "viewbox": "0 0 1240 1754", "use_zh": "打印 / 文档导出", + "use_zh_tw": "列印 / 文件匯出", "use_en": "Print / PDF export", "use_ja": "印刷/PDF出力" } @@ -103,6 +119,7 @@ "id": "Microsoft YaHei", "label": "Microsoft YaHei", "label_zh": "微软雅黑", + "label_zh_tw": "微軟雅黑", "label_en": "Microsoft YaHei", "label_ja": "Microsoft YaHei", "locales": ["zh-CN", "zh-SG", "zh-Hans"], @@ -115,6 +132,7 @@ "id": "DengXian", "label": "DengXian", "label_zh": "等线", + "label_zh_tw": "等線", "label_en": "DengXian", "label_ja": "DengXian", "locales": ["zh-CN", "zh-SG", "zh-Hans"], @@ -127,6 +145,7 @@ "id": "STXihei", "label": "STXihei", "label_zh": "华文细黑", + "label_zh_tw": "華文細黑", "label_en": "STXihei", "label_ja": "STXihei", "locales": ["zh-CN", "zh-SG", "zh-Hans"], @@ -139,6 +158,7 @@ "id": "SimHei", "label": "SimHei", "label_zh": "黑体", + "label_zh_tw": "黑體", "label_en": "SimHei", "label_ja": "SimHei", "locales": ["zh-CN", "zh-SG", "zh-Hans"], @@ -151,6 +171,7 @@ "id": "SimSun", "label": "SimSun", "label_zh": "宋体", + "label_zh_tw": "宋體", "label_en": "SimSun", "label_ja": "SimSun", "locales": ["zh-CN", "zh-SG", "zh-Hans"], @@ -163,6 +184,7 @@ "id": "NSimSun", "label": "NSimSun", "label_zh": "新宋体", + "label_zh_tw": "新宋體", "label_en": "NSimSun", "label_ja": "NSimSun", "locales": ["zh-CN", "zh-SG", "zh-Hans"], @@ -175,6 +197,7 @@ "id": "STZhongsong", "label": "STZhongsong", "label_zh": "华文中宋", + "label_zh_tw": "華文中宋", "label_en": "STZhongsong", "label_ja": "STZhongsong", "locales": ["zh-CN", "zh-SG", "zh-Hans"], @@ -187,6 +210,7 @@ "id": "FangSong", "label": "FangSong", "label_zh": "仿宋", + "label_zh_tw": "仿宋", "label_en": "FangSong", "label_ja": "FangSong", "locales": ["zh-CN", "zh-SG", "zh-Hans"], @@ -199,6 +223,7 @@ "id": "STFangsong", "label": "STFangsong", "label_zh": "华文仿宋", + "label_zh_tw": "華文仿宋", "label_en": "STFangsong", "label_ja": "STFangsong", "locales": ["zh-CN", "zh-SG", "zh-Hans"], @@ -211,6 +236,7 @@ "id": "KaiTi", "label": "KaiTi", "label_zh": "楷体", + "label_zh_tw": "楷體", "label_en": "KaiTi", "label_ja": "KaiTi", "locales": ["zh-CN", "zh-SG", "zh-Hans"], @@ -223,6 +249,7 @@ "id": "STKaiti", "label": "STKaiti", "label_zh": "华文楷体", + "label_zh_tw": "華文楷體", "label_en": "STKaiti", "label_ja": "STKaiti", "locales": ["zh-CN", "zh-SG", "zh-Hans"], @@ -235,6 +262,7 @@ "id": "STXingkai", "label": "STXingkai", "label_zh": "华文行楷", + "label_zh_tw": "華文行楷", "label_en": "STXingkai", "label_ja": "STXingkai", "locales": ["zh-CN", "zh-SG", "zh-Hans"], @@ -247,6 +275,7 @@ "id": "STXinwei", "label": "STXinwei", "label_zh": "华文新魏", + "label_zh_tw": "華文新魏", "label_en": "STXinwei", "label_ja": "STXinwei", "locales": ["zh-CN", "zh-SG", "zh-Hans"], @@ -259,6 +288,7 @@ "id": "Microsoft JhengHei", "label": "Microsoft JhengHei", "label_zh": "微软正黑体", + "label_zh_tw": "微軟正黑體", "label_en": "Microsoft JhengHei", "label_ja": "Microsoft JhengHei", "locales": ["zh-TW", "zh-HK", "zh-Hant"], @@ -271,6 +301,7 @@ "id": "PMingLiU", "label": "PMingLiU", "label_zh": "新细明体", + "label_zh_tw": "新細明體", "label_en": "PMingLiU", "label_ja": "PMingLiU", "locales": ["zh-TW", "zh-HK", "zh-Hant"], @@ -283,6 +314,7 @@ "id": "MingLiU", "label": "MingLiU", "label_zh": "细明体", + "label_zh_tw": "細明體", "label_en": "MingLiU", "label_ja": "MingLiU", "locales": ["zh-TW", "zh-HK", "zh-MO", "zh-Hant"], @@ -295,6 +327,7 @@ "id": "MingLiU_HKSCS", "label": "MingLiU_HKSCS", "label_zh": "细明体 HKSCS", + "label_zh_tw": "細明體 HKSCS", "label_en": "MingLiU HKSCS", "label_ja": "MingLiU HKSCS", "locales": ["zh-HK", "zh-Hant"], @@ -307,6 +340,7 @@ "id": "DFKai-SB", "label": "DFKai-SB", "label_zh": "标楷体", + "label_zh_tw": "標楷體", "label_en": "DFKai-SB", "label_ja": "DFKai-SB", "locales": ["zh-TW", "zh-HK", "zh-MO", "zh-Hant"], @@ -319,6 +353,7 @@ "id": "Yu Gothic", "label": "Yu Gothic", "label_zh": "游哥特体", + "label_zh_tw": "游黑體", "label_en": "Yu Gothic", "label_ja": "游ゴシック", "locales": ["ja-JP"], @@ -331,6 +366,7 @@ "id": "Meiryo", "label": "Meiryo", "label_zh": "Meiryo", + "label_zh_tw": "Meiryo", "label_en": "Meiryo", "label_ja": "メイリオ", "locales": ["ja-JP"], @@ -343,6 +379,7 @@ "id": "BIZ UDGothic", "label": "BIZ UDGothic", "label_zh": "BIZ UD哥特体", + "label_zh_tw": "BIZ UD黑體", "label_en": "BIZ UDGothic", "label_ja": "BIZ UDゴシック", "locales": ["ja-JP"], @@ -355,6 +392,7 @@ "id": "BIZ UDPGothic", "label": "BIZ UDPGothic", "label_zh": "BIZ UDP哥特体", + "label_zh_tw": "BIZ UDP黑體", "label_en": "BIZ UDPGothic", "label_ja": "BIZ UDPゴシック", "locales": ["ja-JP"], @@ -367,6 +405,7 @@ "id": "MS Gothic", "label": "MS Gothic", "label_zh": "MS 哥特体", + "label_zh_tw": "MS 黑體", "label_en": "MS Gothic", "label_ja": "MS ゴシック", "locales": ["ja-JP"], @@ -379,6 +418,7 @@ "id": "MS PGothic", "label": "MS PGothic", "label_zh": "MS P哥特体", + "label_zh_tw": "MS P黑體", "label_en": "MS PGothic", "label_ja": "MS Pゴシック", "locales": ["ja-JP"], @@ -391,6 +431,7 @@ "id": "Yu Mincho", "label": "Yu Mincho", "label_zh": "游明朝体", + "label_zh_tw": "游明體", "label_en": "Yu Mincho", "label_ja": "游明朝", "locales": ["ja-JP"], @@ -403,6 +444,7 @@ "id": "BIZ UDMincho Medium", "label": "BIZ UDMincho Medium", "label_zh": "BIZ UD明朝 Medium", + "label_zh_tw": "BIZ UD明體 Medium", "label_en": "BIZ UDMincho Medium", "label_ja": "BIZ UD明朝 Medium", "locales": ["ja-JP"], @@ -415,6 +457,7 @@ "id": "BIZ UDPMincho Medium", "label": "BIZ UDPMincho Medium", "label_zh": "BIZ UDP明朝 Medium", + "label_zh_tw": "BIZ UDP明體 Medium", "label_en": "BIZ UDPMincho Medium", "label_ja": "BIZ UDP明朝 Medium", "locales": ["ja-JP"], @@ -427,6 +470,7 @@ "id": "MS Mincho", "label": "MS Mincho", "label_zh": "MS 明朝体", + "label_zh_tw": "MS 明體", "label_en": "MS Mincho", "label_ja": "MS 明朝", "locales": ["ja-JP"], @@ -439,6 +483,7 @@ "id": "MS PMincho", "label": "MS PMincho", "label_zh": "MS P明朝体", + "label_zh_tw": "MS P明體", "label_en": "MS PMincho", "label_ja": "MS P明朝", "locales": ["ja-JP"], @@ -451,6 +496,7 @@ "id": "Malgun Gothic", "label": "Malgun Gothic", "label_zh": "Malgun Gothic", + "label_zh_tw": "Malgun Gothic", "label_en": "Malgun Gothic", "label_ja": "Malgun Gothic", "locales": ["ko-KR"], @@ -463,6 +509,7 @@ "id": "Microsoft GothicNeo", "label": "Microsoft GothicNeo", "label_zh": "Microsoft GothicNeo", + "label_zh_tw": "Microsoft GothicNeo", "label_en": "Microsoft GothicNeo", "label_ja": "Microsoft GothicNeo", "locales": ["ko-KR"], @@ -475,6 +522,7 @@ "id": "Dotum", "label": "Dotum", "label_zh": "Dotum", + "label_zh_tw": "Dotum", "label_en": "Dotum", "label_ja": "Dotum", "locales": ["ko-KR"], @@ -487,6 +535,7 @@ "id": "Gulim", "label": "Gulim", "label_zh": "Gulim", + "label_zh_tw": "Gulim", "label_en": "Gulim", "label_ja": "Gulim", "locales": ["ko-KR"], @@ -499,6 +548,7 @@ "id": "Batang", "label": "Batang", "label_zh": "Batang", + "label_zh_tw": "Batang", "label_en": "Batang", "label_ja": "Batang", "locales": ["ko-KR"], @@ -511,6 +561,7 @@ "id": "Gungsuh", "label": "Gungsuh", "label_zh": "Gungsuh", + "label_zh_tw": "Gungsuh", "label_en": "Gungsuh", "label_ja": "Gungsuh", "locales": ["ko-KR"], @@ -523,6 +574,7 @@ "id": "BatangChe", "label": "BatangChe", "label_zh": "BatangChe", + "label_zh_tw": "BatangChe", "label_en": "BatangChe", "label_ja": "BatangChe", "locales": ["ko-KR"], @@ -535,6 +587,7 @@ "id": "DotumChe", "label": "DotumChe", "label_zh": "DotumChe", + "label_zh_tw": "DotumChe", "label_en": "DotumChe", "label_ja": "DotumChe", "locales": ["ko-KR"], @@ -547,6 +600,7 @@ "id": "GulimChe", "label": "GulimChe", "label_zh": "GulimChe", + "label_zh_tw": "GulimChe", "label_en": "GulimChe", "label_ja": "GulimChe", "locales": ["ko-KR"], @@ -559,6 +613,7 @@ "id": "GungsuhChe", "label": "GungsuhChe", "label_zh": "GungsuhChe", + "label_zh_tw": "GungsuhChe", "label_en": "GungsuhChe", "label_ja": "GungsuhChe", "locales": ["ko-KR"], @@ -571,6 +626,7 @@ "id": "Arabic Typesetting", "label": "Arabic Typesetting", "label_zh": "Arabic Typesetting", + "label_zh_tw": "Arabic Typesetting", "label_en": "Arabic Typesetting", "label_ja": "Arabic Typesetting", "locales": ["ar", "fa", "ur"], @@ -583,6 +639,7 @@ "id": "Sakkal Majalla", "label": "Sakkal Majalla", "label_zh": "Sakkal Majalla", + "label_zh_tw": "Sakkal Majalla", "label_en": "Sakkal Majalla", "label_ja": "Sakkal Majalla", "locales": ["ar", "fa", "ur"], @@ -595,6 +652,7 @@ "id": "Urdu Typesetting", "label": "Urdu Typesetting", "label_zh": "Urdu Typesetting", + "label_zh_tw": "Urdu Typesetting", "label_en": "Urdu Typesetting", "label_ja": "Urdu Typesetting", "locales": ["ur", "ar", "fa"], @@ -607,6 +665,7 @@ "id": "Gisha", "label": "Gisha", "label_zh": "Gisha", + "label_zh_tw": "Gisha", "label_en": "Gisha", "label_ja": "Gisha", "locales": ["he"], @@ -619,6 +678,7 @@ "id": "David", "label": "David", "label_zh": "David", + "label_zh_tw": "David", "label_en": "David", "label_ja": "David", "locales": ["he"], @@ -631,6 +691,7 @@ "id": "FrankRuehl", "label": "FrankRuehl", "label_zh": "FrankRuehl", + "label_zh_tw": "FrankRuehl", "label_en": "FrankRuehl", "label_ja": "FrankRuehl", "locales": ["he"], @@ -643,6 +704,7 @@ "id": "Nirmala UI", "label": "Nirmala UI", "label_zh": "Nirmala UI", + "label_zh_tw": "Nirmala UI", "label_en": "Nirmala UI", "label_ja": "Nirmala UI", "locales": ["hi", "mr", "ne"], @@ -655,6 +717,7 @@ "id": "Mangal", "label": "Mangal", "label_zh": "Mangal", + "label_zh_tw": "Mangal", "label_en": "Mangal", "label_ja": "Mangal", "locales": ["hi", "mr", "ne"], @@ -667,6 +730,7 @@ "id": "Aparajita", "label": "Aparajita", "label_zh": "Aparajita", + "label_zh_tw": "Aparajita", "label_en": "Aparajita", "label_ja": "Aparajita", "locales": ["hi", "mr", "ne"], @@ -679,6 +743,7 @@ "id": "Kokila", "label": "Kokila", "label_zh": "Kokila", + "label_zh_tw": "Kokila", "label_en": "Kokila", "label_ja": "Kokila", "locales": ["hi", "mr", "ne"], @@ -691,6 +756,7 @@ "id": "Leelawadee UI", "label": "Leelawadee UI", "label_zh": "Leelawadee UI", + "label_zh_tw": "Leelawadee UI", "label_en": "Leelawadee UI", "label_ja": "Leelawadee UI", "locales": ["th"], @@ -703,6 +769,7 @@ "id": "Angsana New", "label": "Angsana New", "label_zh": "Angsana New", + "label_zh_tw": "Angsana New", "label_en": "Angsana New", "label_ja": "Angsana New", "locales": ["th"], @@ -715,6 +782,7 @@ "id": "Cordia New", "label": "Cordia New", "label_zh": "Cordia New", + "label_zh_tw": "Cordia New", "label_en": "Cordia New", "label_ja": "Cordia New", "locales": ["th"], @@ -727,6 +795,7 @@ "id": "Aptos", "label": "Aptos", "label_zh": "Aptos", + "label_zh_tw": "Aptos", "label_en": "Aptos", "label_ja": "Aptos", "locales": ["en", "und-Latn"], @@ -739,6 +808,7 @@ "id": "Arial", "label": "Arial", "label_zh": "Arial", + "label_zh_tw": "Arial", "label_en": "Arial", "label_ja": "Arial", "locales": ["en", "und-Latn"], @@ -751,6 +821,7 @@ "id": "Calibri", "label": "Calibri", "label_zh": "Calibri", + "label_zh_tw": "Calibri", "label_en": "Calibri", "label_ja": "Calibri", "locales": ["en", "und-Latn"], @@ -763,6 +834,7 @@ "id": "Segoe UI", "label": "Segoe UI", "label_zh": "Segoe UI", + "label_zh_tw": "Segoe UI", "label_en": "Segoe UI", "label_ja": "Segoe UI", "locales": ["en", "und-Latn"], @@ -775,6 +847,7 @@ "id": "Verdana", "label": "Verdana", "label_zh": "Verdana", + "label_zh_tw": "Verdana", "label_en": "Verdana", "label_ja": "Verdana", "locales": ["en", "und-Latn"], @@ -787,6 +860,7 @@ "id": "Tahoma", "label": "Tahoma", "label_zh": "Tahoma", + "label_zh_tw": "Tahoma", "label_en": "Tahoma", "label_ja": "Tahoma", "locales": ["en", "und-Latn"], @@ -799,6 +873,7 @@ "id": "Trebuchet MS", "label": "Trebuchet MS", "label_zh": "Trebuchet MS", + "label_zh_tw": "Trebuchet MS", "label_en": "Trebuchet MS", "label_ja": "Trebuchet MS", "locales": ["en", "und-Latn"], @@ -811,6 +886,7 @@ "id": "Candara", "label": "Candara", "label_zh": "Candara", + "label_zh_tw": "Candara", "label_en": "Candara", "label_ja": "Candara", "locales": ["en", "und-Latn"], @@ -823,6 +899,7 @@ "id": "Corbel", "label": "Corbel", "label_zh": "Corbel", + "label_zh_tw": "Corbel", "label_en": "Corbel", "label_ja": "Corbel", "locales": ["en", "und-Latn"], @@ -835,6 +912,7 @@ "id": "Bahnschrift", "label": "Bahnschrift", "label_zh": "Bahnschrift", + "label_zh_tw": "Bahnschrift", "label_en": "Bahnschrift", "label_ja": "Bahnschrift", "locales": ["en", "und-Latn"], @@ -847,6 +925,7 @@ "id": "Georgia", "label": "Georgia", "label_zh": "Georgia", + "label_zh_tw": "Georgia", "label_en": "Georgia", "label_ja": "Georgia", "locales": ["en", "und-Latn"], @@ -859,6 +938,7 @@ "id": "Times New Roman", "label": "Times New Roman", "label_zh": "Times New Roman", + "label_zh_tw": "Times New Roman", "label_en": "Times New Roman", "label_ja": "Times New Roman", "locales": ["en", "und-Latn"], @@ -871,6 +951,7 @@ "id": "Cambria", "label": "Cambria", "label_zh": "Cambria", + "label_zh_tw": "Cambria", "label_en": "Cambria", "label_ja": "Cambria", "locales": ["en", "und-Latn"], @@ -883,6 +964,7 @@ "id": "Constantia", "label": "Constantia", "label_zh": "Constantia", + "label_zh_tw": "Constantia", "label_en": "Constantia", "label_ja": "Constantia", "locales": ["en", "und-Latn"], @@ -895,6 +977,7 @@ "id": "Consolas", "label": "Consolas", "label_zh": "Consolas", + "label_zh_tw": "Consolas", "label_en": "Consolas", "label_ja": "Consolas", "locales": ["en", "und-Latn"], @@ -907,6 +990,7 @@ "id": "Courier New", "label": "Courier New", "label_zh": "Courier New", + "label_zh_tw": "Courier New", "label_en": "Courier New", "label_ja": "Courier New", "locales": ["en", "und-Latn"], @@ -921,9 +1005,11 @@ "id": "pyramid", "label": "pyramid", "label_zh": "金字塔", + "label_zh_tw": "金字塔", "label_en": "pyramid", "label_ja": "ピラミッド", "desc_zh": "结论先行、相互独立且完全穷尽的论证、每个数据都带比较。适合决策、分析、战略、汇报。", + "desc_zh_tw": "結論先行、相互獨立且完全窮盡的論證、每個數據都帶比較。適合決策、分析、戰略、報告。", "desc_en": "Lead with the answer, use MECE reasoning, and compare every key data point. Best for decisions, analysis, strategy, and reporting.", "desc_ja": "結論を先に示し、MECEな論理構成で、主要データは必ず比較を添える。意思決定・分析・戦略・報告に最適。" }, @@ -931,9 +1017,11 @@ "id": "narrative", "label": "narrative", "label_zh": "叙事", + "label_zh_tw": "敘事", "label_en": "narrative", "label_ja": "ナラティブ", "desc_zh": "情境、张力、解决方案形成故事弧线,保留悬念与转折。适合路演、案例、品牌、融资。", + "desc_zh_tw": "情境、張力、解決方案形成故事弧線,保留懸念與轉折。適合路演、案例、品牌、融資。", "desc_en": "Build a story arc from context to tension to resolution, with suspense and turns. Best for roadshows, cases, brand stories, and fundraising.", "desc_ja": "状況設定から緊張、解決へとストーリーアークを描き、意外性や転換を残す。ロードショー・事例紹介・ブランドストーリー・資金調達向け。" }, @@ -941,9 +1029,11 @@ "id": "instructional", "label": "instructional", "label_zh": "教学", + "label_zh_tw": "教學", "label_en": "instructional", "label_ja": "教育・解説", "desc_zh": "概念拆解、分步推进、并列讲解。适合培训、教程、科普、知识分享。", + "desc_zh_tw": "概念拆解、分步推進、並列講解。適合培訓、教程、科普、知識分享。", "desc_en": "Break concepts down, advance step by step, and explain parallel ideas clearly. Best for training, tutorials, popular science, and knowledge sharing.", "desc_ja": "概念を分解し、段階的に進め、並列する要素を明確に説明する。研修・チュートリアル・科学解説・知識共有に最適。" }, @@ -951,9 +1041,11 @@ "id": "showcase", "label": "showcase", "label_zh": "展演", + "label_zh_tw": "展演", "label_en": "showcase", "label_ja": "ショーケース", "desc_zh": "视觉主导,大图、大数和情绪节奏优先。适合发布、品牌秀、活动。", + "desc_zh_tw": "視覺主導,大圖、大數和情緒節奏優先。適合發表、品牌秀、活動。", "desc_en": "Use visual rhythm, large images, and strong numbers as the lead. Best for launches, brand showcases, and events.", "desc_ja": "ビジュアル主導で、大きな画像・大きな数字・感情のリズムを優先する。発表会・ブランドショー・イベント向け。" }, @@ -961,9 +1053,11 @@ "id": "briefing", "label": "briefing", "label_zh": "简报", + "label_zh_tw": "簡報", "label_en": "briefing", "label_ja": "ブリーフィング", "desc_zh": "中性完整、便于速览,采用主题式标题和均匀权重。适合周报、参考材料、常见问题、会议包。", + "desc_zh_tw": "中性完整、便於速覽,採用主題式標題和均勻權重。適合週報、參考材料、常見問題、會議包。", "desc_en": "Stay neutral, complete, and scannable with topical headings and balanced weight. Best for weekly reports, reference packs, FAQs, and meeting decks.", "desc_ja": "中立的かつ網羅的で一覧しやすく、トピック見出しと均等な重み付けを用いる。週次報告・参考資料・FAQ・会議資料に最適。" } @@ -972,6 +1066,7 @@ { "group": "Corporate / product", "group_zh": "企业 / 产品", + "group_zh_tw": "企業 / 產品", "group_en": "Corporate / product", "group_ja": "企業/プロダクト", "items": [ @@ -979,9 +1074,11 @@ "id": "swiss-minimal", "label": "swiss-minimal", "label_zh": "瑞士极简", + "label_zh_tw": "瑞士極簡", "label_en": "swiss-minimal", "label_ja": "スイス・ミニマル", "desc_zh": "网格锁定、锐利层级、大留白、少装饰。", + "desc_zh_tw": "網格鎖定、銳利層級、大留白、少裝飾。", "desc_en": "Grid-locked layout, sharp hierarchy, generous whitespace, and minimal decoration.", "desc_ja": "グリッドに沿ったレイアウト、明快な階層、余白を活かした装飾の少ないデザイン。" }, @@ -989,9 +1086,11 @@ "id": "soft-rounded", "label": "soft-rounded", "label_zh": "柔和圆角", + "label_zh_tw": "柔和圓角", "label_en": "soft-rounded", "label_ja": "ソフト・ラウンド", "desc_zh": "圆角卡片、柔和投影、亲和现代。", + "desc_zh_tw": "圓角卡片、柔和陰影、親和現代。", "desc_en": "Rounded cards, soft shadows, and a friendly modern tone.", "desc_ja": "角丸のカード、柔らかい影、親しみやすいモダンな雰囲気。" }, @@ -999,9 +1098,11 @@ "id": "glassmorphism", "label": "glassmorphism", "label_zh": "玻璃拟态", + "label_zh_tw": "玻璃擬態", "label_en": "glassmorphism", "label_ja": "グラスモーフィズム", "desc_zh": "半透明玻璃面板、渐变光感、漂浮层次。", + "desc_zh_tw": "半透明玻璃面板、漸變光感、漂浮層次。", "desc_en": "Translucent glass panels, gradient light, and floating depth.", "desc_ja": "半透明のガラスパネル、グラデーションの光、浮遊感のある奥行き。" }, @@ -1009,9 +1110,11 @@ "id": "dark-tech", "label": "dark-tech", "label_zh": "深色科技", + "label_zh_tw": "深色科技", "label_en": "dark-tech", "label_ja": "ダークテック", "desc_zh": "深色画布、发光强调、几何精确。", + "desc_zh_tw": "深色畫布、發光強調、幾何精確。", "desc_en": "Dark canvas, glowing accents, and precise geometry.", "desc_ja": "ダークな背景、光るアクセント、精密な幾何学表現。" }, @@ -1019,9 +1122,11 @@ "id": "blueprint", "label": "blueprint", "label_zh": "蓝图", + "label_zh_tw": "藍圖", "label_en": "blueprint", "label_ja": "ブループリント", "desc_zh": "深底蓝图线稿、等距结构、工程标注。", + "desc_zh_tw": "深底藍圖線稿、等距結構、工程標註。", "desc_en": "Dark blueprint linework, isometric structure, and engineering annotations.", "desc_ja": "濃紺の設計図風の線画、アイソメトリック構造、技術的な注記。" } @@ -1030,6 +1135,7 @@ { "group": "Editorial / publication", "group_zh": "编辑 / 出版", + "group_zh_tw": "編輯 / 出版", "group_en": "Editorial / publication", "group_ja": "エディトリアル/出版", "items": [ @@ -1037,9 +1143,11 @@ "id": "editorial", "label": "editorial", "label_zh": "编辑出版", + "label_zh_tw": "編輯出版", "label_en": "editorial", "label_ja": "エディトリアル", "desc_zh": "杂志式层级、栏线、衬线与无衬线交织。", + "desc_zh_tw": "雜誌式層級、欄線、襯線與無襯線交織。", "desc_en": "Magazine hierarchy, column rules, and a serif/sans-serif mix.", "desc_ja": "雑誌のような階層構造、段組み罫線、セリフ・サンセリフの混在。" }, @@ -1047,9 +1155,11 @@ "id": "photo-editorial", "label": "photo-editorial", "label_zh": "摄影编辑", + "label_zh_tw": "攝影編輯", "label_en": "photo-editorial", "label_ja": "フォトエディトリアル", "desc_zh": "满版摄影主导,文字点缀与图注配合。", + "desc_zh_tw": "滿版攝影主導,文字點綴與圖說配合。", "desc_en": "Full-bleed photography leads, supported by light text and captions.", "desc_ja": "裁ち落とし写真を主役に、控えめなテキストとキャプションで補う。" }, @@ -1057,9 +1167,11 @@ "id": "data-journalism", "label": "data-journalism", "label_zh": "数据新闻", + "label_zh_tw": "數據新聞", "label_en": "data-journalism", "label_ja": "データジャーナリズム", "desc_zh": "多栏微图表、侧栏、来源线、信息密度高。", + "desc_zh_tw": "多欄微圖表、側欄、來源線、資訊密度高。", "desc_en": "Multi-column microcharts, sidebars, source lines, and dense information.", "desc_ja": "多段組みの小型チャート、サイドバー、出典表記、高い情報密度。" }, @@ -1067,9 +1179,11 @@ "id": "brutalist", "label": "brutalist", "label_zh": "粗野主义", + "label_zh_tw": "粗野主義", "label_en": "brutalist", "label_ja": "ブルータリズム", "desc_zh": "报纸密度、粗线框、原始结构、扁平表达。", + "desc_zh_tw": "報紙密度、粗線框、原始結構、扁平表達。", "desc_en": "Newspaper-like density, heavy rules, raw structure, and flat treatment.", "desc_ja": "新聞のような情報密度、太い罫線、素朴な構造、フラットな表現。" } @@ -1078,6 +1192,7 @@ { "group": "Expressive / print", "group_zh": "表现 / 印刷", + "group_zh_tw": "表現 / 印刷", "group_en": "Expressive / print", "group_ja": "表現的/印刷", "items": [ @@ -1085,9 +1200,11 @@ "id": "memphis", "label": "memphis", "label_zh": "孟菲斯", + "label_zh_tw": "孟菲斯", "label_en": "memphis", "label_ja": "メンフィス", "desc_zh": "撞色块、几何碎片、粗描边。", + "desc_zh_tw": "撞色塊、幾何碎片、粗描邊。", "desc_en": "Contrasting color blocks, geometric scraps, and heavy outlines.", "desc_ja": "コントラストの強い色面、幾何学的な断片、太いアウトライン。" }, @@ -1095,9 +1212,11 @@ "id": "zine", "label": "zine", "label_zh": "小刊", + "label_zh_tw": "小刊", "label_en": "zine", "label_ja": "ジン(自主制作誌)", "desc_zh": "孔版印刷错位、半调、有限色、印刷颗粒。", + "desc_zh_tw": "孔版印刷錯位、半色調、有限色、印刷顆粒。", "desc_en": "Riso offsets, halftones, limited colors, and print grain.", "desc_ja": "リソグラフのズレ、ハーフトーン、限られた色数、印刷の粒感。" }, @@ -1105,9 +1224,11 @@ "id": "vintage-poster", "label": "vintage-poster", "label_zh": "复古海报", + "label_zh_tw": "復古海報", "label_en": "vintage-poster", "label_ja": "ヴィンテージポスター", "desc_zh": "中世纪扁平色块、半调、复古几何暖意。", + "desc_zh_tw": "二十世紀中期的扁平色塊、半色調與暖調復古幾何。", "desc_en": "Mid-century flat color blocks, halftones, and warm vintage geometry.", "desc_ja": "ミッドセンチュリー調のフラットな色面、ハーフトーン、温かみのあるレトロな幾何学模様。" }, @@ -1115,9 +1236,11 @@ "id": "paper-cut", "label": "paper-cut", "label_zh": "剪纸", + "label_zh_tw": "剪紙", "label_en": "paper-cut", "label_ja": "切り絵", "desc_zh": "层叠剪纸、层间柔影、手作质感。", + "desc_zh_tw": "層疊剪紙、層間柔影、手作質感。", "desc_en": "Layered cut paper, soft inter-layer shadows, and a handmade feel.", "desc_ja": "重なり合う切り紙、層間の柔らかな影、手作り感のある質感。" } @@ -1126,6 +1249,7 @@ { "group": "Hand-drawn / brush", "group_zh": "手绘 / 笔触", + "group_zh_tw": "手繪 / 筆觸", "group_en": "Hand-drawn / brush", "group_ja": "手描き/筆致", "items": [ @@ -1133,9 +1257,11 @@ "id": "sketch-notes", "label": "sketch-notes", "label_zh": "手绘笔记", + "label_zh_tw": "手繪筆記", "label_en": "sketch-notes", "label_ja": "手描きノート", "desc_zh": "暖纸底、涂鸦线条、柔和彩块。", + "desc_zh_tw": "暖紙底、塗鴉線條、柔和彩塊。", "desc_en": "Warm paper, doodle lines, and soft color blocks.", "desc_ja": "温かみのある紙の質感、落書き風の線、柔らかい色面。" }, @@ -1143,9 +1269,11 @@ "id": "ink-notes", "label": "ink-notes", "label_zh": "墨迹笔记", + "label_zh_tw": "墨跡筆記", "label_en": "ink-notes", "label_ja": "インクノート", "desc_zh": "浅底、黑色手写墨迹、稀疏语义强调。", + "desc_zh_tw": "淺底、黑色手寫墨跡、稀疏語義強調。", "desc_en": "Light background, black handwritten ink, and sparse semantic emphasis.", "desc_ja": "明るい背景に黒の手書きインク、要所を絞った強調表現。" }, @@ -1153,9 +1281,11 @@ "id": "chalkboard", "label": "chalkboard", "label_zh": "黑板", + "label_zh_tw": "黑板", "label_en": "chalkboard", "label_ja": "黒板", "desc_zh": "深板岩底、粉笔笔触、粉彩强调。", + "desc_zh_tw": "深板岩底、粉筆筆觸、粉彩強調。", "desc_en": "Dark slate surface, chalk strokes, and pastel emphasis.", "desc_ja": "濃いスレート調の背景に、チョークの筆致とパステルの強調色。" }, @@ -1163,9 +1293,11 @@ "id": "ink-wash", "label": "ink-wash", "label_zh": "水墨", + "label_zh_tw": "水墨", "label_en": "ink-wash", "label_ja": "水墨画", "desc_zh": "宣纸留白、笔触、印章、静气,新中式表达。", + "desc_zh_tw": "宣紙留白、筆觸、印章、靜氣,新中式表達。", "desc_en": "Rice-paper whitespace, brushwork, seals, and a quiet contemporary Chinese tone.", "desc_ja": "画仙紙の余白、筆致、落款印、静謐な現代中国風の表現。" } @@ -1174,6 +1306,7 @@ { "group": "Specialty", "group_zh": "特殊风格", + "group_zh_tw": "特殊風格", "group_en": "Specialty", "group_ja": "特殊スタイル", "items": [ @@ -1181,9 +1314,11 @@ "id": "pixel-art", "label": "pixel-art", "label_zh": "像素风", + "label_zh_tw": "像素風", "label_en": "pixel-art", "label_ja": "ピクセルアート", "desc_zh": "严格像素网格、块状形体、有限色、扁平表达。", + "desc_zh_tw": "嚴格像素網格、塊狀形體、有限色、扁平表達。", "desc_en": "Strict pixel grid, blocky shapes, limited colors, and flat treatment.", "desc_ja": "厳密なピクセルグリッド、ブロック状の形状、限られた色数、フラットな表現。" } @@ -1195,9 +1330,11 @@ "id": "chunk-filled", "label": "chunk-filled", "label_zh": "几何实心图标", + "label_zh_tw": "幾何實心圖示", "label_en": "chunk-filled", "label_ja": "幾何学的塗りつぶしアイコン", "desc_zh": "实心、直线几何、锐利厚重,适合科技、工程、企业结构图。", + "desc_zh_tw": "實心、直線幾何、銳利厚重,適合科技、工程、企業結構圖。", "desc_en": "Solid, straight, geometric, sharp, and heavy. Good for tech, engineering, and corporate structure diagrams.", "desc_ja": "塗りつぶし・直線的な幾何形状で、鋭くしっかりした印象。テック、エンジニアリング、企業組織図に適する。" }, @@ -1205,9 +1342,11 @@ "id": "tabler-filled", "label": "tabler-filled", "label_zh": "圆润实心图标", + "label_zh_tw": "圓潤實心圖示", "label_en": "tabler-filled", "label_ja": "丸みのある塗りつぶしアイコン", "desc_zh": "实心、圆润曲线、中等视觉重量,适合亲和现代风格。", + "desc_zh_tw": "實心、圓潤曲線、中等視覺重量,適合親和現代風格。", "desc_en": "Solid, rounded, and medium-weight. Good for friendly modern styles.", "desc_ja": "塗りつぶし・丸みのある曲線で、中程度の視覚的な重み。親しみやすいモダンなスタイルに適する。" }, @@ -1215,9 +1354,11 @@ "id": "tabler-outline", "label": "tabler-outline", "label_zh": "线性描边图标", + "label_zh_tw": "線性描邊圖示", "label_en": "tabler-outline", "label_ja": "線形アウトラインアイコン", "desc_zh": "线性描边,轻盈精致,适合屏幕阅读和编辑型图标。", + "desc_zh_tw": "線性描邊,輕盈精緻,適合螢幕閱讀和編輯型圖示。", "desc_en": "Linear stroke, light and refined. Good for screen reading and editable icons.", "desc_ja": "線形のストロークで、軽やかで洗練された印象。画面表示や編集用アイコンに適する。" }, @@ -1225,9 +1366,11 @@ "id": "phosphor-duotone", "label": "phosphor-duotone", "label_zh": "双色层次图标", + "label_zh_tw": "雙色層次圖示", "label_en": "phosphor-duotone", "label_ja": "デュオトーン階調アイコン", "desc_zh": "双色层次、中等重量,适合现代产品和平台类表达。", + "desc_zh_tw": "雙色層次、中等重量,適合現代產品和平台類表達。", "desc_en": "Two-tone layering with medium weight. Good for modern product and platform narratives.", "desc_ja": "2色の階調表現で中程度の重み。モダンなプロダクトやプラットフォームの説明に適する。" }, @@ -1235,9 +1378,11 @@ "id": "emoji", "label": "Emoji", "label_zh": "表情符号", + "label_zh_tw": "表情符號", "label_en": "Emoji", "label_ja": "絵文字", "desc_zh": "系统表情符号,适合轻量、社交、教学或快速识别场景;正式企业 / 咨询风谨慎使用。", + "desc_zh_tw": "系統表情符號,適合輕量、社交、教學或快速識別場景;正式企業 / 諮詢風謹慎使用。", "desc_en": "System emoji for lightweight, social, instructional, or quick-recognition contexts; use carefully in formal corporate or consulting decks.", "desc_ja": "システム絵文字。軽やかなSNS・教育・素早い視認が求められる場面向き。フォーマルな企業/コンサル資料では慎重に使用すること。" }, @@ -1245,6 +1390,7 @@ "id": "none", "label": "不用图标", "label_zh": "不用图标", + "label_zh_tw": "不用圖示", "label_en": "No icons", "label_ja": "アイコンなし" } @@ -1254,6 +1400,7 @@ "id": "ai", "label": "AI 生成", "label_zh": "生成配图", + "label_zh_tw": "生成配圖", "label_en": "AI-generated", "label_ja": "AI生成" }, @@ -1261,6 +1408,7 @@ "id": "web", "label": "Web 来源", "label_zh": "网络来源", + "label_zh_tw": "網路來源", "label_en": "Web-sourced", "label_ja": "Web由来" }, @@ -1268,6 +1416,7 @@ "id": "provided", "label": "用户提供", "label_zh": "用户提供", + "label_zh_tw": "使用者提供", "label_en": "User-provided", "label_ja": "ユーザー提供" }, @@ -1275,6 +1424,7 @@ "id": "placeholder", "label": "占位符", "label_zh": "占位符", + "label_zh_tw": "佔位符", "label_en": "Placeholder", "label_ja": "プレースホルダー" }, @@ -1282,6 +1432,7 @@ "id": "none", "label": "不使用图片", "label_zh": "不使用图片", + "label_zh_tw": "不使用圖片", "label_en": "No images", "label_ja": "画像なし" } @@ -1291,6 +1442,7 @@ "id": "auto", "label": "Automatic Path A → Path B → Offline Manual", "label_zh": "自动选择", + "label_zh_tw": "自動選擇", "label_en": "Automatic Path A → Path B → Offline Manual", "label_ja": "自動選択(Path A → Path B → オフライン手動)" }, @@ -1298,9 +1450,11 @@ "id": "api", "label": "Path A", "label_zh": "接口后端", + "label_zh_tw": "API 後端", "label_en": "Path A", "label_ja": "Path A", "desc_zh": "强制走接口后端,第 5 步运行 image_gen.py(需已配置 IMAGE_BACKEND)。", + "desc_zh_tw": "強制走 API 後端,第 5 步執行 image_gen.py(需已配置 IMAGE_BACKEND)。", "desc_en": "Force the API backend — image_gen.py runs in Step 5 (requires IMAGE_BACKEND).", "desc_ja": "APIバックエンドを強制使用。ステップ5でimage_gen.pyを実行(IMAGE_BACKENDの設定が必要)。" }, @@ -1308,9 +1462,11 @@ "id": "host-native", "label": "Path B", "label_zh": "宿主原生工具", + "label_zh_tw": "宿主原生工具", "label_en": "Path B", "label_ja": "Path B", "desc_zh": "强制使用当前环境的原生图像工具生成(即使配置了 IMAGE_BACKEND 也跳过接口);需宿主提供原生图像工具(Codex / Claude Code 等)。", + "desc_zh_tw": "強制使用目前環境的原生影像工具生成(即使配置了 IMAGE_BACKEND 也跳過 API);需宿主提供原生影像工具(Codex / Claude Code 等)。", "desc_en": "Force the host's native image tool (skips the API even if IMAGE_BACKEND is set); requires a host with a native image tool (Codex / Claude Code / similar).", "desc_ja": "現在の環境のネイティブ画像ツールを強制使用(IMAGE_BACKENDが設定されていてもAPIをスキップ)。ネイティブ画像ツールを持つホスト(Codex/Claude Codeなど)が必要。" }, @@ -1318,9 +1474,11 @@ "id": "manual", "label": "Offline Manual", "label_zh": "离线手动", + "label_zh_tw": "離線手動", "label_en": "Offline Manual", "label_ja": "オフライン手動", "desc_zh": "机制:写入图片提示词文件;用户在外部生成后放入项目图片目录。", + "desc_zh_tw": "機制:寫入圖片提示詞檔案;使用者在外部生成後放入專案圖片目錄。", "desc_en": "Prompts written to images/image_prompts.json; user generates externally and places files in project/images/.", "desc_ja": "images/image_prompts.jsonにプロンプトを書き出し、ユーザーが外部で生成した画像をproject/images/に配置する方式。" } @@ -1330,9 +1488,11 @@ "id": "mixed", "label": "mixed", "label_zh": "混合", + "label_zh_tw": "混合", "label_en": "mixed", "label_ja": "混合", "desc_zh": "复杂公式渲染为图片;简单行内公式保持为可编辑文本或字符。", + "desc_zh_tw": "複雜公式渲染為圖片;簡單行內公式保持為可編輯文字或字元。", "desc_en": "Render complex formula-worthy expressions to PNG; keep simple inline math as editable text / Unicode.", "desc_ja": "複雑な数式はPNG画像として描画し、簡単な行内数式は編集可能なテキスト/Unicode文字のまま残す。" }, @@ -1340,9 +1500,11 @@ "id": "render-all", "label": "render-all", "label_zh": "全部渲染", + "label_zh_tw": "全部渲染", "label_en": "render-all", "label_ja": "すべて画像化", "desc_zh": "所有需要按公式处理的表达式都渲染为图片。", + "desc_zh_tw": "所有需要按公式處理的運算式都渲染為圖片。", "desc_en": "Render every formula-worthy expression to PNG.", "desc_ja": "数式として扱うべき表現はすべてPNG画像として描画する。" }, @@ -1350,9 +1512,11 @@ "id": "text-only", "label": "text-only", "label_zh": "仅文本", + "label_zh_tw": "僅文字", "label_en": "text-only", "label_ja": "テキストのみ", "desc_zh": "不渲染公式;表达式保持为可编辑文本或字符。", + "desc_zh_tw": "不渲染公式;運算式保持為可編輯文字或字元。", "desc_en": "Do not render formulas; keep expressions as editable text / Unicode.", "desc_ja": "数式は画像化せず、編集可能なテキスト/Unicode文字のまま保持する。" } @@ -1362,6 +1526,7 @@ "id": "continuous", "label": "continuous", "label_zh": "连续模式", + "label_zh_tw": "連續模式", "label_en": "continuous", "label_ja": "連続モード" }, @@ -1369,6 +1534,7 @@ "id": "split", "label": "split", "label_zh": "分段模式", + "label_zh_tw": "分段模式", "label_en": "split", "label_ja": "分割モード" } @@ -1378,9 +1544,11 @@ "id": "text", "label": "text", "label_zh": "文字型 · 近读", + "label_zh_tw": "文字型 · 近讀", "label_en": "text / read-close", "label_ja": "文書型・近距離閲覧", "desc_zh": "页面脱离讲者也能独立读懂:使用完整句、短段落、图注、表格和必要细节;bullet 只用于真正并列的项目。", + "desc_zh_tw": "頁面脫離講者也能獨立讀懂:使用完整句、短段落、圖說、表格和必要細節;bullet 只用於真正並列的項目。", "desc_en": "The page stands alone without a presenter: use complete sentences, short prose, captions, tables, and necessary detail; reserve bullets for genuinely parallel items.", "desc_ja": "話者なしでもページ単体で理解できる構成。完全な文、短い段落、注釈、表、必要な細部を用い、箇条書きは本当に並列な項目だけに使う。" }, @@ -1388,9 +1556,11 @@ "id": "balanced", "label": "balanced", "label_zh": "均衡 · 商务", + "label_zh_tw": "均衡 · 商務", "label_en": "balanced / business", "label_ja": "バランス型・ビジネス", "desc_zh": "页面与讲者共同承担信息:一条主结论配合简短说明、结构化证据或必要列表,适合路演和业务评审。", + "desc_zh_tw": "頁面與講者共同承擔資訊:一個主結論配合簡短說明、結構化證據或必要列表,適合路演和業務評審。", "desc_en": "The page and presenter share the load: pair one primary claim with concise explanation, structured evidence, or a necessary list. Best for roadshows and business reviews.", "desc_ja": "ページと話者で情報を分担する構成。主張を一つ置き、短い説明、構造化した根拠、または必要なリストを組み合わせる。ロードショーや事業レビュー向け。" }, @@ -1398,9 +1568,11 @@ "id": "presentation", "label": "presentation", "label_zh": "展示型 · 演讲", + "label_zh_tw": "展示型 · 演講", "label_en": "presentation / keynote", "label_ja": "プレゼン型・講演", "desc_zh": "讲者与视觉承担主要表达:一页一意,以简短主张、关键词、大图或大数字为主,解释进入讲述或备注,避免段落堆积。", + "desc_zh_tw": "講者與視覺承擔主要表達:一頁一意,以簡短主張、關鍵字、大圖或大數字為主,解釋進入講述或備註,避免段落堆積。", "desc_en": "The presenter and visuals carry the explanation: use one idea per page, concise claims, keywords, large visuals, or hero numbers; move detail into speech or notes and avoid paragraph dumps.", "desc_ja": "話者とビジュアルが主に説明を担う構成。1枚1メッセージで、短い主張、キーワード、大きな図や数値を中心にし、詳細は話者またはノートに置いて段落の詰め込みを避ける。" } diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/confirm_ui/static/index.html b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/confirm_ui/static/index.html index d442e88b..7a1fbb12 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/confirm_ui/static/index.html +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/confirm_ui/static/index.html @@ -30,6 +30,7 @@ diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/docs/confirm_ui.md b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/docs/confirm_ui.md index c937583e..a25af9d0 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/docs/confirm_ui.md +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/docs/confirm_ui.md @@ -325,7 +325,7 @@ Direction-local custom projections apply to mode, visual style, and generated-im ## Catalogs — `static/catalogs.json` (the finite option universe) -The front-end loads `/api/catalogs` (served by the confirm server) and falls back to the static `/static/catalogs.json` if that route is unavailable. `/api/catalogs` returns the static file **with the `canvas` list synced live from `config.py CANVAS_FORMATS`** — the set of formats and their `dim` come from config (single source of truth, zero drift), while trilingual labels / use text stay in catalogs.json (a plain fallback label is synthesized for any new id config adds). Keys: `canvas`, `modes`, `visual_styles` (grouped), `icons`, `image_usage`, `image_ai_path`, `formula_policy`, `generation_mode`, `delivery_purpose`. Each entry is `{ "id", "label", "label_zh", "label_en", "label_ja", ... }`; descriptions use `desc_zh` / `desc_en` / `desc_ja`, and `visual_styles` groups use `group_zh` / `group_en` / `group_ja`. The front-end falls back to legacy `label` / `desc` / `group`, so old catalogs still load, but new user-facing catalog text must cover all three languages (zh / en / ja). English labels should mirror canonical reference names (`pyramid`, `swiss-minimal`, `Path A`, `mixed`, etc.); Chinese and Japanese labels should be translated for users. Descriptions render inline after the option title, not as a separate selected-option line. `visual_styles` is `[{ "group", "group_zh", "group_en", "group_ja", "items": [...] }]`. For `canvas` you only need to maintain the trilingual labels in catalogs.json; the format set and dimensions are authoritative in `config.py CANVAS_FORMATS`. +The front-end loads `/api/catalogs` (served by the confirm server) and falls back to the static `/static/catalogs.json` if that route is unavailable. `/api/catalogs` returns the static file **with the `canvas` list synced live from `config.py CANVAS_FORMATS`** — the set of formats and their `dim` come from config (single source of truth, zero drift), while four-language labels / use text stay in catalogs.json (a plain fallback label is synthesized for any new id config adds). Keys: `canvas`, `modes`, `visual_styles` (grouped), `icons`, `image_usage`, `image_ai_path`, `formula_policy`, `generation_mode`, `delivery_purpose`. Each entry is `{ "id", "label", "label_zh", "label_zh_tw", "label_en", "label_ja", ... }`; descriptions use `desc_zh` / `desc_zh_tw` / `desc_en` / `desc_ja`, and `visual_styles` groups use `group_zh` / `group_zh_tw` / `group_en` / `group_ja`. The front-end falls back to legacy `label` / `desc` / `group`, so old catalogs still load, but new user-facing catalog text must cover all four languages (zh / zh-TW / en / ja). English labels should mirror canonical reference names (`pyramid`, `swiss-minimal`, `Path A`, `mixed`, etc.); Simplified Chinese, Traditional Chinese, and Japanese labels should be translated for users. Descriptions render inline after the option title, not as a separate selected-option line. `visual_styles` is `[{ "group", "group_zh", "group_zh_tw", "group_en", "group_ja", "items": [...] }]`. For `canvas` you only need to maintain the four-language labels in catalogs.json; the format set and dimensions are authoritative in `config.py CANVAS_FORMATS`. ## Round-trip data contract @@ -521,7 +521,7 @@ Template-mode-only Stage-2 fragment: - `image_notes` is the initial strategy note shown under the image source chips. Use it for page-role guidance and constraints: which source applies where, what to avoid, which user assets are authoritative, how realistic / abstract the imagery should be, and what can remain as placeholders. It is intent guidance, not a separate finite option. - Final Stage 2 shows and submits `recommend.image_ai_path` as one of `auto` / `api` / `host-native` / `manual` only while its current `image_usage` includes `ai`; changing sources refreshes that production control on the same page. - **Color candidates carry the user-facing core `palette`**: `background`, `secondary_bg`, `primary`, `accent`, `secondary_accent`, and `body_text`. The page renders every role as a labelled swatch with its HEX value visible, and offers per-role override inputs for precise single-role edits, plus a **Custom color card with a free-text box** — the user can describe the palette in words or paste HEX values instead of filling each role; this writes `color: { "name": "custom", "custom": "" }` to `result.json` for the AI to interpret. Legacy `text` is accepted as an alias for `body_text`, but new files should write `body_text`. Strategist derives secondary text, borders, state colors, and visual-style neutral tiers while writing `design_spec.md`, then projects the machine values to `spec_lock.md`; those are not user-facing confirmation choices. -- **Candidate display text may be multilingual**: color / typography candidates can provide `name_zh` / `name_en` / `name_ja` and `note_zh` / `note_en` / `note_ja`; the page falls back to legacy `name` / `note`. Labels resolve in the page language first, then fall back across the others (a `ja` page: ja → en → zh; zh/en pages keep their zh↔en fallback and try `_ja` last), so when `lang` is `ja` always include the `_ja` variants — otherwise the candidate labels render in English. +- **Candidate display text may be multilingual**: color / typography candidates can provide `name_zh` / `name_zh_tw` / `name_en` / `name_ja` and `note_zh` / `note_zh_tw` / `note_en` / `note_ja`; the page falls back to legacy `name` / `note` when present. Otherwise localized fields resolve in the page language first, then by the locale's fallback order: zh → en → ja → zh_tw, en → zh → ja → zh_tw, ja → en → zh → zh_tw, or zh_tw → zh → en → ja. Include all four variants in newly authored multilingual candidates so a persisted UI-language choice never hides recommendation text. - **Typography candidates** use concrete heading/body `primary`; non-English decks also use `english`, while English-primary decks omit it. `cjk` / `latin` remain legacy aliases. Localized `name` labels the pair and `css` only previews. Bundles differ overall; font pairs may repeat without blocking. Fixed pairs require `fixed: true`. Catalog `fonts` supplies language-filtered dropdowns plus Other without limiting recommendations; edits mark Custom and refresh the preview. Include topic samples. [`canvas-formats.md`](../../references/canvas-formats.md) § "Typography Scale Start" is the single owner of initial body anchors and sanity bands; the browser mirrors that rule, and submitted values remain px. - **Per-role size override** (parallel to color's per-role HEX override): besides `body_size`, the page exposes editable inputs for `title` / `subtitle` / `annotation`. The browser applies one documented deterministic dependency chain: PPT uses `reading mode → body baseline`, non-PPT uses `canvas → body baseline`, then every canvas uses `body baseline → unpinned role sizes` (role ramp: `body ×` the §g ratios). Changing reading mode updates a PPT body and all unpinned roles locally; changing body updates unpinned roles locally. Editing body or a role pins that value, so later reading-mode changes do not overwrite it. A font-only selection preserves current sizes; applying a different complete direction, or using the active card's explicit restore action, restores that direction's typography baseline and derived unpinned sizes. This is a browser-only state update: it performs no fetch and asks the backend to author no new recommendations. Each role input is labelled as px and shows an approximate pt equivalent (`1px = 0.75pt`) for orientation. The final values are written to `result.json` as `typography.sizes: { "title", "subtitle", "annotation" }` in **px** — every canvas, no pt and no `sizes_pt` provenance. These confirmed values are Strategist input anchors: the completed page plan may add recurring roles, and downstream execution owns bounded per-occurrence treatment. Candidate `sizes` remain accepted for compatibility; fresh Stage 2 preserves a candidate `body_size` as its baseline and derives only missing or unpinned role sizes from the same local ramp before first render. - **`delivery_purpose` compatibility key / Reading mode** (enumerable, PPT only) decides where meaning is carried, not merely how large type is: `text` makes pages self-contained with complete sentences, short prose, captions, tables, and necessary detail; `balanced` shares explanation between page and presenter; `presentation` uses one idea, concise claims, and visual evidence while speech / notes carry the detail. It therefore governs page grammar, granularity, density / rhythm, and note burden. Reading-mode cards intentionally show **no px value**; the typography section owns the separately visible body / role sizes and applies any local default. It is surfaced in Stage 2 beside the visual system, separate from communication intent. `recommend.delivery_purpose` pre-selects one; `result.json` retains the key, while `spec_lock.md` uses canonical `consumption_mode`. Non-PPT canvases omit it. @@ -530,7 +530,7 @@ Template-mode-only Stage-2 fragment: - **`design_directions`** is the canonical Stage-2 starting set: exactly three top-down, project-fit bundles with stable ids, localized copy, custom mode/style/rendering, icons, complete language-aware typography, and HEX `background`, `secondary_bg`, `primary`, `accent`, `secondary_accent`, `body_text`. The `selected` card carries the persistent Recommended marker and is applied first. A custom direction card uses its localized style-summary note—or the required behavior fallback—instead of requesting a preset-style preview. Newly authored notes may borrow localized catalog display labels where useful or use concise natural language freely; they never force an approximate label or expose internal catalog ids. Clicking an inactive card applies every field it owns; projected custom fields can then be edited in place and all lower controls may diverge. The active card shows an adjusted state and exposes an explicit restore action for its immutable authored bundle. `result.json` stores the edited current components, never a direction id. - `recommend.generation_mode` and `refine_spec` mirror [`generate-pptx`](../../workflows/generate-pptx.md) Step 4. `split` / `true` are explicit opt-ins. Refinement adds no UI stage: after Gate 1 it stops before the lock for unrestricted chat revision until approval. - `content_divergence` is a **free-text** Stage-1 source-treatment field. Blank means a balanced default; facts stay sourced at every level. Strategist consumes it while authoring §IX and records it in `design_spec.md §I`; it is not written to `spec_lock.md`. Beautify sends `{ "value": "keep source wording and page structure verbatim", "locked": true }`, so the UI displays it read-only and the server restores it on every staged submit. Template-fill does not use this confirmation flow and does not surface it. -- `lang` is the soft UI-language default (`zh` / `en` / `ja`); the persisted user choice wins. It never sets `primary_language`. +- `lang` is the soft UI-language default (`zh` / `zh-TW` / `en` / `ja`); the persisted user choice wins. It never sets `primary_language`. ### Output — `result.json` (written on submit, read by the AI) diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_editor/server.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_editor/server.py index db0c82bb..9e2e2bce 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_editor/server.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_editor/server.py @@ -110,7 +110,9 @@ _SLIDE_CACHE: dict = {} # path -> (mtime, (content, warnings)) _LIST_CACHE_LOCK = threading.Lock() _LIST_CACHE: dict = {} # path -> (mtime, annotation_count_on_disk) -DEFAULT_PORT = 5050 +# Keep live preview on a separate range from Confirm UI so a stale preview tab +# cannot send ``/api/shutdown`` to a later Confirm UI process. +DEFAULT_PORT = 6060 PUBLIC_HOST = '127.0.0.1' STARTUP_TIMEOUT = 15 diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_editor/static/app.js b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_editor/static/app.js index be7451f4..e06bcc64 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_editor/static/app.js +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_editor/static/app.js @@ -231,16 +231,96 @@ nav_last: "末页 (End)", nav_counter: "{current} / {total}", nav_empty: "— / —" + }, + "zh-TW": { + page_title: "PPT Master - 即時預覽", + panel_slides: "投影片", + panel_annotations: "標註", + panel_edit_annotate: "編輯 / 標註", + placeholder_select_slide: "在左側選擇一張投影片開始", + label_selected_element: "已選元素", + empty_selected_element: "點選投影片中的元素進行選擇", + btn_select_group: "選擇父群組", + label_batch_edit: "批次編輯", + label_group_edit: "群組編輯", + section_geometry: "幾何", + section_style: "樣式", + section_text_style: "文字", + section_raw_attrs: "原始屬性", + label_edit_instruction: "修改說明", + pending_none: "沒有待套用修改", + pending_summary: "{edits} 筆直接修改、{annotations} 個頁面有 AI 標註待套用", + pending_pages: "頁面:{pages}", + quick_align: "對齊/移動", + quick_resize: "調整大小", + quick_replace_image: "換圖", + quick_copy: "改文案", + quick_relayout: "重排此區域", + placeholder_annotation: "描述希望 AI 如何修改該元素……", + placeholder_annotation_multi: "描述希望如何修改所選 {count} 個元素……", + btn_add_annotation: "新增標註", + label_annotations_on_slide: "本頁標註", + btn_submit_annotations: "套用修改", + btn_exit_preview: "結束預覽", + modal_submit: "提交", + modal_cancel: "取消", + empty_waiting_slides: "正在等待生成投影片……", + empty_no_slides: "未找到投影片", + placeholder_live_ready: "即時預覽已就緒,生成的投影片會在這裡出現。", + placeholder_slide_writing: "投影片仍在寫入,等待下次重新整理……", + empty_annotations: "尚無標註", + tooltip_remove_annotation: "刪除標註", + multi_selected: "已選 {count} 個元素", + multi_mixed: "混合", + err_load_slides: "載入投影片失敗:", + err_load_slide: "載入投影片失敗:", + err_add_annotation: "新增標註失敗:", + err_remove_annotation: "刪除標註失敗:", + err_save: "儲存失敗:", + err_edit: "編輯失敗:", + label_direct_edit: "物件屬性(點選套用修改後寫入)", + prop_multiline_hint: "多行文字——選取單行(tspan)編輯文字", + edit_saved_hint: "修改已暫存。點選「套用修改」後寫入 svg_output。", + btn_undo: "復原", + undo_done: "已復原上一筆暫存修改", + undo_empty: "沒有可復原的暫存修改", + overlap_caption: "此處元素重疊——請點選其中一個", + err_empty_svg: "投影片已載入但畫布為空。SVG 可能損壞或缺少根 元素。", + warn_icon_inline: "{count} 個圖示渲染失敗:{names}", + warn_matrix_transform: "本次幾何修改會以 transform matrix 儲存。預覽是準確的;PPTX 匯出需要使用支援 matrix 的目前匯出器。", + modal_matrix_transform_note: "\n\n提示:至少有一筆暫存幾何修改使用了 transform matrix。請用目前 PPTX 匯出器重新匯出,確保 matrix 被套用。", + slide_error_tooltip: "該投影片解析失敗:", + reload_banner: "目前頁已在磁碟上更新,點此重新載入。", + modal_confirm_submit: "確認將暫存的直接修改和 AI 標註寫入磁碟?\n\n預覽服務會繼續執行。需要關閉時請點選結束預覽。", + modal_success_submit: "修改已儲存到 svg_output。\n\n預覽服務仍在執行。", + modal_success_direct_only: "修改已儲存到 svg_output。\n\n直接修改已經寫入 SVG 原始檔;需要重新整理 PPTX 時,請回到對話視窗要求重新匯出。預覽服務仍在執行。", + modal_success_annotations_only: "標註已儲存到 svg_output。\n\n需要 AI 理解並執行這些標註時,請回到對話視窗要求套用標註。預覽服務仍在執行。", + modal_success_mixed: "直接修改和標註已儲存到 svg_output。\n\n請回到對話視窗先套用需要 AI 判斷的標註,確認後再重新匯出 PPTX。預覽服務仍在執行。", + modal_confirm_exit: "結束預覽並停止本機服務?\n\n未套用的屬性修改和標註將被丟棄。", + modal_success_exit: "預覽已停止。\n\n可以關閉本分頁並回到對話視窗。", + modal_stopping: "正在停止預覽服務……", + lang_toggle_title: "切換語言", + nav_first: "第一頁 (Home)", + nav_prev: "上一頁 (←)", + nav_next: "下一頁 (→)", + nav_last: "末頁 (End)", + nav_counter: "{current} / {total}", + nav_empty: "— / —" } }; var LANG = (function () { try { var stored = window.localStorage.getItem("ppt_lang"); - if (stored === "zh" || stored === "en" || stored === "ja") return stored; + if (stored === "zh" || stored === "en" || stored === "ja" || + stored === "zh-TW") return stored; } catch (e) { /* ignore */ } var nav = (navigator.language || navigator.userLanguage || "en").toLowerCase(); - if (nav.indexOf("zh") === 0) return "zh"; + if (nav.indexOf("zh") === 0) { + if (/\bhans\b/.test(nav)) return "zh"; + if (/\bhant\b/.test(nav) || /\b(tw|hk|mo)\b/.test(nav)) return "zh-TW"; + return "zh"; + } if (nav.indexOf("ja") === 0) return "ja"; return "en"; })(); @@ -259,7 +339,7 @@ } function applyI18n() { - document.documentElement.setAttribute("lang", LANG === "zh" ? "zh-CN" : (LANG === "ja" ? "ja" : "en")); + document.documentElement.setAttribute("lang", LANG === "zh" ? "zh-CN" : (LANG === "zh-TW" ? "zh-TW" : (LANG === "ja" ? "ja" : "en"))); document.title = t("page_title"); document.querySelectorAll("[data-i18n]").forEach(function (el) { el.textContent = t(el.getAttribute("data-i18n")); @@ -273,7 +353,7 @@ updateNavLabel(); } - var LANG_NAMES = { zh: "中文", en: "English", ja: "日本語" }; + var LANG_NAMES = { zh: "中文", en: "English", ja: "日本語", "zh-TW": "繁體中文" }; function refreshLangUI(lang) { // Custom dropdown (OS-independent): button shows the CURRENT language. @@ -289,7 +369,7 @@ } function setLang(lang) { - if (lang !== "zh" && lang !== "en" && lang !== "ja") return; + if (lang !== "zh" && lang !== "en" && lang !== "ja" && lang !== "zh-TW") return; LANG = lang; try { window.localStorage.setItem("ppt_lang", lang); } catch (e) { /* ignore */ } applyI18n(); diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_editor/static/index.html b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_editor/static/index.html index d6569933..e7bb82e3 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_editor/static/index.html +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_editor/static/index.html @@ -34,6 +34,7 @@ diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/workflows/profiles/beautify-pptx.md b/plugins/codex/plugins/ppt-master/skills/ppt-master/workflows/profiles/beautify-pptx.md index 014fee01..0f8a2f2e 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/workflows/profiles/beautify-pptx.md +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/workflows/profiles/beautify-pptx.md @@ -240,7 +240,7 @@ the inherited / source-derived default so the user sees the recommendation and keeps the place to change it. Schema → [`scripts/docs/confirm_ui.md`](../../scripts/docs/confirm_ui.md). -The typography rows below show the non-English shape; omit `english` for an English source. +Rows are abbreviated; follow Confirm UI's four-locale contract and omit `english` for English sources. ```json { diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/workflows/stages/live-preview.md b/plugins/codex/plugins/ppt-master/skills/ppt-master/workflows/stages/live-preview.md index e444e12f..fb7f9ff1 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/workflows/stages/live-preview.md +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/workflows/stages/live-preview.md @@ -69,7 +69,7 @@ Triggered by the user signals listed in "When to Run". ## Notes (editor invariants — referenced from Generate Step 6) -- **UI**: trilingual (中文 / English / 日本語); auto-detects from `navigator.language`, persists in `localStorage`, switched via the language dropdown on the right panel. The right panel is an **Edit / Annotate** surface: direct SVG edits and AI-needed annotations are visually separated, with a pending-status strip showing staged direct edits and pages with unsaved annotations. Slide navigation: first/prev/next/last buttons at the top of the center panel, plus `←` / `→` / `Home` / `End` (suppressed while typing in the annotation textarea). +- **UI**: four-language (中文 / 繁體中文 / English / 日本語); auto-detects from `navigator.language`, persists in `localStorage`, switched via the language dropdown on the right panel. The right panel is an **Edit / Annotate** surface: direct SVG edits and AI-needed annotations are visually separated, with a pending-status strip showing staged direct edits and pages with unsaved annotations. Slide navigation: first/prev/next/last buttons at the top of the center panel, plus `←` / `→` / `Home` / `End` (suppressed while typing in the annotation textarea). - **Buttons**: `Add annotation` stages annotation text in memory; `Apply changes` writes staged direct edits plus annotation markers to disk and keeps the service running; `Exit preview` is the only UI action that stops Flask. - **Direct edit (no AI)**: selection mode determines the right-panel surface. Single element = full object inspector (geometry, safe text content, computed text styles for the selected text node or descendant text inside a selected textbox/group, raw SVG attributes except protected fields like `id`, UI `class`, event handlers, and hrefs). SVG `` group = group-level edit surface; select via `Alt/Option` + click or **Select parent group** from a child element. Multi-select = limited batch editor over top-level selected objects only: shared x/y plus `fill` / `stroke` / `opacity`; text style fields (`font-size` / `font-family` / `font-weight` / `text-anchor`) appear only when every selected object is `text`/`tspan`. Preview updates immediately; disk writes wait for **Apply changes**. - **Drag to move**: press and drag an already-selected element on the canvas to reposition it (selection stays a separate click, so the background is never dragged by accident); the whole selection moves together under multi-select. The pointer delta is mapped through each element's own CTM, so moves track the cursor regardless of viewport scale or group transforms. Each release stages one direct edit per moved element (the same `x`/`y`-or-`transform` write the geometry inputs produce), previewed live and written only on **Apply changes**; dragging on empty canvas is still rubber-band selection. A failed stage rolls the canvas back to the pre-drag position. diff --git a/plugins/codex/plugins/shadcn/THIRD_PARTY_SOURCE.json b/plugins/codex/plugins/shadcn/THIRD_PARTY_SOURCE.json index d725d931..dc40fc7c 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": "41bbc12cfd39ed8d9cb8da04275479ee7ecc0612", + "commit": "a85299a9edd2a961e32f01ced86963a852652bd2", "adapter": "claude-skill", "sourcePath": "skills/shadcn", - "syncedAt": "2026-08-11T16:00:01Z" + "syncedAt": "2026-08-13T08:38:10Z" } diff --git a/plugins/codex/plugins/superpowers/.codex-plugin/plugin.json b/plugins/codex/plugins/superpowers/.codex-plugin/plugin.json index 7083815b..3ce77cff 100644 --- a/plugins/codex/plugins/superpowers/.codex-plugin/plugin.json +++ b/plugins/codex/plugins/superpowers/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "superpowers", - "version": "6.2.0", + "version": "6.3.0", "description": "面向编码 Agent 的规划、TDD、调试、代码评审和交付工作流集合。", "author": { "name": "Jesse Vincent", diff --git a/plugins/codex/plugins/superpowers/README.md b/plugins/codex/plugins/superpowers/README.md index 2757b2ef..09a91c6d 100644 --- a/plugins/codex/plugins/superpowers/README.md +++ b/plugins/codex/plugins/superpowers/README.md @@ -2,10 +2,33 @@ Superpowers is a complete software development methodology for your coding agents, built on top of a set of composable skills and some initial instructions that make sure your agent uses them. +## Table of Contents -## Quickstart - -Give your agent Superpowers: [Claude Code](#claude-code), [Antigravity](#antigravity), [Codex App](#codex-app), [Codex CLI](#codex-cli), [Cursor](#cursor), [Factory Droid](#factory-droid), [Gemini CLI](#gemini-cli), [GitHub Copilot CLI](#github-copilot-cli), [Kimi Code](#kimi-code), [OpenCode](#opencode), [Pi](#pi). +- [How it works](#how-it-works) +- [Commercial Services](#commercial-services) +- [Getting Started](#installation) + - [Claude Code](#claude-code) + - [Antigravity](#antigravity) + - [Codex App](#codex-app) + - [Codex CLI](#codex-cli) + - [Cursor](#cursor) + - [Devin CLI](#devin-cli) + - [Factory Droid](#factory-droid) + - [Gemini CLI](#gemini-cli) + - [GitHub Copilot CLI](#github-copilot-cli) + - [Grok Build CLI](#grok-build-cli) + - [Kimi Code](#kimi-code) + - [OpenCode](#opencode) + - [Pi](#pi) + - [Hermes Agent](#hermes-agent) +- [The Basic Workflow](#the-basic-workflow) +- [Community](#community) +- [What's Inside](#whats-inside) +- [Philosophy](#philosophy) +- [Contributing](#contributing) +- [Updating](#updating) +- [License](#license) +- [Visual companion telemetry](#visual-companion-telemetry) ## How it works @@ -102,6 +125,20 @@ Superpowers is available via the [official Codex plugin marketplace](https://git - Or search for "superpowers" in the plugin marketplace. +### Devin CLI + +- Install the plugin from this repository: + + ```bash + devin plugins install obra/superpowers + ``` + +- Update to the latest version with: + + ```bash + devin plugins update superpowers + ``` + ### Factory Droid - Register the marketplace: @@ -144,6 +181,22 @@ Superpowers is available via the [official Codex plugin marketplace](https://git copilot plugin install superpowers@superpowers-marketplace ``` +### Grok Build CLI + +Superpowers is available via the [official Grok plugin marketplace](https://github.com/xai-org/plugin-marketplace). + +- Install the plugin from xAI's official marketplace: + + ```bash + grok plugin install superpowers@xai-official --trust + ``` + +- Or open the marketplace in the TUI, search for Superpowers, and install it: + + ```text + /marketplace + ``` + ### Kimi Code Superpowers is available in Kimi Code's plugin marketplace. @@ -193,6 +246,18 @@ pi -e /path/to/superpowers The Pi package loads the Superpowers skills and a small extension that injects the `using-superpowers` bootstrap at session startup and again after compaction. Pi has native skills, so no compatibility `Skill` tool is required. Subagent and task-list tools remain optional Pi companion packages. +### Hermes Agent + +Install Superpowers as a Hermes plugin from this repository: + +```bash +hermes plugins install obra/superpowers --enable +``` + +Restart any active Hermes sessions after installing. Note: Hermes has no +post-compaction hook, so a very long session that compacts over its first +turn loses the bootstrap — start a fresh session if skills stop triggering. + ## The Basic Workflow 1. **brainstorming** - Activates before writing code. Refines rough ideas through questions, explores alternatives, presents design in sections for validation. Saves design document. @@ -211,6 +276,14 @@ The Pi package loads the Superpowers skills and a small extension that injects t **The agent checks for relevant skills before any task.** Mandatory workflows, not suggestions. +## Community + +Superpowers is built by [Jesse Vincent](https://blog.fsck.com) and the rest of the folks at [Prime Radiant](https://primeradiant.com). + +- **Discord**: [Join us](https://discord.gg/35wsABTejz) for community support, questions, and sharing what you're building with Superpowers +- **Issues**: https://github.com/obra/superpowers/issues +- **Release announcements**: [Sign up](https://primeradiant.com/superpowers/) to get notified about new versions + ## What's Inside ### Skills Library @@ -271,11 +344,3 @@ MIT License - see LICENSE file for details ## Visual companion telemetry Because skills and plugins don't provide any feedback to creators, we have no idea how many of you are using Superpowers. By default, the Prime Radiant logo on brainstorming's optional visual companion feature is loaded from our website. It includes the version of Superpowers in use. It does not include any details about your project, prompt, or coding agent. We don't see your clicks or anything about what you're building. This helps us have a rough idea of how many folks are using Superpowers and which version of Superpowers they're using. It's 100% optional. To disable this, set the environment variable `SUPERPOWERS_DISABLE_TELEMETRY` to any true value. Superpowers also honors Claude Code's `DISABLE_TELEMETRY` and `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC` opt-outs. - -## Community - -Superpowers is built by [Jesse Vincent](https://blog.fsck.com) and the rest of the folks at [Prime Radiant](https://primeradiant.com). - -- **Discord**: [Join us](https://discord.gg/35wsABTejz) for community support, questions, and sharing what you're building with Superpowers -- **Issues**: https://github.com/obra/superpowers/issues -- **Release announcements**: [Sign up](https://primeradiant.com/superpowers/) to get notified about new versions diff --git a/plugins/codex/plugins/superpowers/THIRD_PARTY_SOURCE.json b/plugins/codex/plugins/superpowers/THIRD_PARTY_SOURCE.json index c4211290..e2cac192 100644 --- a/plugins/codex/plugins/superpowers/THIRD_PARTY_SOURCE.json +++ b/plugins/codex/plugins/superpowers/THIRD_PARTY_SOURCE.json @@ -2,8 +2,8 @@ "sourceId": "superpowers", "repo": "https://github.com/obra/superpowers.git", "ref": "main", - "commit": "44c9b2d6e889982ac18c27d05a19fefe335194e1", + "commit": "b36e0829c6d0140e93cfef2ca599b1b07d4a7797", "adapter": "codex-plugin", "sourcePath": ".", - "syncedAt": "2026-07-29T16:00:04Z" + "syncedAt": "2026-08-13T08:38:10Z" } diff --git a/plugins/codex/plugins/superpowers/skills/brainstorming/SKILL.md b/plugins/codex/plugins/superpowers/skills/brainstorming/SKILL.md index 0cbb7d05..5f9c6041 100644 --- a/plugins/codex/plugins/superpowers/skills/brainstorming/SKILL.md +++ b/plugins/codex/plugins/superpowers/skills/brainstorming/SKILL.md @@ -7,20 +7,91 @@ description: "在开始创造性工作前澄清意图、约束和可行方向; Help turn ideas into fully formed designs and specs through natural collaborative dialogue. -Start by understanding the current project context, then ask questions one at a time to refine the idea. Once you understand what you're building, present the design and get user approval. +Start by classifying how much process the request needs, then work +through your path: understand the context, refine the idea, present a +design, and get your human partner's approval. -Do NOT invoke any implementation skill, write any code, scaffold any project, or take any implementation action until you have presented a design and the user has approved it. This applies to EVERY project regardless of perceived simplicity. +Do NOT invoke any implementation skill, write any code, scaffold any +project, or take any implementation action until you have told your +human partner what you intend and they have approved it. This applies +to EVERY task on EVERY path below — the ceremony scales with the task; +the approval gate never does. -## Anti-Pattern: "This Is Too Simple To Need A Design" +## Three Paths -Every project goes through this process. A todo list, a single-function utility, a config change — all of them. "Simple" projects are where unexamined assumptions cause the most wasted work. The design can be short (a few sentences for truly simple projects), but you MUST present it and get approval. +Before your first question, classify the request and say the +classification out loud — "this looks bounded, so I'll present a short +design here rather than write a spec" — so your human partner can +override it: + +- **Spike** — a feasibility question ("can we...", "is it possible...", + "quick and dirty is fine") whose output is an answer, not code you + keep. Present the question and what you'll try in 2-3 sentences, get + a nod, then find out as cheaply as correctness allows. No design + doc, no spec file. Report findings as a recommendation; anything you + built stays labeled throwaway. +- **Bounded** — a well-scoped change to code that already exists in + this repo: a new flag, a small endpoint, a one-file fix. + Understanding the kind of app is not enough — bounded means the flow + you are changing is already here to read. If there is no existing + flow to change, the task is not bounded. Ask the clarifying + questions that matter, present a short design IN CHAT (a few + sentences to a few short paragraphs), and STOP. Implementation + starts only after your human partner says yes to that design — a + bounded task's approval is as hard a gate as an architectural + one. No spec file, no implementation plan document. +- **Architectural** — new projects, new subsystems, changes that + restructure how components fit together or alter interfaces others + depend on. Follow the full process: questions, approaches, sectioned + design, written spec, then the writing-plans skill. + +When in doubt between two paths, take the heavier one. The ratchet is +one-way: hidden complexity discovered mid-task upgrades the path — +stop, say so, and step up. Nothing downgrades mid-task. + +## Anti-Pattern: "Too Simple To Need Approval" + +Every path ends with your human partner approving your intent before +implementation. A todo list, a single-function utility, a config +change — the design may be two sentences in chat, but you MUST present +it and get approval. "Simple" tasks are where unexamined assumptions +cause the most wasted work. What scales with simplicity is the +artifact, never the approval. + +## Red Flags + +| Thought | Reality | +|---------|---------| +| "This is too simple to need a design" | Simple means a short design, not no design. Two sentences in chat, then approval. | +| "I'll call it bounded and skip the spec" | Reaching for a label to skip work IS the doubt — take the heavier path. | +| "It's bounded and the design is obvious — I'll start while they read it" | The gate is the approval, not the design's length. Present, then stop until you hear yes. | +| "I understand this kind of app, so it's bounded" | Bounded measures the repo, not your familiarity. A new project has no existing flow — it is architectural. | +| "The spike works, so I'll keep the code" | A spike's output is an answer. Keeping the code is a new request — classify it. | +| "It grew, but I'm almost done — no need to re-classify" | Hidden complexity upgrades the path mid-task. Stop and say so. | +| "They approved the spike, so the follow-up change is approved too" | Each task gets its own classification and its own approval. | ## Checklist -You MUST create a task for each of these items and complete them in order: +Classify first, announce the path, then create a task for each item on +your path and complete them in order. +**Spike:** +1. **Explore project context** — enough to frame the probe +2. **Present question + probe plan** — 2-3 sentences +3. **Get approval** — a nod is enough +4. **Investigate** — as cheaply as correctness allows +5. **Report findings** — a recommendation; label anything built as throwaway + +**Bounded:** +1. **Explore project context** — check files, docs, recent commits +2. **Ask clarifying questions** — one at a time, the ones that matter +3. **Present short design in chat** — approach, files touched, testing +4. **Get approval** — STOP and wait for an explicit yes; presenting the design and starting in the same breath is skipping the gate +5. **Implement** — proceed with the normal development workflow (TDD applies); no plan document + +**Architectural:** 1. **Explore project context** — check files, docs, recent commits 2. **Offer the visual companion just-in-time** — NOT upfront. The first time a question would genuinely be clearer shown than described, offer it then (its own message); on approval its browser tab opens for you. If no visual question ever arises, never offer it. See the Visual Companion section below. 3. **Ask clarifying questions** — one at a time, understand purpose/constraints/success criteria @@ -35,6 +106,13 @@ You MUST create a task for each of these items and complete them in order: ```dot digraph brainstorming { + "Classify: spike / bounded / architectural" [shape=diamond]; + "Present question + probe (2-3 sentences)" [shape=box]; + "Ask clarifying questions (bounded)" [shape=box]; + "Present short design in chat" [shape=box]; + "Human approves?" [shape=diamond]; + "Investigate; report recommendation" [shape=doublecircle]; + "Implement via normal workflow (no plan doc)" [shape=doublecircle]; "Explore project context" [shape=box]; "Ask clarifying questions" [shape=box]; "Propose 2-3 approaches" [shape=box]; @@ -44,7 +122,17 @@ digraph brainstorming { "Spec self-review\n(fix inline)" [shape=box]; "User reviews spec?" [shape=diamond]; "Invoke writing-plans skill" [shape=doublecircle]; + "Hidden complexity? Upgrade path" [shape=box]; + "Classify: spike / bounded / architectural" -> "Present question + probe (2-3 sentences)" [label="spike"]; + "Classify: spike / bounded / architectural" -> "Ask clarifying questions (bounded)" [label="bounded"]; + "Classify: spike / bounded / architectural" -> "Explore project context" [label="architectural"]; + "Present question + probe (2-3 sentences)" -> "Human approves?"; + "Ask clarifying questions (bounded)" -> "Present short design in chat"; + "Present short design in chat" -> "Human approves?"; + "Human approves?" -> "Investigate; report recommendation" [label="spike: yes"]; + "Human approves?" -> "Implement via normal workflow (no plan doc)" [label="bounded: yes"]; + "Hidden complexity? Upgrade path" -> "Classify: spike / bounded / architectural"; "Explore project context" -> "Ask clarifying questions"; "Ask clarifying questions" -> "Propose 2-3 approaches"; "Propose 2-3 approaches" -> "Present design sections"; @@ -58,10 +146,21 @@ digraph brainstorming { } ``` -**The terminal state is invoking writing-plans.** Do NOT invoke frontend-design, mcp-builder, or any other implementation skill. The ONLY skill you invoke after brainstorming is writing-plans. +**Terminal states are path-bound.** Architectural: the ONLY skill you +invoke after brainstorming is writing-plans — never frontend-design, +mcp-builder, or any other implementation skill. Bounded: after +approval, implementation proceeds directly through the normal +development workflow; no plan document. Spike: the terminal state is a +reported recommendation. ## The Process +The subsections below serve the bounded and architectural paths (a +spike stops at "present the probe, get a nod"). Sections from +**Exploring approaches** onward are architectural-path depth — for +bounded work, context plus a few questions plus a short in-chat design +is the whole process. + **Understanding the idea:** - Check out the current project state first (files, docs, recent commits) @@ -100,7 +199,7 @@ digraph brainstorming { - Where existing code has problems that affect the work (e.g., a file that's grown too large, unclear boundaries, tangled responsibilities), include targeted improvements as part of the design - the way a good developer improves code they're working in. - Don't propose unrelated refactoring. Stay focused on what serves the current goal. -## After the Design +## After the Design (architectural path) **Documentation:** diff --git a/plugins/codex/plugins/superpowers/skills/brainstorming/visual-companion.md b/plugins/codex/plugins/superpowers/skills/brainstorming/visual-companion.md index 906c9ac8..c145e643 100644 --- a/plugins/codex/plugins/superpowers/skills/brainstorming/visual-companion.md +++ b/plugins/codex/plugins/superpowers/skills/brainstorming/visual-companion.md @@ -83,10 +83,11 @@ scripts/start-server.sh --project-dir /path/to/project --open --foreground **Copilot CLI:** ```bash -# Use --foreground and start the server via the bash tool with mode: "async" -# so the process survives across turns. Capture the returned shellId for -# read_bash / stop_bash if you need to interact with it later. -scripts/start-server.sh --project-dir /path/to/project --open --foreground +# Start it with Copilot CLI's non-blocking/background shell mechanism so the +# server survives across turns. Keep --foreground so the harness, not the +# script, owns backgrounding. The launcher is a .sh, so invoke it via bash +# (on Windows, call Git Bash's bash.exe from the PowerShell tool). +bash scripts/start-server.sh --project-dir /path/to/project --open --foreground ``` **Other environments:** The server must keep running in the background across conversation turns. If your environment reaps detached processes, use `--foreground` and launch the command with your platform's background execution mechanism. diff --git a/plugins/codex/plugins/superpowers/skills/finishing-a-development-branch/SKILL.md b/plugins/codex/plugins/superpowers/skills/finishing-a-development-branch/SKILL.md index 6f2b1580..c0a6edb8 100644 --- a/plugins/codex/plugins/superpowers/skills/finishing-a-development-branch/SKILL.md +++ b/plugins/codex/plugins/superpowers/skills/finishing-a-development-branch/SKILL.md @@ -174,6 +174,29 @@ git worktree remove "$WORKTREE_PATH" git worktree prune # Self-healing: clean up any stale registrations ``` +**If removal is refused** (`contains modified or untracked files`): the +worktree holds files that exist nowhere else — uncommitted plans, notes, +or scratch work. Never `--force` on your own initiative. Show your human +partner what is at stake and ask: + +```bash +git -C "$WORKTREE_PATH" status --porcelain -uall +``` + +``` +Worktree removal refused — these files were never committed: + + + +1. Commit them to before cleanup +2. Move them into
+3. Delete them (unrecoverable) + +Which? +``` + +Carry out the choice, then remove the worktree. + **Otherwise:** The host environment owns this workspace — leave it in place. If your platform provides a workspace-exit tool, use it. @@ -196,6 +219,7 @@ place. If your platform provides a workspace-exit tool, use it. | "'Yeah, get rid of it' counts as confirmation" | Only the typed word `discard` authorizes deletion. | | "The PR is up, so the worktree is clutter now" | PR feedback gets fixed in that worktree. It stays until the work lands. | | "This other worktree looks stale — I'll clean it too" | Clean up only worktrees under `.worktrees/` or `worktrees/`. Everything else belongs to the host. | +| "Removal refused — `--force` is just finishing the cleanup" | The refusal means files exist only in that worktree. `--force` destroys them permanently. Show your human partner and ask. | | "The merged-result failure is probably flaky" | A failing merged result stops everything. Branch and worktree stay put while you investigate. | | "The base branch is obviously main" | Confirm the fork point or ask. Merging into the wrong base is expensive to undo. | | "The push was rejected — force-push will fix it" | A rejected push means the remote moved. Investigate; force-push only on your human partner's explicit request. | diff --git a/plugins/codex/plugins/superpowers/skills/requesting-code-review/code-reviewer.md b/plugins/codex/plugins/superpowers/skills/requesting-code-review/code-reviewer.md index db84ae2a..b898cb98 100644 --- a/plugins/codex/plugins/superpowers/skills/requesting-code-review/code-reviewer.md +++ b/plugins/codex/plugins/superpowers/skills/requesting-code-review/code-reviewer.md @@ -34,6 +34,15 @@ Subagent (general-purpose): Your review is read-only on this checkout. Do not mutate the working tree, the index, HEAD, or branch state in any way. Use tools like `git show`, `git diff`, and `git log` to inspect history. If you need a working copy of a different revision, check it out into a separate temporary directory (e.g. `git worktree add /tmp/review-[SHA] [SHA]`) — never move HEAD on this checkout. + ## You Do Not Dispatch Subagents + + Do all of this review yourself. Never spawn a subagent to review part + of the diff, and never spawn another reviewer for a second opinion. + This process already provides every review seat the work gets; a + reviewer you spawn duplicates one of them at full cost, and its + verdict counts for nothing. If the diff feels too large for one + pass, review it in passes yourself and say so in your report. + ## What to Check **Plan alignment:** diff --git a/plugins/codex/plugins/superpowers/skills/subagent-driven-development/SKILL.md b/plugins/codex/plugins/superpowers/skills/subagent-driven-development/SKILL.md index bcccb9a8..c5187554 100644 --- a/plugins/codex/plugins/superpowers/skills/subagent-driven-development/SKILL.md +++ b/plugins/codex/plugins/superpowers/skills/subagent-driven-development/SKILL.md @@ -14,7 +14,21 @@ Execute plan by dispatching a fresh implementer subagent per task, a task review **Narration:** between tool calls, narrate at most one short line — the ledger and the tool results carry the record. -**Continuous execution:** Do not pause to check in with your human partner between tasks. Execute all tasks from the plan without stopping. The only reasons to stop are: BLOCKED status you cannot resolve, ambiguity that genuinely prevents progress, or all tasks complete. "Should I continue?" prompts and progress summaries waste their time — they asked you to execute the plan, so execute it. +**Continuous execution:** Do not pause to check in with your human partner between tasks. Execute all tasks from the plan without stopping. The only reasons to stop are the four named below, or all tasks complete. "Should I continue?" prompts and progress summaries waste their time — they asked you to execute the plan, so execute it. + +**Rulings, not stalls.** A running plan does not wait on a human. Conflicts, +ambiguities, plan defects, a cap you would have asked to exceed — decide +them. The spec is the binding authority, the plan is its argument, and your +judgment settles what neither answers. Record every decision in the ledger as +`Ruling: `, and keep +going. A wrong ruling costs rework your human partner can see and undo; a +session parked on a question costs their whole day and buys nothing. + +Four things stop you, and only these: an irreversible or destructive +operation; a security-sensitive action; a side effect outside this worktree +that norms say you ask about first (a merge, a push to a shared branch, a +publish); and a plan so broken that every path forward is a guess. For those, +stop and ask. ## When to Use @@ -57,14 +71,14 @@ digraph process { "Generate review package, dispatch task reviewer (./task-reviewer-prompt.md)" [shape=box]; "Spec ✅ and quality approved?" [shape=diamond]; "Finding conflicts with plan text?" [shape=diamond]; - "Ask human partner which governs" [shape=box]; + "Rule on the conflict, ledger the ruling" [shape=box]; "Fix round R of 5: R≤3 resume implementer; R≥4 fresh implementer, more capable model" [shape=box]; "Dispatch scoped re-review (./re-review-prompt.md)" [shape=box]; "All findings addressed?" [shape=diamond]; "R = 5?" [shape=diamond]; "Adjudicate each open finding" [shape=box]; "Any load-bearing finding?" [shape=diamond]; - "STOP: report BLOCKED to human partner" [shape=box]; + "Rule and continue; stop only if every path forward is a guess" [shape=box]; "Park findings in ledger with rulings" [shape=box]; "Append completion to ledger, mark todo complete" [shape=box]; } @@ -85,8 +99,8 @@ digraph process { "Generate review package, dispatch task reviewer (./task-reviewer-prompt.md)" -> "Spec ✅ and quality approved?"; "Spec ✅ and quality approved?" -> "Append completion to ledger, mark todo complete" [label="yes"]; "Spec ✅ and quality approved?" -> "Finding conflicts with plan text?" [label="no"]; - "Finding conflicts with plan text?" -> "Ask human partner which governs" [label="yes"]; - "Ask human partner which governs" -> "Fix round R of 5: R≤3 resume implementer; R≥4 fresh implementer, more capable model"; + "Finding conflicts with plan text?" -> "Rule on the conflict, ledger the ruling" [label="yes"]; + "Rule on the conflict, ledger the ruling" -> "Fix round R of 5: R≤3 resume implementer; R≥4 fresh implementer, more capable model"; "Finding conflicts with plan text?" -> "Fix round R of 5: R≤3 resume implementer; R≥4 fresh implementer, more capable model" [label="no"]; "Fix round R of 5: R≤3 resume implementer; R≥4 fresh implementer, more capable model" -> "Dispatch scoped re-review (./re-review-prompt.md)"; "Dispatch scoped re-review (./re-review-prompt.md)" -> "All findings addressed?"; @@ -95,7 +109,7 @@ digraph process { "R = 5?" -> "Fix round R of 5: R≤3 resume implementer; R≥4 fresh implementer, more capable model" [label="no - next round"]; "R = 5?" -> "Adjudicate each open finding" [label="yes - breaker trips"]; "Adjudicate each open finding" -> "Any load-bearing finding?"; - "Any load-bearing finding?" -> "STOP: report BLOCKED to human partner" [label="yes"]; + "Any load-bearing finding?" -> "Rule and continue; stop only if every path forward is a guess" [label="yes"]; "Any load-bearing finding?" -> "Park findings in ledger with rulings" [label="no"]; "Park findings in ledger with rulings" -> "Append completion to ledger, mark todo complete"; "Append completion to ledger, mark todo complete" -> "More tasks remain?"; @@ -140,19 +154,32 @@ a ledger file, not only in todos. that happens, recover from `git log`. Read the plan once, note its context and Global Constraints, and create a -todo per task. +todo per task. If the plan names a Spec, read that too: the spec is the +authority the plan argues from, and conflicts inside the plan resolve +against it. A plan with no reachable spec gets a ledger note saying so — +rulings made without one are provisional. -Before dispatching Task 1, scan the plan once for conflicts: +Before dispatching Task 1, scan the plan once for conflicts, writing down +what you checked as you check it: - tasks that contradict each other or the plan's Global Constraints - anything the plan explicitly mandates that the review rubric treats as a defect (a test that asserts nothing, verbatim duplication of a logic block) -Present everything you find to your human partner as one batched question — -each finding beside the plan text that mandates it, asking which governs — -before execution begins, not one interrupt per discovery mid-plan. If the -scan is clean, proceed without comment. The review loop remains the net for -conflicts that only emerge from implementation. +The scan's output is a table, not a verdict. One row for every pair of tasks +that share a file or an interface: the two tasks, what one produces against +what the other consumes, and what you found. One row for every task: whether +its own text agrees with itself — the tests it specifies against the code it +specifies, the files it creates against the files it later touches. "The scan +is clean" without those rows is not a scan you ran. + +Write the table to the ledger. Rule on everything you find before execution +begins — each finding against the plan text that mandates it — and record +each ruling in the ledger. If the scan is clean, proceed without comment. +Rule on each conflict it surfaces — the spec is the binding authority, the +plan is its argument — record the ruling beside its row, and dispatch +Task 1. The review loop remains the net for conflicts that only emerge from +implementation. ## Model Selection @@ -193,10 +220,29 @@ that implementer. Single-file mechanical fixes also take the cheapest tier. ## The Task Loop +**Batch small same-shape work.** When the plan lists several tasks that are +each a small, independent edit of the same kind — the same one-line fix, +constant change, or field addition repeated across files — do not dispatch +one subagent per task. Compose ONE dispatch brief listing every file and +its change, send the whole batch to a single subagent, and review its diff +as one unit. Reserve one-dispatch-per-task for work that needs its own +judgment, its own tests, or its own review surface. + Everything you paste into a dispatch prompt — and everything a subagent prints back — stays resident in your context for the rest of the session and is re-read on every later turn. Hand artifacts over as files. +**Waiting on dispatched subagents:** never poll a wait interface with +short timeouts, and never sit in one silent, open-ended wait either. +While you have local work — ledger updates, packaging the next review, +reading reports — keep working; child results arrive on their own. +When you are genuinely idle, wait in bounded stretches (five to ten +minutes, where your platform allows), and between stretches post one +line of status and reconcile your live children: list them, and chase +any that finished without reporting. A bounded stretch keeps nearly +all of a long wait's efficiency while guaranteeing a stuck or lost +child is noticed within minutes, not at the end of the session. + ### 1. Dispatch the implementer Record BASE (`git rev-parse HEAD`) before dispatching — the review package @@ -223,6 +269,12 @@ and fix-round diffs need it. later dispatches — a real session's dispatch hit 42k chars of which 99% was pasted history. A fresh subagent needs its task, the interfaces it touches, and the global constraints. Nothing else. +- The dispatch carries the no-subagents contract (it is in the + implementer template): the implementer never dispatches subagents — + not helpers, and never a reviewer. Review arrives from you, after the + report. In real sessions, every reviewer a worker spawned duplicated + the task review the controller dispatched anyway — a full extra + review seat per task. - If an earlier task parked a finding in the area this task touches, carry a pointer to that ledger entry in the dispatch. - Record the implementer's agent identity from the dispatch result — @@ -245,7 +297,7 @@ Implementer subagents report one of four statuses. Handle each appropriately: 1. If it's a context problem, provide more context and re-dispatch with the same model 2. If the task requires more reasoning, re-dispatch with a more capable model 3. If the task is too large, break it into smaller pieces -4. If the plan itself is wrong, escalate to the human +4. If the plan itself is wrong, rule on the correction, ledger it, and re-dispatch with the ruling carried in the dispatch **Never** ignore an escalation or force the same model to retry without changes. If the implementer said it's stuck, something needs to change. @@ -312,10 +364,11 @@ Before the loop starts, two routes leave it immediately: before merge. A roll-up nobody reads is a silent discard. Minor findings never enter the loop. - A finding labeled plan-mandated — or any finding that conflicts with - what the plan's text requires — is the human's decision, like any plan - contradiction: present the finding and the plan text, ask which governs. - Do not dismiss the finding because the plan mandates it, and do not - dispatch a fix that contradicts the plan without asking. + what the plan's text requires — is yours to rule on: weigh the finding + against the plan text, decide with the spec as the binding authority, and + ledger the ruling before you act on it. Do not dismiss the finding because + the plan mandates it, and do not dispatch a fix that contradicts the plan + without a recorded ruling. Everything else enters the loop. A fix round is one fix dispatch plus one scoped re-review. Five rounds maximum per task: @@ -360,15 +413,16 @@ dispatching. Adjudicate each open finding yourself — you hold the plan and the cross-task context the reviewer lacks: - **The reviewer is wrong, or the point is contestable:** park it — - `Task : parked — — ruling: `. The final + `Task : parked — — Ruling: `. The final review sees both sides. - **Real, but nothing downstream builds on it:** park it the same way, with a ruling that says it's real and deferred. - **Real and load-bearing** — a later task builds on it, or it reveals a - plan defect: STOP. Append `Task : BLOCKED — ` and report to - your human partner with the finding, the plan text it collides with, and - the fix history. Parking a structural failure lets every dependent task - build on it and hands the final review a problem it cannot fix either. + plan defect: rule on the smallest change that unblocks the dependent work, + ledger it as `Task : Ruling: `, + and carry it into the next task's dispatch. Parking a structural failure + silently lets every dependent task build on it. Stop only when the defect + leaves every path forward a guess. Adjudicate only at the cap. Adjudicating earlier to end a loop is pre-judging with a different name. Every adjudication is a ledger entry — @@ -409,12 +463,22 @@ Then run exactly one scoped re-review of the fix wave (`scripts/review-package PLAN_FILE FIX_BASE HEAD` over the fix range, [re-review-prompt.md](re-review-prompt.md)). Adjudicate any residual findings as in the task loop's breaker: park with -rulings, or stop on load-bearing ones. There is no second fix wave — +rulings, or rule on the load-bearing ones and ledger what you decided. Only +the four classes above stop you here. There is no second fix wave — residual load-bearing findings surface to your human partner when finishing-a-development-branch presents the options. ## Finish +Before you delete anything, collect every ledger line containing `Ruling:` — +preflight rulings, parked findings, breaker adjudications, all of them — into +your final message under "Rulings I made", in the order you made them, each +with what it costs if wrong. The list is exhaustive: if the ledger holds a +ruling, the list holds it. That list is the only place the decisions you +took on your human partner's behalf reach them — they read it and rework +whatever you got wrong. A ruling that dies with the workspace was a decision +made in secret. + When the final whole-branch review is clean and its fixes are merged, delete this plan's workspace (`rm -rf `) — the git history is the record now. Sibling directories belong to other plans; leave them @@ -434,6 +498,7 @@ Use superpowers:finishing-a-development-branch. | "The fix was small, skip the re-review" | Unreviewed fixes are how regressions land. Every round ends with a scoped re-review. | | "Reviews slow the loop down" | The loop without reviews is just unverified churn. Reviews are the loop's brakes and steering. | | "Ledger bookkeeping is overhead" | The ledger is what survives compaction. Controllers without one have re-dispatched entire completed task sequences. | +| "The implementer spawned its own reviewer — free extra assurance" | It's a duplicate seat reviewing the same diff; the task review is the gate. A worker-spawned reviewer is a defect to flag, not rigor. | ## Example Workflow diff --git a/plugins/codex/plugins/superpowers/skills/subagent-driven-development/implementer-prompt.md b/plugins/codex/plugins/superpowers/skills/subagent-driven-development/implementer-prompt.md index fbe441e2..5c8ecd61 100644 --- a/plugins/codex/plugins/superpowers/skills/subagent-driven-development/implementer-prompt.md +++ b/plugins/codex/plugins/superpowers/skills/subagent-driven-development/implementer-prompt.md @@ -47,6 +47,18 @@ Subagent (general-purpose): While iterating, run the focused test for what you're changing; run the full suite once before committing, not after every edit. + ## You Do Not Dispatch Subagents + + Do all of this task's work yourself. Never spawn a subagent to + implement part of the task, and above all never spawn a reviewer to + check your work. Self-review (below) means reading your own diff. + Review is the controller's job: after you report, it dispatches a + fresh reviewer against your diff. A reviewer you spawn duplicates + that review at full cost, and its approval counts for nothing in + the process. If you catch yourself thinking "an independent review + would strengthen my report" — that review is already scheduled. + Report instead. + ## Code Organization You reason best about code you can hold in context at once, and your edits are more diff --git a/plugins/codex/plugins/superpowers/skills/subagent-driven-development/re-review-prompt.md b/plugins/codex/plugins/superpowers/skills/subagent-driven-development/re-review-prompt.md index 18b0fb8a..ad74b10b 100644 --- a/plugins/codex/plugins/superpowers/skills/subagent-driven-development/re-review-prompt.md +++ b/plugins/codex/plugins/superpowers/skills/subagent-driven-development/re-review-prompt.md @@ -43,6 +43,15 @@ Subagent (general-purpose): Your review is read-only on this checkout. Do not mutate the working tree, the index, HEAD, or branch state in any way. + ## You Do Not Dispatch Subagents + + Do all of this review yourself. Never spawn a subagent to review part + of the diff, and never spawn another reviewer for a second opinion. + This process already provides every review seat the work gets; a + reviewer you spawn duplicates one of them at full cost, and its + verdict counts for nothing. If the diff feels too large for one + pass, review it in passes yourself and say so in your report. + ## Scope Your scope is the findings list and the fix diff. Verdict every finding. diff --git a/plugins/codex/plugins/superpowers/skills/subagent-driven-development/task-reviewer-prompt.md b/plugins/codex/plugins/superpowers/skills/subagent-driven-development/task-reviewer-prompt.md index fefaea8a..ce796948 100644 --- a/plugins/codex/plugins/superpowers/skills/subagent-driven-development/task-reviewer-prompt.md +++ b/plugins/codex/plugins/superpowers/skills/subagent-driven-development/task-reviewer-prompt.md @@ -52,6 +52,15 @@ Subagent (general-purpose): Your review is read-only on this checkout. Do not mutate the working tree, the index, HEAD, or branch state in any way. + ## You Do Not Dispatch Subagents + + Do all of this review yourself. Never spawn a subagent to review part + of the diff, and never spawn another reviewer for a second opinion. + This process already provides every review seat the work gets; a + reviewer you spawn duplicates one of them at full cost, and its + verdict counts for nothing. If the diff feels too large for one + pass, review it in passes yourself and say so in your report. + ## Do Not Trust the Report Treat the implementer's report as unverified claims about the code. It @@ -75,6 +84,13 @@ Subagent (general-purpose): Warnings or other noise in the implementer's reported test output are findings — test output should be pristine. + Evidence you cannot see is not evidence that doesn't exist. If the + report or its test evidence looks truncated, or you cannot locate the + results it claims, re-read the file at its stated path — and if it is + genuinely missing or garbled, report that as a gap for the controller. + Re-running the suite to regenerate what you failed to read is not + verification; illegibility of the evidence is not invalidation of it. + ## Part 1: Spec Compliance Compare the diff against What Was Requested: @@ -86,6 +102,12 @@ Subagent (general-purpose): - **Misunderstood:** right feature built the wrong way, wrong problem solved + If the brief lists several files each with its own change (a batched + dispatch), check the diff against that list file by file: every listed + file must have its corresponding hunk. A listed file the diff never + touches is a Missing finding, no matter how clean the rest of the + batch looks. + If a requirement cannot be verified from this diff alone (it lives in unchanged code or spans tasks), report it as a ⚠️ item instead of broadening your search. diff --git a/plugins/codex/plugins/superpowers/skills/using-superpowers/SKILL.md b/plugins/codex/plugins/superpowers/skills/using-superpowers/SKILL.md index 7cde1c21..dd6f7eb8 100644 --- a/plugins/codex/plugins/superpowers/skills/using-superpowers/SKILL.md +++ b/plugins/codex/plugins/superpowers/skills/using-superpowers/SKILL.md @@ -56,6 +56,7 @@ If your harness appears here, read its reference file for special instructions: - Codex: `references/codex-tools.md` - Pi: `references/pi-tools.md` - Antigravity: `references/antigravity-tools.md` +- Hermes Agent: `references/hermes-tools.md` ## User Instructions diff --git a/plugins/codex/plugins/superpowers/skills/using-superpowers/references/codex-tools.md b/plugins/codex/plugins/superpowers/skills/using-superpowers/references/codex-tools.md index b14b5858..e4488fb2 100644 --- a/plugins/codex/plugins/superpowers/skills/using-superpowers/references/codex-tools.md +++ b/plugins/codex/plugins/superpowers/skills/using-superpowers/references/codex-tools.md @@ -7,7 +7,76 @@ Add to your Codex config (`~/.codex/config.toml`): multi_agent = true ``` -This enables `spawn_agent`, `wait_agent`, and `close_agent` for skills like `dispatching-parallel-agents` and `subagent-driven-development`. When using subagent-driven-development, close reviewer subagents when their review returns. Keep each implementer subagent open until its task's review passes — the fix loop resumes the implementer — then close it. If your harness cannot send another message to a spawned agent, dispatch each fix round as a fresh implementer carrying the brief, the report file, and the findings. +This enables the multi-agent tools that skills like +`dispatching-parallel-agents` and `subagent-driven-development` use. +Which tools you get depends on the multi-agent version your model +preset selects (current presets run V2; older ones run V1). Trust your +actual tool list over any table — including this one — when they +disagree. + +- **Spawning:** give children a clean context with + `spawn_agent {fork_turns: "none"}`; the default `"all"` copies your + entire transcript into the child. On Codex 0.145+, role files under + `~/.codex/agents/` attach to isolated forks via `agent_type`. + Full-history forks accept `model` and `reasoning_effort` overrides + (only `agent_type` is refused there) — isolated forks are the SDD + default for context hygiene, not because overrides require them. +- **Fix rounds:** resume the implementer with `followup_task` — it + delivers your message, triggers a turn, and transparently reloads a + child the harness evicted. Never dispatch a fresh implementer on the + theory that a spawned agent cannot be messaged again; on V2 it + always can. +- **Lifecycle:** V2 has no `close_agent`. Finished children are + evicted automatically when slots are needed; leaving them unclosed + costs nothing. Only V1 sessions have `close_agent` — there, close + reviewers when their review returns, and close each implementer + after its task's review passes. +- **Model names:** never copy a model name from a skill, table, or old + session into `spawn_agent` without checking it against your current + spawn allowlist — V2 accepts only V2-capable presets and hard-errors + on the rest. + +## Waiting on children + +`wait_agent` is an event subscription, not a poll: a long wait wakes +the moment a child produces mailbox activity, with the same latency as +a short one. Short-timeout polling buys nothing and costs a tool call — +and a context rebill — per poll. In measured sessions, roughly +two-thirds of all wait calls were short polls that timed out. + +- While you still have local work, do not wait at all. A completed + child's final answer is pushed into your mailbox and arrives with + your next turn. +- When you are genuinely idle with children outstanding, wait in + bounded stretches: `wait_agent` with `timeout_ms` 300000-600000 + (5-10 minutes). After each stretch — wake or timeout — post one + status line, run `list_agents`, and chase any child that finished + without reporting. Never stack polls shorter than five minutes; the + event subscription wakes a bounded stretch just as fast as a short + one. +- Completion mail cannot wake an idle controller (it is delivered + without triggering a turn); covering that idle window is + `wait_agent`'s only job. A stretch that times out with no activity + is your cue to reconcile, not to shorten the next stretch. + +## Model routing on spawns + +Every `spawn_agent` you issue — including when you are yourself a +spawned child running a fan-out — sets `model` AND `reasoning_effort` +explicitly, per the Model Selection rules of the skill you are +executing. Setting `model` alone is a trap: the child's effort +silently resets to that model's default, not to yours. + +Ask your human partner to add a machine-level backstop to +`~/.codex/config.toml` so any spawn that slips through still routes to +a deliberate tier instead of silently inheriting the session's most +expensive model: + +```toml +[agents] +default_subagent_model = "" +default_subagent_reasoning_effort = "medium" +``` ## Environment Detection diff --git a/plugins/codex/plugins/superpowers/skills/using-superpowers/references/hermes-tools.md b/plugins/codex/plugins/superpowers/skills/using-superpowers/references/hermes-tools.md new file mode 100644 index 00000000..0f1fa57b --- /dev/null +++ b/plugins/codex/plugins/superpowers/skills/using-superpowers/references/hermes-tools.md @@ -0,0 +1,56 @@ +# Hermes Agent Tool Mapping + +Skills speak in actions ("dispatch a subagent", "create a todo", "read a file"). On Hermes Agent these resolve to the tools below. + +## Tools + +| Action skills request | Hermes tool | +|---|---| +| Read a file | `read_file` | +| Create a new file | `write_file` | +| Edit a file (targeted patch) | `patch` | +| Run a shell command | `terminal` | +| Search file contents | `search_files` | +| Find files by name | `terminal` with `find` | +| Fetch a URL / read a webpage | `web_extract(urls=[...])` | +| Search the web | `web_search(query=...)` | +| Dispatch a subagent | `delegate_task(goal=..., context=..., toolsets=[...], role="leaf")` | +| Task tracking | `todo` tool | +| Invoke a skill | `skill_view("skill-name")` | + +## Instructions file + +When a skill mentions "your instructions file," on Hermes Agent this is **`AGENTS.md`** in the project directory, or **`SOUL.md`** globally at `~/.hermes/SOUL.md`. + +## Invoking a skill + +Hermes Agent has a `skills` toolset with `skill_view` and `skills_list` tools. +To invoke a superpowers skill, use: + +``` +skill_view("brainstorming") +skill_view("test-driven-development") +``` + +If `skill_view` cannot find a superpowers skill (it may not appear in the catalog +until the plugin fully registers it), fall back to reading the SKILL.md directly: + +``` +read_file(path="~/.hermes/plugins/superpowers/skills//SKILL.md") +``` + +This fallback is the same mechanism used by other harnesses without native skill loading. + +## Subagent dispatch + +Use `delegate_task` to spawn isolated subagents for parallel or sequential workstreams: + +``` +delegate_task(goal="...", context="...", toolsets=[...], role="leaf") +``` + +If `delegate_task` is unavailable, do the work inline rather than inventing tool calls. + +## Task tracking + +Use the `todo` tool for task tracking within a session. For multi-agent task boards, use `hermes kanban` CLI if available. Treat older `TodoWrite` references as the task-tracking action. diff --git a/plugins/codex/plugins/superpowers/skills/writing-plans/SKILL.md b/plugins/codex/plugins/superpowers/skills/writing-plans/SKILL.md index 092013ac..1a803c44 100644 --- a/plugins/codex/plugins/superpowers/skills/writing-plans/SKILL.md +++ b/plugins/codex/plugins/superpowers/skills/writing-plans/SKILL.md @@ -66,6 +66,9 @@ independently testable deliverable. **Tech Stack:** [Key technologies/libraries] +**Spec:** [path to the spec/design doc this plan implements — the plan +argues from the spec, so the spec travels with it; executors read both] + ## Global Constraints [The spec's project-wide requirements — version floors, dependency limits, diff --git a/plugins/codex/plugins/superpowers/skills/writing-skills/render-graphs.js b/plugins/codex/plugins/superpowers/skills/writing-skills/render-graphs.js index 1d670fbb..59e74b54 100755 --- a/plugins/codex/plugins/superpowers/skills/writing-skills/render-graphs.js +++ b/plugins/codex/plugins/superpowers/skills/writing-skills/render-graphs.js @@ -13,9 +13,9 @@ * Requires: graphviz (dot) installed on system */ -const fs = require('fs'); -const path = require('path'); -const { execSync } = require('child_process'); +import * as fs from 'fs'; +import * as path from 'path'; +import { execFileSync } from 'child_process'; function extractDotBlocks(markdown) { const blocks = []; @@ -69,7 +69,7 @@ ${bodies.join('\n\n')} function renderToSvg(dotContent) { try { - return execSync('dot -Tsvg', { + return execFileSync('dot', ['-Tsvg'], { input: dotContent, encoding: 'utf-8', maxBuffer: 10 * 1024 * 1024 @@ -107,9 +107,10 @@ function main() { process.exit(1); } - // Check if dot is available + // Check if dot is available. Run the binary directly rather than probing + // with `which`, which is not a command on Windows. try { - execSync('which dot', { encoding: 'utf-8' }); + execFileSync('dot', ['-V'], { stdio: 'ignore' }); } catch { console.error('Error: graphviz (dot) not found. Install with:'); console.error(' brew install graphviz # macOS'); diff --git a/plugins/codex/plugins/ui-ux-pro-max/README.md b/plugins/codex/plugins/ui-ux-pro-max/README.md index 3fb27ad4..f8e66c08 100755 --- a/plugins/codex/plugins/ui-ux-pro-max/README.md +++ b/plugins/codex/plugins/ui-ux-pro-max/README.md @@ -585,6 +585,23 @@ rm -rf .windsurf/skills/ui-ux-pro-max # Windsurf rm -rf .agents/skills/ui-ux-pro-max # Antigravity / Codex ``` +### Claude.ai's "Upload a skill" dialog says "Zip contains too many files (maximum 200)" + +Do not upload the full GitHub repository ZIP. It is a development checkout that includes source code, CLI assets, documentation, previews, and multiple bundled skills, so it exceeds Claude's 200-file upload limit. It is not a Claude skill upload artifact, and this project does not currently publish a separate manual-upload ZIP for Claude.ai. + +For Claude Code, install through the Marketplace: + +```bash +/plugin marketplace add nextlevelbuilder/ui-ux-pro-max-skill +/plugin install ui-ux-pro-max@ui-ux-pro-max-skill +``` + +Or use the CLI installer: + +```bash +npx ui-ux-pro-max-cli init --ai claude +``` + ### Claude Marketplace install fails with "Zip file contains a symbolic link" This is a known issue with versions prior to v2.5.1. The repository used symlinks internally which some installation tools can't handle. **Fix:** use the CLI installer instead: 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 159f3054..7f453401 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": "abb7f2fd5a083fa1ff55c326a963ff0d95c33f99", + "commit": "97eb2a20032f0833e3d317162208a60385b0f96e", "adapter": "claude-skill", "sourcePath": ".claude/skills/ui-ux-pro-max", - "syncedAt": "2026-08-06T16:00:02Z" + "syncedAt": "2026-08-13T08:38:10Z" } diff --git a/scripts/sync_external_plugins.ps1 b/scripts/sync_external_plugins.ps1 index f735f836..57acf47e 100644 --- a/scripts/sync_external_plugins.ps1 +++ b/scripts/sync_external_plugins.ps1 @@ -871,6 +871,27 @@ function Sync-SkillCollection { $skillDirs = @(Get-ChildItem -LiteralPath $sourceSkillsRoot -Directory | Where-Object { Test-Path -LiteralPath (Join-Path $_.FullName "SKILL.md") } | Sort-Object Name) + $includeSkills = @() + if ($Source.PSObject.Properties.Name -contains "includeSkills" -and $Source.includeSkills) { + $includeSkills = @($Source.includeSkills | ForEach-Object { ([string]$_).Trim() } | Where-Object { $_ }) + } + if ($includeSkills.Count -gt 0) { + $skillDirsByName = @{} + foreach ($skillDir in $skillDirs) { + $skillDirsByName[$skillDir.Name] = $skillDir + } + $selectedSkillDirs = @() + foreach ($skillName in $includeSkills) { + if ($skillName -notmatch '^[a-z0-9]+(?:-[a-z0-9]+)*$') { + throw "skill-collection includeSkills contains invalid name: $skillName" + } + if (-not $skillDirsByName.ContainsKey($skillName)) { + throw "skill-collection includeSkills skill not found: $skillName" + } + $selectedSkillDirs += $skillDirsByName[$skillName] + } + $skillDirs = $selectedSkillDirs + } if ($skillDirs.Count -eq 0) { throw "skill-collection adapter found no child SKILL.md files: $sourceSkillsRoot" }