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.
This commit is contained in:
@@ -24,8 +24,8 @@
|
|||||||
"repo": "https://github.com/Yeachan-Heo/oh-my-codex.git",
|
"repo": "https://github.com/Yeachan-Heo/oh-my-codex.git",
|
||||||
"ref": "main",
|
"ref": "main",
|
||||||
"adapter": "codex-plugin",
|
"adapter": "codex-plugin",
|
||||||
"commit": "b48df502d566430be768d3c60f2f51fa91630396",
|
"commit": "2da36489cfa07ef1df802f01865e7d959d36f236",
|
||||||
"syncedAt": "2026-09-01T16:00:00Z"
|
"syncedAt": "2026-09-03T09:20:38Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "ui-ux-pro-max",
|
"id": "ui-ux-pro-max",
|
||||||
@@ -33,8 +33,8 @@
|
|||||||
"repo": "https://github.com/nextlevelbuilder/ui-ux-pro-max-skill.git",
|
"repo": "https://github.com/nextlevelbuilder/ui-ux-pro-max-skill.git",
|
||||||
"ref": "main",
|
"ref": "main",
|
||||||
"adapter": "claude-skill",
|
"adapter": "claude-skill",
|
||||||
"commit": "58c220ff9d02be80523b06c03471925c52e8ab5d",
|
"commit": "91c193ac059b487d13ce535c7015b021eb71c841",
|
||||||
"syncedAt": "2026-09-02T16:00:01Z"
|
"syncedAt": "2026-09-03T09:20:38Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "caveman",
|
"id": "caveman",
|
||||||
@@ -96,8 +96,8 @@
|
|||||||
"repo": "https://github.com/hugohe3/ppt-master.git",
|
"repo": "https://github.com/hugohe3/ppt-master.git",
|
||||||
"ref": "main",
|
"ref": "main",
|
||||||
"adapter": "claude-skill",
|
"adapter": "claude-skill",
|
||||||
"commit": "06abd6ed41a6d066f1be035852432f127687de0e",
|
"commit": "6a8e91e244c987e49fbc4744be3b6d235f4f1e77",
|
||||||
"syncedAt": "2026-09-03T02:28:39Z"
|
"syncedAt": "2026-09-03T09:20:38Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "grill-me",
|
"id": "grill-me",
|
||||||
@@ -114,8 +114,8 @@
|
|||||||
"repo": "https://git.playones.com/huzhifa/skill-git-push.git",
|
"repo": "https://git.playones.com/huzhifa/skill-git-push.git",
|
||||||
"ref": "main",
|
"ref": "main",
|
||||||
"adapter": "codex-plugin",
|
"adapter": "codex-plugin",
|
||||||
"commit": "72c856975eaa340b023eb5393d958ca0bff1f59c",
|
"commit": "3a0b288dfa4df0657dc63c0fd424069432016595",
|
||||||
"syncedAt": "2026-09-02T10:37:18Z"
|
"syncedAt": "2026-09-03T09:20:38Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "etunel-role-collaboration",
|
"id": "etunel-role-collaboration",
|
||||||
@@ -132,8 +132,8 @@
|
|||||||
"repo": "https://github.com/vercel/next.js.git",
|
"repo": "https://github.com/vercel/next.js.git",
|
||||||
"ref": "canary",
|
"ref": "canary",
|
||||||
"adapter": "skill-collection",
|
"adapter": "skill-collection",
|
||||||
"commit": "69ec884e44d1050013724facfe452248e5b9de55",
|
"commit": "fb4c498852c0884cbc356cac4c2a6efec98da50f",
|
||||||
"syncedAt": "2026-09-03T02:28:39Z"
|
"syncedAt": "2026-09-03T09:20:38Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "shuorenhua",
|
"id": "shuorenhua",
|
||||||
|
|||||||
@@ -3,5 +3,5 @@
|
|||||||
"name": "playwright浏览器自动化操作",
|
"name": "playwright浏览器自动化操作",
|
||||||
"version": "20260605",
|
"version": "20260605",
|
||||||
"keySource": "none",
|
"keySource": "none",
|
||||||
"syncedAt": "2026-09-03T02:47:41Z"
|
"syncedAt": "2026-09-03T09:22:45Z"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
"sourceId": "next-skills",
|
"sourceId": "next-skills",
|
||||||
"repo": "https://github.com/vercel/next.js.git",
|
"repo": "https://github.com/vercel/next.js.git",
|
||||||
"ref": "canary",
|
"ref": "canary",
|
||||||
"commit": "69ec884e44d1050013724facfe452248e5b9de55",
|
"commit": "fb4c498852c0884cbc356cac4c2a6efec98da50f",
|
||||||
"adapter": "skill-collection",
|
"adapter": "skill-collection",
|
||||||
"sourcePath": "skills",
|
"sourcePath": "skills",
|
||||||
"syncedAt": "2026-09-03T02:28:39Z"
|
"syncedAt": "2026-09-03T09:20:38Z"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "oh-my-codex",
|
"name": "oh-my-codex",
|
||||||
"version": "0.21.2",
|
"version": "0.21.3",
|
||||||
"description": "oh-my-codex 是 Codex CLI 的多 Agent 编排、结构化工作流、插件级 hooks、MCP 和 HUD 扩展插件。",
|
"description": "oh-my-codex 是 Codex CLI 的多 Agent 编排、结构化工作流、插件级 hooks、MCP 和 HUD 扩展插件。",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Yeachan Heo",
|
"name": "Yeachan Heo",
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
"sourceId": "oh-my-codex",
|
"sourceId": "oh-my-codex",
|
||||||
"repo": "https://github.com/Yeachan-Heo/oh-my-codex.git",
|
"repo": "https://github.com/Yeachan-Heo/oh-my-codex.git",
|
||||||
"ref": "main",
|
"ref": "main",
|
||||||
"commit": "b48df502d566430be768d3c60f2f51fa91630396",
|
"commit": "2da36489cfa07ef1df802f01865e7d959d36f236",
|
||||||
"adapter": "codex-plugin",
|
"adapter": "codex-plugin",
|
||||||
"sourcePath": "plugins/oh-my-codex",
|
"sourcePath": "plugins/oh-my-codex",
|
||||||
"syncedAt": "2026-09-01T16:00:00Z"
|
"syncedAt": "2026-09-03T09:20:38Z"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,61 +55,36 @@ Thanks to [Kimi](https://www.kimi.com/code/?aff=ppt-master) for sponsoring this
|
|||||||
> **Editable is already table stakes — what sets PPT Master apart is native depth.** It hands you a real PowerPoint: slide masters, native shapes, data-backed charts and tables — not flat text boxes, and not a filled-in template. It also does more than lay slides out nicely — it reasons the argument into shape first, then designs; and that native depth keeps **converging with PowerPoint itself**, adding more of its native capabilities release after release. In form, it's a workflow that runs inside any agent-capable AI tool: hand the AI your topic or material, and it generates on your machine — your data stays local, no platform or model lock-in. How it works and where the limits are → [Product Positioning](#product-positioning).
|
> **Editable is already table stakes — what sets PPT Master apart is native depth.** It hands you a real PowerPoint: slide masters, native shapes, data-backed charts and tables — not flat text boxes, and not a filled-in template. It also does more than lay slides out nicely — it reasons the argument into shape first, then designs; and that native depth keeps **converging with PowerPoint itself**, adding more of its native capabilities release after release. In form, it's a workflow that runs inside any agent-capable AI tool: hand the AI your topic or material, and it generates on your machine — your data stays local, no platform or model lock-in. How it works and where the limits are → [Product Positioning](#product-positioning).
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
|
<a href="#quick-start"><strong>Quick Start</strong></a> ·
|
||||||
<a href="https://hugohe3.github.io/ppt-master-examples/"><strong>Live Demo</strong></a> ·
|
<a href="https://hugohe3.github.io/ppt-master-examples/"><strong>Live Demo</strong></a> ·
|
||||||
<a href="https://github.com/hugohe3/ppt-master-examples"><strong>Examples</strong></a> ·
|
<a href="https://github.com/hugohe3/ppt-master-examples"><strong>Examples</strong></a> ·
|
||||||
<a href="./docs/faq.md"><strong>FAQ</strong></a> ·
|
<a href="./docs/faq.md"><strong>FAQ</strong></a> ·
|
||||||
<a href="./docs/roadmap.md"><strong>Roadmap</strong></a>
|
<a href="./docs/roadmap.md"><strong>Roadmap</strong></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<sub>The gallery below was generated in <strong>May 2026</strong> with Claude Opus 4.7 + <code>gpt-image-2</code> — one pass each, no manual polish.</sub>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center" width="33%">
|
<td align="center" width="33%">
|
||||||
<a href="https://hugohe3.github.io/ppt-master-examples/viewer.html?project=ppt169_pritzker_2026"><img src="docs/assets/screenshots/preview_pritzker_2026.png" alt="Editorial magazine — Pritzker 2026 architecture review" /></a><br/>
|
<a href="https://hugohe3.github.io/ppt-master-examples/viewer.html?project=ppt169_pixel_breakfast_atlas"><img src="docs/assets/screenshots/preview_pixel_breakfast_atlas.webp" alt="Pixel art — Chinese breakfast atlas" /></a><br/>
|
||||||
<sub><b>Editorial Magazine</b> — architecture photography, calm typographic grid<br/>
|
<sub><b>Pixel Art</b> — Chinese breakfast atlas: AI sprite sheets, HUD panels, Morph and 8-bit sound cues</sub>
|
||||||
<a href="https://hugohe3.github.io/ppt-master-examples/viewer.html?project=ppt169_pritzker_2026">Flip online</a> · <a href="https://raw.githubusercontent.com/hugohe3/ppt-master-examples/main/examples/ppt169_pritzker_2026/exports/pritzker_2026.pptx">Download .pptx</a></sub>
|
|
||||||
</td>
|
</td>
|
||||||
<td align="center" width="33%">
|
<td align="center" width="33%">
|
||||||
<a href="https://hugohe3.github.io/ppt-master-examples/viewer.html?project=ppt169_global_ai_capital_2026"><img src="docs/assets/screenshots/preview_global_ai_capital.png" alt="Data journalism — Global AI Capital 2026" /></a><br/>
|
<a href="https://hugohe3.github.io/ppt-master-examples/viewer.html?project=ppt169_attention_is_all_you_need"><img src="docs/assets/screenshots/preview_attention_is_all_you_need.webp" alt="Technical blueprint — Attention Is All You Need" /></a><br/>
|
||||||
<sub><b>Data Journalism</b> — Bloomberg-style dark dashboard, chart-driven<br/>
|
<sub><b>Technical Blueprint</b> — Transformer paper walkthrough: diagrams, native formulas, notes and animations</sub>
|
||||||
<a href="https://hugohe3.github.io/ppt-master-examples/viewer.html?project=ppt169_global_ai_capital_2026">Flip online</a> · <a href="https://raw.githubusercontent.com/hugohe3/ppt-master-examples/main/examples/ppt169_global_ai_capital_2026/exports/global_ai_capital_2026.pptx">Download .pptx</a></sub>
|
|
||||||
</td>
|
</td>
|
||||||
<td align="center" width="33%">
|
<td align="center" width="33%">
|
||||||
<a href="https://hugohe3.github.io/ppt-master-examples/viewer.html?project=ppt169_swiss_grid_systems"><img src="docs/assets/screenshots/preview_swiss_grid.png" alt="Swiss typographic grid — Grid Systems primer" /></a><br/>
|
<a href="https://hugohe3.github.io/ppt-master-examples/viewer.html?project=ppt169_china_telecom_2025"><img src="docs/assets/screenshots/preview_china_telecom_2025.webp" alt="Brand template — China Telecom 2025 results" /></a><br/>
|
||||||
<sub><b>Swiss Grid</b> — strict modular grid, restrained type, red-accent<br/>
|
<sub><b>Brand Template</b> — China Telecom 2025 results on the company's own deck template, with a native-chart export</sub>
|
||||||
<a href="https://hugohe3.github.io/ppt-master-examples/viewer.html?project=ppt169_swiss_grid_systems">Flip online</a> · <a href="https://raw.githubusercontent.com/hugohe3/ppt-master-examples/main/examples/ppt169_swiss_grid_systems/exports/swiss_grid_systems.pptx">Download .pptx</a></sub>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td align="center" width="33%">
|
|
||||||
<a href="https://hugohe3.github.io/ppt-master-examples/viewer.html?project=ppt169_glassmorphism_demo"><img src="docs/assets/screenshots/preview_glassmorphism_demo.png" alt="Glassmorphism SaaS — AI Agent engineering demo" /></a><br/>
|
|
||||||
<sub><b>Glassmorphism SaaS</b> — translucent layers, gradient depth, product UI<br/>
|
|
||||||
<a href="https://hugohe3.github.io/ppt-master-examples/viewer.html?project=ppt169_glassmorphism_demo">Flip online</a> · <a href="https://raw.githubusercontent.com/hugohe3/ppt-master-examples/main/examples/ppt169_glassmorphism_demo/exports/glassmorphism_demo.pptx">Download .pptx</a></sub>
|
|
||||||
</td>
|
|
||||||
<td align="center" width="33%">
|
|
||||||
<a href="https://hugohe3.github.io/ppt-master-examples/viewer.html?project=ppt169_sugar_rush_memphis"><img src="docs/assets/screenshots/preview_sugar_rush_memphis.png" alt="Memphis pop — Sugar Rush festival" /></a><br/>
|
|
||||||
<sub><b>Memphis Pop</b> — bold primaries, geometric patterns, playful energy<br/>
|
|
||||||
<a href="https://hugohe3.github.io/ppt-master-examples/viewer.html?project=ppt169_sugar_rush_memphis">Flip online</a> · <a href="https://raw.githubusercontent.com/hugohe3/ppt-master-examples/main/examples/ppt169_sugar_rush_memphis/exports/sugar_rush_memphis.pptx">Download .pptx</a></sub>
|
|
||||||
</td>
|
|
||||||
<td align="center" width="33%">
|
|
||||||
<a href="https://hugohe3.github.io/ppt-master-examples/viewer.html?project=ppt169_indie_bookstore_zine_guide"><img src="docs/assets/screenshots/preview_indie_bookstore_zine.png" alt="Risograph zine — Indie bookstore guide" /></a><br/>
|
|
||||||
<sub><b>Risograph Zine</b> — duotone print, hand-made bookstore-culture feel<br/>
|
|
||||||
<a href="https://hugohe3.github.io/ppt-master-examples/viewer.html?project=ppt169_indie_bookstore_zine_guide">Flip online</a> · <a href="https://raw.githubusercontent.com/hugohe3/ppt-master-examples/main/examples/ppt169_indie_bookstore_zine_guide/exports/indie_bookstore_zine_guide.pptx">Download .pptx</a></sub>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<sub>Downloading any .pptx and opening it in PowerPoint is the fastest way to see what it can really do.<br/><a href="https://hugohe3.github.io/ppt-master-examples/">Flip through all examples online →</a> · <a href="https://github.com/hugohe3/ppt-master-examples">Source repository</a> · <a href="./docs/why-ppt-master.md">Why PPT Master?</a></sub>
|
<sub>Every example is a single pass with no manual polish; downloading a .pptx and opening it in PowerPoint is the fastest way to see what it can really do.<br/><a href="https://hugohe3.github.io/ppt-master-examples/">Flip through all examples online →</a> · <a href="https://github.com/hugohe3/ppt-master-examples">Source repository</a> · <a href="./docs/why-ppt-master.md">Why PPT Master?</a></sub>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Drop in your source material, and what you get back isn't a static layout you can edit — it's **a complete deck with real PowerPoint behavior**: native slide transitions, opt-in entrance / emphasis / motion-path / exit animations (off by default), speaker notes that can become audio narration and even video, charts and tables that can ship as real data-backed PowerPoint objects, and it can follow your own PPT template — present it as-is, and keep refining. How to use each capability → [Getting Started](./docs/getting-started.md).
|
|
||||||
|
|
||||||
## Product Positioning
|
## Product Positioning
|
||||||
|
|
||||||
**Editable is now table stakes — the real question is how much of PowerPoint you actually get.** PPT Master delivers PowerPoint's native object model itself, and in depth: native shapes and connectors with working adjustment handles, data-backed charts and tables on demand, and the full text / picture / fill / effect model — click any element and keep editing it as a native PowerPoint object; and through the template / structured route, it can hand you a deck with real slide masters and layouts (`p:sldMaster` / `p:sldLayout` inheritance).
|
**Editable is now table stakes — the real question is how much of PowerPoint you actually get.** PPT Master delivers PowerPoint's native object model itself, and in depth: native shapes and connectors with working adjustment handles, data-backed charts and tables on demand, and the full text / picture / fill / effect model — click any element and keep editing it as a native PowerPoint object; and through the template / structured route, it can hand you a deck with real slide masters and layouts (`p:sldMaster` / `p:sldLayout` inheritance).
|
||||||
@@ -118,7 +93,7 @@ And that depth is a **direction of travel, not a fixed checklist.** PPT Master's
|
|||||||
|
|
||||||
In form, it's a workflow (a "skill") that runs inside any agent-capable AI tool: tell it in chat — "make a deck from this PDF" — and it runs the workflow on your machine and exports a natively editable `.pptx`. No coding on your side; you do exactly three things — install Python, install an AI tool, drop in your material.
|
In form, it's a workflow (a "skill") that runs inside any agent-capable AI tool: tell it in chat — "make a deck from this PDF" — and it runs the workflow on your machine and exports a natively editable `.pptx`. No coding on your side; you do exactly three things — install Python, install an AI tool, drop in your material.
|
||||||
|
|
||||||
Generating a new deck from source documents is the main pipeline, but not the only route. PPT Master can also distill reusable brand / style / layout / deck templates from your references, fill an existing `.pptx` with new content while preserving its design, and add native transitions, animations, and narration to a finished deck — each route with an explicit contract for what gets preserved.
|
Generating a new deck from source documents is the main pipeline, but not the only route. PPT Master can also distill reusable brand / style / layout / deck templates from your references, fill an existing `.pptx` with new content while preserving its design, and add native transitions, animations, and narration to a finished deck — each route with an explicit contract for what gets preserved. How to use each capability → [Getting Started](./docs/getting-started.md).
|
||||||
|
|
||||||
On top of that native depth, this form comes with three promises:
|
On top of that native depth, this form comes with three promises:
|
||||||
|
|
||||||
@@ -332,7 +307,7 @@ You: Quickly generate a 5-page deck from projects/q3-report/sources/report.pdf
|
|||||||
|
|
||||||
Whatever you state explicitly is followed; whatever you leave unspecified the agent decides on its own instead of asking. It still converts sources, fills factual gaps, applies the shared visual baseline, and uses images/icons/native shapes/charts/tables/PowerPoint-native inline or block formulas as needed — it drops interaction and durable planning, not presentation capability. It is one-pass and non-resumable, and there is no `svg_final/` preview. Full guide → [Quick mode](./docs/getting-started.md#quick-mode).
|
Whatever you state explicitly is followed; whatever you leave unspecified the agent decides on its own instead of asking. It still converts sources, fills factual gaps, applies the shared visual baseline, and uses images/icons/native shapes/charts/tables/PowerPoint-native inline or block formulas as needed — it drops interaction and durable planning, not presentation capability. It is one-pass and non-resumable, and there is no `svg_final/` preview. Full guide → [Quick mode](./docs/getting-started.md#quick-mode).
|
||||||
|
|
||||||
> **Output:** The SVG pipeline has one PPTX converter: it reads `svg_output/` and writes a directly editable native DrawingML deck to `exports/<name>_<timestamp>.pptx`. The default Generate flow runs `finalize_svg.py` and produces self-contained previews in `svg_final/`; PowerPoint's manual **Convert to Shape** command is outside the supported contract. Explicit [quick generation](./skills/ppt-master/workflows/profiles/quick-generate.md) skips Strategist, confirmation, `design_spec.md`, `spec_lock.md`, and `finalize_svg.py`: whatever you state explicitly is followed, and whatever you leave unspecified the agent decides directly in one active context. It still converts sources, researches factual gaps, applies shared mode/style/aesthetic guidance, prepares required images/icons, authors formulas as native inline or block markers, considers native shapes and data visualizations, hand-authors SVG, passes the lockless Quick final quality check, and exports the final PPTX. It writes no substitute plan and cannot resume after context loss. Formula markers compile their LaTeX payload to editable OMML for PowerPoint 2010+; block groups and inline `<tspan>` runs keep ordinary SVG previews that are replaced during export. Formula rendering and editability in Keynote, WPS, LibreOffice, and other non-PowerPoint clients are not part of this contract. Ordinary export capabilities remain available as needed, including native chart/table replacement, notes, motion, narration, and diagnostics; notes, custom object animation, and narration start off, and the agent may enable them when the request or deck needs them. A default-path Quick export writes the normal postflight report and snapshots `svg_output/` to `backup/<timestamp>/svg_output/`; an explicit output path keeps the ordinary no-backup behavior. By default charts and tables export as individually editable SVG-derived DrawingML shapes, which prioritize cross-app visual consistency. Pass `--native-charts-and-tables` to replace eligible groups with PowerPoint-native Chart/Table objects backed by data, which provide **Edit Data** and object-specific controls but may render differently across apps; this variant is saved as `exports/<name>_<timestamp>_native_charts_tables.pptx`. Both chart/table export variants are editable—the distinction is the PowerPoint object model, not editability itself.
|
> **Output:** the deck lands in `exports/<name>_<timestamp>.pptx` as natively editable DrawingML; the default flow also writes self-contained page previews to `svg_final/`. Charts and tables ship as editable shapes by default; pass `--native-charts-and-tables` for data-backed PowerPoint Chart / Table objects with **Edit Data**, saved as a separate `_native_charts_tables.pptx`. Formulas compile to editable OMML for PowerPoint 2010+. Backups, notes, animation and narration switches, and the non-PowerPoint boundaries → [FAQ](./docs/faq.md).
|
||||||
|
|
||||||
> **Already have a `.pptx` you want to reuse?** Give the AI the deck and material and ask it to "fill this deck with the new content" — Edit Native PPTX keeps the design and unchanged pages byte-for-byte, edits chosen pages, supports selection/reordering, and can add notes or narration. See the [FAQ](./docs/faq.md) and [workflow](./skills/ppt-master/workflows/edit-native-pptx.md).
|
> **Already have a `.pptx` you want to reuse?** Give the AI the deck and material and ask it to "fill this deck with the new content" — Edit Native PPTX keeps the design and unchanged pages byte-for-byte, edits chosen pages, supports selection/reordering, and can add notes or narration. See the [FAQ](./docs/faq.md) and [workflow](./skills/ppt-master/workflows/edit-native-pptx.md).
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
"sourceId": "ppt-master",
|
"sourceId": "ppt-master",
|
||||||
"repo": "https://github.com/hugohe3/ppt-master.git",
|
"repo": "https://github.com/hugohe3/ppt-master.git",
|
||||||
"ref": "main",
|
"ref": "main",
|
||||||
"commit": "06abd6ed41a6d066f1be035852432f127687de0e",
|
"commit": "6a8e91e244c987e49fbc4744be3b6d235f4f1e77",
|
||||||
"adapter": "claude-skill",
|
"adapter": "claude-skill",
|
||||||
"sourcePath": "skills/ppt-master",
|
"sourcePath": "skills/ppt-master",
|
||||||
"syncedAt": "2026-09-03T02:28:39Z"
|
"syncedAt": "2026-09-03T09:20:38Z"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ python3 scripts/slice_images.py <project>/images/illus_sheet.png --grid 2x3 \
|
|||||||
|
|
||||||
| Constraint | Rule |
|
| Constraint | Rule |
|
||||||
|---|---|
|
|---|---|
|
||||||
| **Strict key recovery** | Raise `--tolerance` only enough to absorb measured flat-field drift, `--inset` only for an isolated outer gutter, and regenerate or enlarge when an effect reaches an edge |
|
| **Strict key recovery** | Measure the smallest channel distance from any element pixel to the key first; raise `--tolerance` only enough to absorb measured flat-field drift and keep it below that distance, `--inset` only for an isolated outer gutter, and regenerate or enlarge when an effect reaches an edge. A `1x1` lettering sheet whose glyph touches the outer key border fails the same gate: pad the sheet with a key-colored border (about 10%) before slicing, or regenerate with more margin |
|
||||||
| **Clean isolated cells** | Fused cells, scene backgrounds, or flourishes crossing a cell make the sheet unusable; re-rolls follow only a strict keying failure or user/preview evidence, never taste |
|
| **Clean isolated cells** | Fused cells, scene backgrounds, or flourishes crossing a cell make the sheet unusable; re-rolls follow only a strict keying failure or user/preview evidence, never taste |
|
||||||
| **Enough source pixels** | Each cell at least 1.5–2× its display size (`1K` small accents, `2K` medium, `4K` large or enlarged) |
|
| **Enough source pixels** | Each cell at least 1.5–2× its display size (`1K` small accents, `2K` medium, `4K` large or enlarged) |
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -117,7 +117,7 @@ Operand count, preset choice, geometry, paint, rotation, and grouping come from
|
|||||||
|
|
||||||
## 3. Fragment Generation
|
## 3. Fragment Generation
|
||||||
|
|
||||||
`render` emits one object; `render-batch --input -` emits several already-selected objects for one page or template construction from a JSON array with the `render` fields (required `preset`, `id`, `frame` `[x, y, w, h]`; optional `object_kind`, `name`, `fill`, `fill_opacity`, `stroke`, `stroke_width`, `stroke_opacity`, `stroke_linecap`, `stroke_linejoin`, `filter_id`, `adjustments` such as `{"adj": "val 42000"}`). Paint comes from the page context with `spec_lock.md` roles as anchors (create-template: from the confirmed brief and template Design Spec); mirror/preserve input keeps source paint. The batch is transient input, never a project resource or multi-page plan, and never chooses layout.
|
`render` emits one object; `render-batch --input -` emits several already-selected objects for one page or template construction from a JSON array with the `render` fields (required `preset`, `id`, `frame` `[x, y, w, h]`; optional `object_kind`, `name`, `fill`, `fill_opacity`, `stroke`, `stroke_width`, `stroke_opacity`, `stroke_linecap`, `stroke_linejoin`, `filter_id`, `adjustments` such as `{"adj": "val 42000"}` — the object form of `render --adjust NAME=FORMULA`, keyed by guide name). Paint comes from the page context with `spec_lock.md` roles as anchors (create-template: from the confirmed brief and template Design Spec); mirror/preserve input keeps source paint. The batch is transient input, never a project resource or multi-page plan, and never chooses layout.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ Use `data-pptx-role` only when no specialized marker owns the behavior:
|
|||||||
| `header`, `footer`, `logo`, `watermark`, `chrome` | Slide-local static framing without Master/Layout ownership |
|
| `header`, `footer`, `logo`, `watermark`, `chrome` | Slide-local static framing without Master/Layout ownership |
|
||||||
| `page-number` | Slide-local number when no `slide-number` placeholder exists |
|
| `page-number` | Slide-local number when no `slide-number` placeholder exists |
|
||||||
|
|
||||||
On flat pages a direct root background image, a full-canvas scrim/decoration rectangle, or a free-floating decorative image layer that crosses text zones (a cut-paper piece, a texture fragment) may carry the role and remain a primitive with a stable unique `id`; do not add a `<g>` solely to avoid an ungrouped-element advisory. Never add structural roles to ordinary titles, body copy, cards, KPIs, diagrams, charts, icons, or images.
|
On flat pages a direct root background image, a full-canvas scrim/decoration rectangle, or a free-floating decorative image layer that crosses text zones (a cut-paper piece, a texture fragment) may carry the role and remain a primitive with a stable unique `id`; do not add a `<g>` solely to avoid an ungrouped-element advisory — a `<g>` carrying the role is still a root group and declares `data-pptx-bounds`. Never add structural roles to ordinary titles, body copy, cards, KPIs, diagrams, charts, icons, or images.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -187,7 +187,7 @@ These forms are needed only when the stated PPT behavior matters:
|
|||||||
|
|
||||||
### 4.3 Element Grouping (Mandatory)
|
### 4.3 Element Grouping (Mandatory)
|
||||||
|
|
||||||
**Hard rule — root groups protect body-text layout**: every visible direct root `<g>` except a compact helper-authored preset atom declares positive root-coordinate `data-pptx-bounds="x y width height"` sized as the intended module zone. On flat pages, maximize ordinary zones within canvas/sibling space without overlap; the checker fails root-group overlap beyond `1px`, warns on module text overflow through `5%` and fails above it, and fails any larger root-`viewBox` text overflow. Bounds do not clip or reflow. A native plate, caption, or label laid over a picture belongs inside that picture's root group, so it takes no separate zone and creates no root-group overlap, and a clipped picture's zone is its visible region; shrinking the picture to free a text zone is not the repair. Structured slots, structural-role groups, and a wholly off-canvas Morph endpoint marked `data-pptx-morph-staging="true"` are the only exemptions; thresholds and estimator detail: [`svg-contract.md`](../scripts/docs/svg-contract.md) §4.
|
**Hard rule — root groups protect body-text layout**: every visible direct root `<g>` except a compact helper-authored preset atom declares positive root-coordinate `data-pptx-bounds="x y width height"` sized as the intended module zone. On flat pages, maximize ordinary zones within canvas/sibling space without overlap; the checker fails root-group overlap beyond `1px`, warns on module text overflow through `5%` and fails above it, and fails any larger root-`viewBox` text overflow. Bounds do not clip or reflow. A native plate, caption, or label laid over a picture belongs inside that picture's root group, so it takes no separate zone and creates no root-group overlap, and a clipped picture's zone is its visible region; shrinking the picture to free a text zone is not the repair. Structured slots, structural-role groups, and a wholly off-canvas Morph endpoint marked `data-pptx-morph-staging="true"` are overlap-exempt only; thresholds and estimator: [`svg-contract.md`](../scripts/docs/svg-contract.md) §4.
|
||||||
|
|
||||||
Wrap each logical Slide-local body unit in one descriptive top-level `<g id>`; group count follows the page's semantic units, and each group becomes one stable animation target when animation is enabled. Nested implementation groups may remain anonymous, need no bounds, and create no animation step; use them only when internal subunits (icon + title, value + label, repeated rows) are useful to edit — there is no default nesting pattern, depth, or quota. Titles, direct atomic Master/Layout elements, and canvas-level static framing — background images and full-canvas scrim/decoration rectangles — may remain root primitives; on flat pages give such framing a stable `id` plus `data-pptx-role="background"` / `"decoration"` and never add a `<g>` solely to silence an ungrouped-element advisory.
|
Wrap each logical Slide-local body unit in one descriptive top-level `<g id>`; group count follows the page's semantic units, and each group becomes one stable animation target when animation is enabled. Nested implementation groups may remain anonymous, need no bounds, and create no animation step; use them only when internal subunits (icon + title, value + label, repeated rows) are useful to edit — there is no default nesting pattern, depth, or quota. Titles, direct atomic Master/Layout elements, and canvas-level static framing — background images and full-canvas scrim/decoration rectangles — may remain root primitives; on flat pages give such framing a stable `id` plus `data-pptx-role="background"` / `"decoration"` and never add a `<g>` solely to silence an ungrouped-element advisory.
|
||||||
|
|
||||||
|
|||||||
@@ -177,13 +177,15 @@ def get_project_info(project_path: str) -> Dict:
|
|||||||
Project information dictionary
|
Project information dictionary
|
||||||
"""
|
"""
|
||||||
project_path = Path(project_path)
|
project_path = Path(project_path)
|
||||||
|
# ``.`` or ``..`` carry no name of their own; parse the real directory name.
|
||||||
|
dir_name = project_path.resolve().name
|
||||||
|
|
||||||
# Parse directory name
|
# Parse directory name
|
||||||
parsed = parse_project_name(project_path.name)
|
parsed = parse_project_name(dir_name)
|
||||||
|
|
||||||
info = {
|
info = {
|
||||||
'path': str(project_path),
|
'path': str(project_path),
|
||||||
'dir_name': project_path.name,
|
'dir_name': dir_name,
|
||||||
'name': parsed['name'],
|
'name': parsed['name'],
|
||||||
'format': parsed['format'],
|
'format': parsed['format'],
|
||||||
'format_name': parsed['format_name'],
|
'format_name': parsed['format_name'],
|
||||||
@@ -465,13 +467,13 @@ def validate_project_structure(
|
|||||||
{'file_name': svg_file.name})
|
{'file_name': svg_file.name})
|
||||||
warnings.append(msg)
|
warnings.append(msg)
|
||||||
|
|
||||||
# Check directory naming format
|
# Check directory naming format (``.`` has no name of its own)
|
||||||
dir_name = project_path.name
|
dir_name = project_path.resolve().name
|
||||||
if not re.search(r'_\d{8}$', dir_name):
|
if not re.search(r'_\d{8}$', dir_name):
|
||||||
msg = f"Directory name missing date suffix (_YYYYMMDD): {dir_name}"
|
msg = f"Directory name missing date suffix (_YYYYMMDD): {dir_name}"
|
||||||
if use_helper and verbose:
|
if use_helper and verbose:
|
||||||
msg += "\n" + \
|
msg += "\n" + \
|
||||||
ErrorHelper.format_error_message('missing_date_suffix')
|
ErrorHelper.format_error_message('missing_project_date')
|
||||||
warnings.append(msg)
|
warnings.append(msg)
|
||||||
|
|
||||||
is_valid = len(errors) == 0
|
is_valid = len(errors) == 0
|
||||||
|
|||||||
@@ -643,7 +643,15 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
calibrate = subparsers.add_parser('calibrate', help='Calibrate project typography roles.')
|
calibrate = subparsers.add_parser('calibrate', help='Calibrate project typography roles.')
|
||||||
calibrate.add_argument('project_path', type=Path)
|
calibrate.add_argument('project_path', type=Path)
|
||||||
calibrate.add_argument('--outline', action='store_true')
|
calibrate.add_argument('--outline', action='store_true')
|
||||||
calibrate.add_argument('--role', action='append', type=_role_argument, default=[])
|
calibrate.add_argument(
|
||||||
|
'--role',
|
||||||
|
action='append',
|
||||||
|
type=_role_argument,
|
||||||
|
default=[],
|
||||||
|
metavar='NAME:FAMILY:SIZE',
|
||||||
|
help='Typography role to calibrate when spec_lock.md is absent, e.g. '
|
||||||
|
'body:"Microsoft YaHei":20; repeatable.',
|
||||||
|
)
|
||||||
calibrate.add_argument('--json', action='store_true')
|
calibrate.add_argument('--json', action='store_true')
|
||||||
for command in (measure, wrap, box):
|
for command in (measure, wrap, box):
|
||||||
command.add_argument('--json', action='store_true')
|
command.add_argument('--json', action='store_true')
|
||||||
|
|||||||
+1
-1
@@ -124,7 +124,7 @@ With an active template workspace, append exactly one line after the §I table
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
```
|
```
|
||||||
|
|
||||||
Preserve Title/Body characters and resolved stacks; omit a blank Typography upgrade and never place it in a stack. Each justified recurring family override adds its role to Font Plan plus `- **<Role> stack**: <complete ordered stack>` (roles: `Display`, `Annotation`, `Footer`, `Footnote`, `Data`, `Emphasis`, `Quote`, `Code` — only recurring, intentional differences; `Display` covers hero numerals and oversized titles that leave the Title family; a non-locked `Role rationale` only for an extra family); never collapse distinct Title/Body stacks or drop a declared role. Each Font Size Hierarchy value is a deck-wide role anchor; Executor's band and display exception are [`executor-base.md`](../references/executor-base.md) §2.1, so every recurring role is named here. Record every recurring palette role and size anchor the plan establishes, never one-off garnish. For confirmed custom directions add `Mode References`, `Mode Behavior`, `Visual Style References`, and `Visual Style Behavior` under Theme Style as applicable. `Stroke Width` under §VI only for a stroke library. `simple-icons` rows follow the brand-mark rule in the [icon README](../templates/icons/README.md). The §VI table records the synced SVG pool and, at `complete` depth, broad scenarios — never page placement; leave it empty when no bundled or brand icons are prepared. Other prepared SVGs under the project `icons/` remain usable without entering that selection. Illustrated icons are AI image resources: their sheet and placed slice rows belong in §VIII, and only placed slices project to `spec_lock.md images`.
|
Preserve Title/Body characters and resolved stacks; omit a blank Typography upgrade and never place it in a stack. Each justified recurring family override adds its role to Font Plan plus `- **<Role> stack**: <complete ordered stack>` (roles such as `Display`, `Annotation`, `Footer`, `Footnote`, `Data`, `Emphasis`, `Quote`, `Code`, or any descriptive recurring role the deck needs — a second monospace role like `Index` is valid — only recurring, intentional differences; `Display` covers hero numerals and oversized titles that leave the Title family; a non-locked `Role rationale` only for an extra family); never collapse distinct Title/Body stacks or drop a declared role. Each Font Size Hierarchy value is a deck-wide role anchor; Executor's band and display exception are [`executor-base.md`](../references/executor-base.md) §2.1, so every recurring role is named here. Record every recurring palette role and size anchor the plan establishes, never one-off garnish. For confirmed custom directions add `Mode References`, `Mode Behavior`, `Visual Style References`, and `Visual Style Behavior` under Theme Style as applicable. `Stroke Width` under §VI only for a stroke library. `simple-icons` rows follow the brand-mark rule in the [icon README](../templates/icons/README.md). The §VI table records the synced SVG pool and, at `complete` depth, broad scenarios — never page placement; leave it empty when no bundled or brand icons are prepared. Other prepared SVGs under the project `icons/` remain usable without entering that selection. Illustrated icons are AI image resources: their sheet and placed slice rows belong in §VIII, and only placed slices project to `spec_lock.md images`.
|
||||||
|
|
||||||
When §VIII contains any `Acquire Via: ai` row, add under §III:
|
When §VIII contains any `Acquire Via: ai` row, add under §III:
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ An AI skill that provides design intelligence for building professional UI/UX ac
|
|||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<i>Other projects</i><br>
|
<i>Other projects</i><br>
|
||||||
<a href="https://nextlevelbuilder.io">NextLevelBuilder.io</a> | <a href="https://goclaw.sh">GoClaw.sh</a> | <a href="https://claudekit.cc">ClaudeKit.cc</a> | <a href="https://tose.sh">TOSE.sh</a>
|
<a href="https://nextlevelbuilder.io">NextLevelBuilder.io</a> | <a href="https://goclaw.sh">GoClaw.sh</a> | <a href="https://agentkit.best">AgentKit.best</a> | <a href="https://tose.sh">TOSE.sh</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## What's New in v2.0
|
## What's New in v2.0
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
"sourceId": "ui-ux-pro-max",
|
"sourceId": "ui-ux-pro-max",
|
||||||
"repo": "https://github.com/nextlevelbuilder/ui-ux-pro-max-skill.git",
|
"repo": "https://github.com/nextlevelbuilder/ui-ux-pro-max-skill.git",
|
||||||
"ref": "main",
|
"ref": "main",
|
||||||
"commit": "58c220ff9d02be80523b06c03471925c52e8ab5d",
|
"commit": "91c193ac059b487d13ce535c7015b021eb71c841",
|
||||||
"adapter": "claude-skill",
|
"adapter": "claude-skill",
|
||||||
"sourcePath": ".claude/skills/ui-ux-pro-max",
|
"sourcePath": ".claude/skills/ui-ux-pro-max",
|
||||||
"syncedAt": "2026-09-02T16:00:01Z"
|
"syncedAt": "2026-09-03T09:20:38Z"
|
||||||
}
|
}
|
||||||
|
|||||||
+82
@@ -0,0 +1,82 @@
|
|||||||
|
"""Every script invocation in the shipped skill markdown resolves from the skill directory.
|
||||||
|
|
||||||
|
Regression test for #474. The sub-skills ship in two copies (.claude/skills/<skill>/
|
||||||
|
for the plugin, cli/assets/skills/<skill>/ for CLI installs) and land in layouts where
|
||||||
|
neither the project root nor ~/.claude/skills/ is a valid anchor: the plugin cache, a
|
||||||
|
project's .claude/skills/, ~/.claude/skills/ (--global), or a manual copy. The one anchor
|
||||||
|
that exists in all of them is the skill's own directory, so documented commands use
|
||||||
|
`scripts/<file>` for the skill's own scripts and `../<skill>/scripts/<file>` for a
|
||||||
|
sibling sub-skill (the sub-skills are always installed side by side).
|
||||||
|
|
||||||
|
This test extracts every `python|python3|node|bash <path>` invocation from every
|
||||||
|
markdown file under both trees and asserts that the path is skill-relative and names a
|
||||||
|
file that ships. The core skill's `${CLAUDE_PLUGIN_ROOT}/.claude/skills/...` form is
|
||||||
|
resolved against the repository root, which is what that variable denotes under a
|
||||||
|
plugin install - and accepted only in that file, because the sub-skills also ship
|
||||||
|
through the CLI, where the variable does not exist. The grep-based path contract in check-asset-sync.yml is the negative
|
||||||
|
side (no home-, project- or variable-rooted paths anywhere, code included); this is
|
||||||
|
the positive side (every documented invocation points at a real file).
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
import unittest
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
REPO = next(
|
||||||
|
parent for parent in Path(__file__).resolve().parents
|
||||||
|
if (parent / "scripts" / "generate-catalog-summary.py").is_file()
|
||||||
|
)
|
||||||
|
SKILL_TREES = ("cli/assets/skills", ".claude/skills")
|
||||||
|
# The only file that may use the plugin-root form: hand-authored for the plugin install
|
||||||
|
# and not shipped by the CLI (sync-assets.mjs mirrors data/ and scripts/, never SKILL.md).
|
||||||
|
# (Built from segments: the path contract in check-asset-sync.yml scans this file too.)
|
||||||
|
PLUGIN_ONLY_FILE = Path(".claude") / "skills" / "ui-ux-pro-max" / "SKILL.md"
|
||||||
|
INVOCATION = re.compile(r'(?<![\w/.-])(?:python3?|node|bash)\s+"?([^\s"`\']+\.(?:py|cjs|js|mjs|sh))')
|
||||||
|
PLUGIN_ROOT = "${CLAUDE_PLUGIN_ROOT}/"
|
||||||
|
|
||||||
|
|
||||||
|
def shipped_invocations():
|
||||||
|
for tree in SKILL_TREES:
|
||||||
|
for skill_dir in sorted((REPO / tree).iterdir()):
|
||||||
|
if not skill_dir.is_dir():
|
||||||
|
continue
|
||||||
|
for md in sorted(skill_dir.rglob("*.md")):
|
||||||
|
for lineno, line in enumerate(md.read_text(encoding="utf-8").splitlines(), 1):
|
||||||
|
for match in INVOCATION.finditer(line):
|
||||||
|
yield skill_dir, md, lineno, match.group(1)
|
||||||
|
|
||||||
|
|
||||||
|
def resolve(skill_dir, md, path):
|
||||||
|
"""Return (target, None) for a skill-relative path, or (None, reason)."""
|
||||||
|
if path.startswith(PLUGIN_ROOT):
|
||||||
|
if md.relative_to(REPO) != PLUGIN_ONLY_FILE:
|
||||||
|
return None, "the ${CLAUDE_PLUGIN_ROOT} form is only valid in the plugin-only core SKILL.md"
|
||||||
|
return REPO / path[len(PLUGIN_ROOT):], None
|
||||||
|
if path.startswith("scripts/"):
|
||||||
|
return skill_dir / path, None
|
||||||
|
if path.startswith("../"):
|
||||||
|
parts = path.split("/")
|
||||||
|
if len(parts) > 3 and parts[2] == "scripts" and (skill_dir.parent / parts[1]).is_dir():
|
||||||
|
return skill_dir.parent / parts[1] / "/".join(parts[2:]), None
|
||||||
|
return None, "a sibling invocation must be ../<skill>/scripts/<file> and the sibling must ship"
|
||||||
|
return None, "not skill-relative (expected scripts/<file> or ../<skill>/scripts/<file>)"
|
||||||
|
|
||||||
|
|
||||||
|
class SkillScriptPathsTest(unittest.TestCase):
|
||||||
|
def test_every_shipped_markdown_invocation_resolves_from_the_skill_directory(self):
|
||||||
|
problems, seen = [], 0
|
||||||
|
for skill_dir, md, lineno, path in shipped_invocations():
|
||||||
|
seen += 1
|
||||||
|
target, reason = resolve(skill_dir, md, path)
|
||||||
|
if reason is None and not target.is_file():
|
||||||
|
reason = f"no such file: {target}"
|
||||||
|
if reason:
|
||||||
|
problems.append(f"{md.relative_to(REPO)}:{lineno}: {path} -- {reason}")
|
||||||
|
# Guard against a silently broken extractor: the two trees carry well over
|
||||||
|
# a hundred documented invocations between them.
|
||||||
|
self.assertGreater(seen, 100, f"extractor found only {seen} invocations")
|
||||||
|
self.assertEqual(problems, [], "\n" + "\n".join(problems))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
"sourceId": "updating-gitea-repositories",
|
"sourceId": "updating-gitea-repositories",
|
||||||
"repo": "https://git.playones.com/huzhifa/skill-git-push.git",
|
"repo": "https://git.playones.com/huzhifa/skill-git-push.git",
|
||||||
"ref": "main",
|
"ref": "main",
|
||||||
"commit": "72c856975eaa340b023eb5393d958ca0bff1f59c",
|
"commit": "3a0b288dfa4df0657dc63c0fd424069432016595",
|
||||||
"adapter": "codex-plugin",
|
"adapter": "codex-plugin",
|
||||||
"sourcePath": ".",
|
"sourcePath": ".",
|
||||||
"syncedAt": "2026-09-02T10:37:18Z"
|
"syncedAt": "2026-09-03T09:20:38Z"
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -14,11 +14,14 @@ Publish only the intended changes to a Gitea repository through HTTPS, Git Crede
|
|||||||
1. Always read [repository workflow](references/repository-workflow.md).
|
1. Always read [repository workflow](references/repository-workflow.md).
|
||||||
2. On macOS, also read [macOS GCM setup](references/macos.md).
|
2. On macOS, also read [macOS GCM setup](references/macos.md).
|
||||||
3. On native Windows or WSL, also read [Windows GCM setup](references/windows.md).
|
3. On native Windows or WSL, also read [Windows GCM setup](references/windows.md).
|
||||||
|
4. On native Linux, including Linux controlled through a Windows remote desktop, also read [Linux GCM setup](references/linux.md).
|
||||||
|
|
||||||
## Core Contract
|
## Core Contract
|
||||||
|
|
||||||
- Require a clean Gitea HTTPS URL, exact prepared source paths, intended repository paths, target branch, and commit intent. Infer only what the active task makes unambiguous.
|
- Require a clean Gitea HTTPS URL, exact prepared source paths, intended repository paths, target branch, and commit intent. Infer only what the active task makes unambiguous.
|
||||||
- Verify GCM by executing its version command. When it succeeds, reuse that installation without install, reinstall, or upgrade actions. Install only when no working GCM exists; repair only when installation records exist but the executable does not.
|
- Verify GCM by executing its version command. When it succeeds, reuse that installation without install, reinstall, or upgrade actions. Install only when no working GCM exists; repair only when installation records exist but the executable does not.
|
||||||
|
- Select setup instructions from the operating system where the Git process runs. A Windows computer used only to control a remote Linux desktop does not make that Git session Windows or WSL.
|
||||||
|
- Treat web SSO/OIDC login and Git HTTPS authentication as separate unless the Gitea instance explicitly documents an integrated Git flow. The web login can be used to create a PAT; it does not by itself authorize a command-line push.
|
||||||
- The user creates a Gitea PAT with `write:repository`. The user enters the Gitea login and PAT only in a local GCM prompt. Never request or expose a PAT in chat, URLs, environment variables, command arguments, logs, or files.
|
- The user creates a Gitea PAT with `write:repository`. The user enters the Gitea login and PAT only in a local GCM prompt. Never request or expose a PAT in chat, URLs, environment variables, command arguments, logs, or files.
|
||||||
- Preserve unrelated work. Stage only exact task paths; never use unscoped `git add .` or `git add -A`.
|
- Preserve unrelated work. Stage only exact task paths; never use unscoped `git add .` or `git add -A`.
|
||||||
- Before committing, set the user-confirmed identity only in the target repository:
|
- Before committing, set the user-confirmed identity only in the target repository:
|
||||||
@@ -37,6 +40,8 @@ Publish only the intended changes to a Gitea repository through HTTPS, Git Crede
|
|||||||
|---|---|
|
|---|---|
|
||||||
| GCM version works | Reuse it unchanged |
|
| GCM version works | Reuse it unchanged |
|
||||||
| Installer record exists but command fails | Repair or reinstall GCM |
|
| Installer record exists but command fails | Repair or reinstall GCM |
|
||||||
|
| Git runs on a remotely controlled Linux host | Use the Linux instructions |
|
||||||
|
| Linux Secret Service has no graphical session | Use a repository-local GCM memory cache |
|
||||||
| HTTPS remote has no refs | Initialize the confirmed default branch |
|
| HTTPS remote has no refs | Initialize the confirmed default branch |
|
||||||
| Remote has history | Clone or fetch before writing |
|
| Remote has history | Clone or fetch before writing |
|
||||||
| Dirty changes overlap task paths | Stop or use a clean clone/worktree |
|
| Dirty changes overlap task paths | Stop or use a clean clone/worktree |
|
||||||
@@ -50,6 +55,8 @@ Publish only the intended changes to a Gitea repository through HTTPS, Git Crede
|
|||||||
|
|
||||||
- Trusting package-manager state instead of running the GCM version command.
|
- Trusting package-manager state instead of running the GCM version command.
|
||||||
- Treating a PAT as ordinary text.
|
- Treating a PAT as ordinary text.
|
||||||
|
- Assuming a successful browser SSO/OIDC login also authenticates Git HTTPS.
|
||||||
|
- Applying Windows or WSL setup to Git that actually runs on a remote Linux host.
|
||||||
- Staging the whole worktree for a narrow update.
|
- Staging the whole worktree for a narrow update.
|
||||||
- Treating push rejection as permission to force-push.
|
- Treating push rejection as permission to force-push.
|
||||||
- Reporting the local commit without remote SHA verification.
|
- Reporting the local commit without remote SHA verification.
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
interface:
|
interface:
|
||||||
display_name: "Updating Gitea Repositories"
|
display_name: "Updating Gitea Repositories"
|
||||||
short_description: "通过 HTTPS、GCM 和 PAT 安全更新 Gitea 仓库"
|
short_description: "通过 HTTPS、GCM 和 PAT 更新 Gitea 仓库"
|
||||||
default_prompt: "Use $updating-gitea-repositories to publish prepared changes to this Gitea HTTPS repository."
|
default_prompt: "Use $updating-gitea-repositories to publish prepared changes to this Gitea HTTPS repository from the current host."
|
||||||
|
|||||||
+102
@@ -0,0 +1,102 @@
|
|||||||
|
# Linux GCM Setup
|
||||||
|
|
||||||
|
Use this reference when Git runs on native Linux. This includes a Linux desktop controlled from Windows through RDP, VNC, or similar software. Use the Windows reference only when Git itself runs on Windows or WSL is intentionally using the Windows GCM executable.
|
||||||
|
|
||||||
|
## Identify the Session
|
||||||
|
|
||||||
|
Verify Git, GCM, the executable paths, and the configured helper:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uname -s
|
||||||
|
git --version
|
||||||
|
git-credential-manager --version
|
||||||
|
command -v git
|
||||||
|
command -v git-credential-manager
|
||||||
|
git config --show-origin --get-all credential.helper
|
||||||
|
```
|
||||||
|
|
||||||
|
If the GCM version command succeeds, reuse that installation. Do not install or upgrade it during an ordinary repository update.
|
||||||
|
|
||||||
|
A visible remote desktop does not guarantee that an agent or background shell inherited the desktop session. Check without printing unrelated environment values:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
test -n "${DISPLAY:-}" || test -n "${WAYLAND_DISPLAY:-}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Install When GCM Is Missing
|
||||||
|
|
||||||
|
Linux needs both GCM and an explicitly selected credential store. Use an official installation method appropriate for the distribution: the .NET global tool, a verified Debian package, or a verified release tarball. Run `git-credential-manager configure` afterward.
|
||||||
|
|
||||||
|
Do not download an unpinned executable from an unofficial source. Verify the release signature or checksum before installation. If the normal package needs administrator rights, ask the user to run the installation locally or use an official current-user method; never ask for an administrator password in chat.
|
||||||
|
|
||||||
|
On a Debian-based host without administrator access, a verified official `.deb` can be unpacked into the current user's directories. Inspect the package first and stop if its layout differs from `usr/local/share/gcm-core`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gcm_package="/absolute/path/to/verified-gcm.deb"
|
||||||
|
gcm_unpack_dir=$(mktemp -d)
|
||||||
|
gcm_install_dir="${XDG_DATA_HOME:-$HOME/.local/share}/gcm-core"
|
||||||
|
gcm_bin_dir="$HOME/.local/bin"
|
||||||
|
|
||||||
|
dpkg-deb -c "$gcm_package"
|
||||||
|
test ! -e "$gcm_install_dir"
|
||||||
|
test ! -e "$gcm_bin_dir/git-credential-manager"
|
||||||
|
test ! -L "$gcm_bin_dir/git-credential-manager"
|
||||||
|
dpkg-deb -x "$gcm_package" "$gcm_unpack_dir"
|
||||||
|
test -x "$gcm_unpack_dir/usr/local/share/gcm-core/git-credential-manager"
|
||||||
|
install -d "$(dirname "$gcm_install_dir")" "$gcm_bin_dir"
|
||||||
|
cp -a "$gcm_unpack_dir/usr/local/share/gcm-core" "$gcm_install_dir"
|
||||||
|
ln -s "$gcm_install_dir/git-credential-manager" "$gcm_bin_dir/git-credential-manager"
|
||||||
|
"$gcm_bin_dir/git-credential-manager" --version
|
||||||
|
"$gcm_bin_dir/git-credential-manager" configure
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the full executable path until `$HOME/.local/bin` is available on `PATH`. If an install directory or link already exists, inspect it and repair only the known broken installation; do not overwrite it blindly.
|
||||||
|
|
||||||
|
## Choose a Credential Store
|
||||||
|
|
||||||
|
For a graphical Linux session with a working Secret Service collection:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git config --global credential.credentialStore secretservice
|
||||||
|
git-credential-manager configure
|
||||||
|
```
|
||||||
|
|
||||||
|
Secret Service requires a graphical session to unlock its collection. If Git runs from an agent, background shell, or terminal without access to that graphical session, configure GCM's in-memory cache only in the target repository:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git config --local credential.credentialStore cache
|
||||||
|
git config --local credential.cacheOptions "--timeout 900"
|
||||||
|
```
|
||||||
|
|
||||||
|
This keeps the PAT in memory for 15 minutes and leaves GCM as the Git credential helper. Do not replace it with a plaintext credential store. Do not change a working global Secret Service configuration merely because one repository is being updated from a non-graphical shell.
|
||||||
|
|
||||||
|
For persistent use without a graphical session, GCM also supports the `gpg` store after `gpg`, `pass`, and a key pair have been set up. Do not initialize those tools or keys as a side effect of a repository update unless the user requests it.
|
||||||
|
|
||||||
|
## OIDC Web Login and Git Push
|
||||||
|
|
||||||
|
An organization may use DingTalk or another OIDC provider for the Gitea website. Treat that as the way to open the account settings and create a PAT. Unless the Gitea instance explicitly documents another Git flow, the HTTPS push still uses:
|
||||||
|
|
||||||
|
- Username: the Gitea login accepted by the instance.
|
||||||
|
- Password: a PAT with `write:repository`, entered only in the user's local terminal prompt.
|
||||||
|
|
||||||
|
Run the push from an interactive terminal:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd <prepared-repository>
|
||||||
|
git push -u origin <target-branch>
|
||||||
|
```
|
||||||
|
|
||||||
|
If the agent cannot expose an interactive prompt to the user, stop at this command and ask the user to run it. Resume with fetch and SHA verification after the user reports success. Never place the PAT in the remote URL, shell command, environment variable, chat, log, or repository file.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
If GCM reports that `secretservice` cannot be used without a graphical interface, first confirm where the setting came from:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git config --show-origin --get-all credential.credentialStore
|
||||||
|
git config --show-origin --get-all credential.helper
|
||||||
|
```
|
||||||
|
|
||||||
|
Then use the repository-local `cache` configuration above for this push, or rerun Git inside the real graphical session. Do not disable TLS verification. Install the organization's trusted CA correctly or stop and report the certificate issue.
|
||||||
|
|
||||||
|
Official references: [GCM installation](https://github.com/git-ecosystem/git-credential-manager/blob/main/docs/install.md), [credential stores](https://github.com/git-ecosystem/git-credential-manager/blob/main/docs/credstores.md), and [GCM configuration](https://github.com/git-ecosystem/git-credential-manager/blob/main/docs/configuration.md).
|
||||||
+7
-3
@@ -4,7 +4,7 @@ Read this reference for every Gitea repository update.
|
|||||||
|
|
||||||
## 1. Resolve Inputs
|
## 1. Resolve Inputs
|
||||||
|
|
||||||
Identify the clean Gitea HTTPS URL, prepared source paths, repository target paths, target branch, and commit intent. If a source-to-target mapping is ambiguous, stop and ask before writing.
|
Identify the clean Gitea HTTPS URL, prepared source paths, repository target paths, target branch, commit intent, and the operating system where Git actually runs. If a Windows machine only displays or controls a remote Linux desktop, use the Linux flow. If a source-to-target mapping is ambiguous, stop and ask before writing.
|
||||||
|
|
||||||
## 2. Inspect Before Editing
|
## 2. Inspect Before Editing
|
||||||
|
|
||||||
@@ -12,7 +12,9 @@ Read applicable `AGENTS.md` and `CONTRIBUTING*`. Inspect the repository root, cu
|
|||||||
|
|
||||||
Verify GCM using the active platform reference. A successful version command means reuse the existing installation without installing or upgrading it. Configure GCM only when its helper is absent or conflicting.
|
Verify GCM using the active platform reference. A successful version command means reuse the existing installation without installing or upgrading it. Configure GCM only when its helper is absent or conflicting.
|
||||||
|
|
||||||
The user creates a Gitea PAT with `write:repository` and enters the Gitea login plus PAT only in the local GCM prompt. The account must already have repository write access.
|
Web login and Git HTTPS authentication are separate concerns. For example, an organization may use DingTalk or another OIDC provider to sign in to the Gitea web interface, while Git HTTPS still expects a Gitea username and PAT. Do not assume that a browser login authorizes the command line unless the instance explicitly documents that behavior.
|
||||||
|
|
||||||
|
The user signs in to the Gitea web interface, creates a PAT with `write:repository`, and enters the Gitea login plus PAT only in the local GCM prompt. The account must already have repository write access. Never ask the user to paste a PAT into chat.
|
||||||
|
|
||||||
## 3. Choose the Repository Path
|
## 3. Choose the Repository Path
|
||||||
|
|
||||||
@@ -48,6 +50,8 @@ Confirm every staged path is in scope, deletions are intentional, no secret or t
|
|||||||
|
|
||||||
Commit with an intent-based message. Re-fetch before pushing when the remote may have advanced. Push normally to the target branch. If the default branch is protected, push a task branch and report that review or merge is required. Do not use `--force`, `--force-with-lease`, `--no-verify`, or TLS bypasses.
|
Commit with an intent-based message. Re-fetch before pushing when the remote may have advanced. Push normally to the target branch. If the default branch is protected, push a task branch and report that review or merge is required. Do not use `--force`, `--force-with-lease`, `--no-verify`, or TLS bypasses.
|
||||||
|
|
||||||
|
When an interactive prompt is required but the agent cannot share it safely, give the user the exact working directory and `git push` command. The user enters the username and PAT in their own terminal. Do not replace this handoff with credentials in a command, URL, environment variable, or file. After the user reports that the push finished, continue with the remote verification below.
|
||||||
|
|
||||||
After a successful push, fetch the pushed branch and compare:
|
After a successful push, fetch the pushed branch and compare:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -60,4 +64,4 @@ Report completion only when the local and remote SHAs match. Include the reposit
|
|||||||
|
|
||||||
## Stop Conditions
|
## Stop Conditions
|
||||||
|
|
||||||
Stop on ambiguous paths, missing Git identity, authentication or TLS failure, insufficient account/PAT permissions, unexpected staged files, validation failure, overlapping user changes, non-fast-forward history requiring judgment, protected-branch rejection, server-hook rejection, or a request to overwrite remote history.
|
Stop on ambiguous paths, missing Git identity, authentication or TLS failure, insufficient account/PAT permissions, unexpected staged files, validation failure, overlapping user changes, non-fast-forward history requiring judgment, protected-branch rejection, server-hook rejection, or a request to overwrite remote history. A required local credential prompt is a user handoff, not permission to weaken authentication or store the PAT insecurely.
|
||||||
|
|||||||
Reference in New Issue
Block a user