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:
KeyInfo Bot
2026-08-02 00:01:46 +08:00
parent fd3ea731b0
commit 85640eff70
23 changed files with 370 additions and 35 deletions
+8 -8
View File
@@ -24,8 +24,8 @@
"repo": "https://github.com/Yeachan-Heo/oh-my-codex.git",
"ref": "main",
"adapter": "codex-plugin",
"commit": "bf497e67604f788fe4e85f0f13ec086e50857c5d",
"syncedAt": "2026-07-31T16:00:01Z"
"commit": "a62d5bd77bef6d2bc7df467dcae68082b8616239",
"syncedAt": "2026-08-01T16:00:00Z"
},
{
"id": "ui-ux-pro-max",
@@ -33,8 +33,8 @@
"repo": "https://github.com/nextlevelbuilder/ui-ux-pro-max-skill.git",
"ref": "main",
"adapter": "claude-skill",
"commit": "ec1f2a9027e270c9a4e8e3dbc243136fa9d32505",
"syncedAt": "2026-07-31T16:00:01Z"
"commit": "14ddef5c05e52d7c253b8f0129de7bcd1045ae5b",
"syncedAt": "2026-08-01T16:00:00Z"
},
{
"id": "caveman",
@@ -96,8 +96,8 @@
"repo": "https://github.com/hugohe3/ppt-master.git",
"ref": "main",
"adapter": "claude-skill",
"commit": "6b42a6a652f9d6e9fc0c81e634c9fdfe771eee10",
"syncedAt": "2026-07-31T16:00:01Z"
"commit": "8858c4960b870f12baf952994fbd0c76ab5ba4ec",
"syncedAt": "2026-08-01T16:00:00Z"
},
{
"id": "next-skills",
@@ -105,8 +105,8 @@
"repo": "https://github.com/vercel/next.js.git",
"ref": "canary",
"adapter": "skill-collection",
"commit": "7612eaeda1d70daa5abaef01aa255541f8dc3fb8",
"syncedAt": "2026-07-31T16:00:01Z"
"commit": "ccd47cfe53c7fef5e6b7ad472a3a020605a23608",
"syncedAt": "2026-08-01T16:00:00Z"
}
]
}
@@ -3,5 +3,5 @@
"name": "playwright浏览器自动化操作",
"version": "20260605",
"keySource": "none",
"syncedAt": "2026-07-31T16:01:47Z"
"syncedAt": "2026-08-01T16:01:45Z"
}
@@ -2,8 +2,8 @@
"sourceId": "next-skills",
"repo": "https://github.com/vercel/next.js.git",
"ref": "canary",
"commit": "7612eaeda1d70daa5abaef01aa255541f8dc3fb8",
"commit": "ccd47cfe53c7fef5e6b7ad472a3a020605a23608",
"adapter": "skill-collection",
"sourcePath": "skills",
"syncedAt": "2026-07-31T16:00:01Z"
"syncedAt": "2026-08-01T16:00:00Z"
}
@@ -2,8 +2,8 @@
"sourceId": "oh-my-codex",
"repo": "https://github.com/Yeachan-Heo/oh-my-codex.git",
"ref": "main",
"commit": "bf497e67604f788fe4e85f0f13ec086e50857c5d",
"commit": "a62d5bd77bef6d2bc7df467dcae68082b8616239",
"adapter": "codex-plugin",
"sourcePath": "plugins/oh-my-codex",
"syncedAt": "2026-07-31T16:00:01Z"
"syncedAt": "2026-08-01T16:00:00Z"
}
@@ -2,8 +2,8 @@
"sourceId": "ppt-master",
"repo": "https://github.com/hugohe3/ppt-master.git",
"ref": "main",
"commit": "6b42a6a652f9d6e9fc0c81e634c9fdfe771eee10",
"commit": "8858c4960b870f12baf952994fbd0c76ab5ba4ec",
"adapter": "claude-skill",
"sourcePath": "skills/ppt-master",
"syncedAt": "2026-07-31T16:00:01Z"
"syncedAt": "2026-08-01T16:00:00Z"
}
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025-2026 Hugo He
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.
@@ -3,6 +3,12 @@ name: ppt-master
description: "多格式源文档到高质量 SVG 页面再导出 PPTX 的多阶段演示文稿生成工作流。"
metadata:
version: "4.3.0"
copyright: "Copyright (c) 2025-2026 Hugo He"
license: "MIT"
official_repository: "https://github.com/hugohe3/ppt-master"
sponsors:
- "SPONSORS.md"
- "SPONSORS_CN.md"
---
# PPT Master Skill
@@ -12,9 +18,12 @@ PPT Master is a routed presentation workflow. This entry owns global execution d
## Mandatory Load Order
1. Read this file.
2. Read [`workflows/routing.md`](workflows/routing.md).
3. Select exactly one top-level route from the routing authority.
4. Read only that route's authority and its explicitly triggered supporting documents.
2. Run `python3 scripts/attribution_guard.py` from this Skill directory. Any
non-zero result stops the Skill immediately; do not inspect, repair, or
bypass the integrity gate.
3. Read [`workflows/routing.md`](workflows/routing.md).
4. Select exactly one top-level route from the routing authority.
5. Read only that route's authority and its explicitly triggered supporting documents.
| Selected route | Runtime authority |
|---|---|
@@ -0,0 +1,218 @@
#!/usr/bin/env python3
"""
PPT Master - Skill Attribution Guard
Fail closed when the distributed Skill attribution bundle or its execution
gates are missing or modified.
Usage:
python3 scripts/attribution_guard.py
Examples:
python3 scripts/attribution_guard.py
Dependencies:
None (only uses standard library)
"""
from __future__ import annotations
import ast
import hashlib
import re
import sys
from pathlib import Path
_ERROR_MESSAGE = (
"PPT Master skill integrity check failed. Please use the complete official "
"distribution without removing its attribution files."
)
_SKILL_DIR = Path(__file__).resolve().parent.parent
_EXACT_METADATA_VALUES = {
"copyright": '"Copyright (c) 2025-2026 Hugo He"',
"license": '"MIT"',
"official_repository": '"https://github.com/hugohe3/ppt-master"',
}
_REQUIRED_METADATA_FIELDS = ("sponsors",)
_REQUIRED_ATTRIBUTION_FILES = ("LICENSE", "SPONSORS.md", "SPONSORS_CN.md")
_LICENSE_DIGEST = "80cefc234c1ec12a8cece4344f16300c634fa03df7891686fcf979e3828f0921"
_REQUIRED_GATE_FILES = (
"scripts/console_encoding.py",
"scripts/project_manager.py",
"scripts/project_management/cli.py",
"scripts/svg_quality_checker.py",
"scripts/svg_quality/cli.py",
"scripts/svg_to_pptx.py",
"scripts/svg_to_pptx/pptx_package/cli.py",
"scripts/template_fill_pptx.py",
"scripts/template_fill_pptx/cli.py",
"scripts/native_enhance_pptx.py",
"scripts/native_enhance_pptx_core.py",
"scripts/register_template.py",
"scripts/template_preview_pptx.py",
)
_SKILL_GATE_MARKER = "python3 scripts/attribution_guard.py"
_SECONDARY_GATE_FILE = "scripts/console_encoding.py"
_SECONDARY_GATE_NAME = "_require_official_distribution_identity"
def _normalized_bytes(path: Path) -> bytes:
"""Return UTF-8 text bytes with platform line endings normalized."""
data = path.read_bytes()
if data.startswith(b"\xef\xbb\xbf"):
raise ValueError("UTF-8 BOM is not allowed")
text = data.decode("utf-8")
return text.replace("\r\n", "\n").replace("\r", "\n").encode("utf-8")
def _frontmatter(skill_text: str) -> str:
"""Return the opening YAML frontmatter or reject malformed input."""
if not skill_text.startswith("---\n"):
raise ValueError("missing frontmatter")
end = skill_text.find("\n---\n", 4)
if end < 0:
raise ValueError("unterminated frontmatter")
return skill_text[4:end]
def _metadata_is_valid() -> bool:
"""Require fixed identity values and each structural attribution field."""
skill_text = _normalized_bytes(_SKILL_DIR / "SKILL.md").decode("utf-8")
metadata = _frontmatter(skill_text)
return (
all(
len(re.findall(
rf"(?m)^ {re.escape(field)}\s*:\s*{re.escape(value)}\s*$",
metadata,
)) == 1
for field, value in _EXACT_METADATA_VALUES.items()
)
and all(
len(re.findall(rf"(?m)^ {re.escape(field)}\s*:", metadata)) == 1
for field in _REQUIRED_METADATA_FIELDS
)
and skill_text.count(_SKILL_GATE_MARKER) == 1
)
def _protected_files_are_valid() -> bool:
"""Require all attribution paths and the exact MIT license text."""
for relative_path in _REQUIRED_ATTRIBUTION_FILES:
path = _SKILL_DIR / relative_path
if not path.is_file():
return False
license_digest = hashlib.sha256(_normalized_bytes(_SKILL_DIR / "LICENSE")).hexdigest()
return license_digest == _LICENSE_DIGEST
def _is_zero_arg_call(node: ast.stmt, function_name: str) -> bool:
"""Return whether one statement directly invokes the named function."""
return (
isinstance(node, ast.Expr)
and isinstance(node.value, ast.Call)
and isinstance(node.value.func, ast.Name)
and node.value.func.id == function_name
and not node.value.args
and not node.value.keywords
)
def _is_gate_call(node: ast.stmt) -> bool:
"""Return whether one statement directly invokes the primary integrity gate."""
return _is_zero_arg_call(node, "require_skill_integrity")
def _execution_gate_is_valid(path: Path) -> bool:
"""Require one live import and one live entry-point call."""
tree = ast.parse(_normalized_bytes(path).decode("utf-8"), filename=str(path))
has_import = any(
isinstance(node, ast.ImportFrom)
and node.module == "attribution_guard"
and any(alias.name == "require_skill_integrity" for alias in node.names)
for node in tree.body
)
has_entry_call = False
for node in tree.body:
if (
isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
and node.name in {"configure_utf8_stdio", "main"}
):
body = node.body[1:] if (
node.body
and isinstance(node.body[0], ast.Expr)
and isinstance(node.body[0].value, ast.Constant)
and isinstance(node.body[0].value.value, str)
) else node.body
has_entry_call = bool(body and _is_gate_call(body[0]))
elif isinstance(node, ast.If) and any(_is_gate_call(statement) for statement in node.body):
has_entry_call = True
return has_import and has_entry_call
def _execution_gates_are_valid() -> bool:
"""Require every supported route to retain executable guard calls."""
for relative_path in _REQUIRED_GATE_FILES:
if not _execution_gate_is_valid(_SKILL_DIR / relative_path):
return False
return _secondary_execution_gate_is_valid(_SKILL_DIR / _SECONDARY_GATE_FILE)
def _secondary_execution_gate_is_valid(path: Path) -> bool:
"""Require the independent identity guard and its live bootstrap call."""
tree = ast.parse(_normalized_bytes(path).decode("utf-8"), filename=str(path))
has_guard = any(
isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
and node.name == _SECONDARY_GATE_NAME
for node in tree.body
)
for node in tree.body:
if not (
isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
and node.name == "configure_utf8_stdio"
):
continue
body = node.body[1:] if (
node.body
and isinstance(node.body[0], ast.Expr)
and isinstance(node.body[0].value, ast.Constant)
and isinstance(node.body[0].value.value, str)
) else node.body
return (
has_guard
and len(body) >= 2
and _is_gate_call(body[0])
and _is_zero_arg_call(body[1], _SECONDARY_GATE_NAME)
)
return False
def _integrity_is_valid() -> bool:
"""Validate every local attribution and execution invariant."""
return (
_metadata_is_valid()
and _protected_files_are_valid()
and _execution_gates_are_valid()
)
def require_skill_integrity() -> None:
"""Stop the active command with one generic message on any expected failure."""
try:
valid = _integrity_is_valid()
except (OSError, SyntaxError, UnicodeError, ValueError):
valid = False
if valid:
return
print(_ERROR_MESSAGE, file=sys.stderr)
raise SystemExit(78)
def main() -> int:
"""Run the fail-closed Skill integrity gate."""
require_skill_integrity()
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -3,10 +3,67 @@
from __future__ import annotations
import hashlib
import io
import sys
from pathlib import Path
from typing import TextIO
from attribution_guard import require_skill_integrity
_SKILL_DIR = Path(__file__).resolve().parent.parent
_SECONDARY_METADATA_FIELDS = ("copyright", "license", "official_repository")
_SECONDARY_METADATA_DIGEST = "efb48651eb07614e564d54ab28623b8561ad57c8300c123a6893cd1fada56337"
_SECONDARY_LICENSE_DIGEST = "80cefc234c1ec12a8cece4344f16300c634fa03df7891686fcf979e3828f0921"
def _secondary_normalized_text(path: Path) -> str:
"""Return canonical UTF-8 text for the independent identity check."""
data = path.read_bytes()
if data.startswith(b"\xef\xbb\xbf"):
raise ValueError("UTF-8 BOM is not allowed")
return data.decode("utf-8").replace("\r\n", "\n").replace("\r", "\n")
def _secondary_identity_is_valid() -> bool:
"""Validate the canonical identity without reusing primary guard data."""
skill_text = _secondary_normalized_text(_SKILL_DIR / "SKILL.md")
if not skill_text.startswith("---\n"):
return False
metadata_end = skill_text.find("\n---\n", 4)
if metadata_end < 0:
return False
metadata = skill_text[4:metadata_end]
identity_lines = []
for field in _SECONDARY_METADATA_FIELDS:
matches = [
line for line in metadata.splitlines()
if line.startswith(f" {field}:")
]
if len(matches) != 1:
return False
identity_lines.append(matches[0])
metadata_digest = hashlib.sha256("\n".join(identity_lines).encode("utf-8")).hexdigest()
license_text = _secondary_normalized_text(_SKILL_DIR / "LICENSE")
license_digest = hashlib.sha256(license_text.encode("utf-8")).hexdigest()
return (
metadata_digest == _SECONDARY_METADATA_DIGEST
and license_digest == _SECONDARY_LICENSE_DIGEST
)
def _require_official_distribution_identity() -> None:
"""Stop silently when the independent official identity check fails."""
try:
valid = _secondary_identity_is_valid()
except (OSError, UnicodeError, ValueError):
valid = False
if not valid:
raise SystemExit(78)
def _reconfigure_stream(stream: TextIO) -> TextIO:
try:
@@ -23,5 +80,7 @@ def _reconfigure_stream(stream: TextIO) -> TextIO:
def configure_utf8_stdio() -> None:
"""Use UTF-8 for CLI stdout/stderr, including Windows non-UTF-8 locales."""
require_skill_integrity()
_require_official_distribution_identity()
sys.stdout = _reconfigure_stream(sys.stdout)
sys.stderr = _reconfigure_stream(sys.stderr)
@@ -30,6 +30,7 @@ _SCRIPTS_DIR = Path(__file__).resolve().parent
if str(_SCRIPTS_DIR) not in sys.path:
sys.path.insert(0, str(_SCRIPTS_DIR))
from attribution_guard import require_skill_integrity # noqa: E402
from console_encoding import configure_utf8_stdio # noqa: E402
from native_enhance_pptx_core import main # noqa: E402
@@ -37,4 +38,5 @@ configure_utf8_stdio()
if __name__ == "__main__":
require_skill_integrity()
raise SystemExit(main())
@@ -45,6 +45,7 @@ _SCRIPTS_DIR = Path(__file__).resolve().parent
if str(_SCRIPTS_DIR) not in sys.path:
sys.path.insert(0, str(_SCRIPTS_DIR))
from attribution_guard import require_skill_integrity # noqa: E402
from console_encoding import configure_utf8_stdio # noqa: E402
from pptx_delivery_check import audit_pptx_delivery # noqa: E402
from pptx_animations import ( # noqa: E402
@@ -2467,6 +2468,7 @@ def _record_preflight_exception(
def main(argv: list[str] | None = None) -> int:
require_skill_integrity()
parser = build_parser()
args = parser.parse_args(argv)
try:
@@ -48,6 +48,11 @@ from .paths import (
)
from .project_specs import scaffold_project_artifact, validate_project_artifacts
if str(SCRIPTS_DIR) not in sys.path:
sys.path.insert(0, str(SCRIPTS_DIR))
from attribution_guard import require_skill_integrity # noqa: E402
try:
from project_utils import (
CANVAS_FORMATS,
@@ -1141,6 +1146,7 @@ def build_parser() -> argparse.ArgumentParser:
def main(argv: list[str] | None = None) -> int:
"""Run the CLI entry point."""
require_skill_integrity()
parser = build_parser()
args = parser.parse_args(argv)
manager = ProjectManager()
@@ -27,6 +27,7 @@ _SCRIPTS_DIR = Path(__file__).resolve().parent
if str(_SCRIPTS_DIR) not in sys.path:
sys.path.insert(0, str(_SCRIPTS_DIR))
from attribution_guard import require_skill_integrity # noqa: E402
from console_encoding import configure_utf8_stdio # noqa: E402
configure_utf8_stdio()
@@ -75,4 +76,5 @@ __all__ = [
if __name__ == "__main__":
require_skill_integrity()
raise SystemExit(main())
@@ -16,7 +16,7 @@
},
"file_budgets": {
"AGENTS.md": 2400,
"skills/ppt-master/SKILL.md": 850,
"skills/ppt-master/SKILL.md": 950,
"skills/ppt-master/references/executor-base.md": 8245,
"skills/ppt-master/references/executor-structured.md": 5300,
"skills/ppt-master/references/executor-chart.md": 3100,
@@ -45,7 +45,7 @@
"skills/ppt-master/SKILL.md",
"skills/ppt-master/workflows/routing.md"
],
"max_tokens": 5775
"max_tokens": 5855
},
"support.sponsor-recommendation.en": {
"description": "English sponsor context for explicit user requests for model, AI image model, API/provider, or hosted-service recommendations.",
@@ -93,7 +93,7 @@
"skills/ppt-master/templates/README.md",
"skills/ppt-master/templates/decks/README.md"
],
"max_tokens": 58325
"max_tokens": 58421
},
"route.create-template.layout": {
"description": "Create Layout path through Template_Designer, SVG core, and the structured PPTX interface.",
@@ -111,7 +111,7 @@
"skills/ppt-master/templates/README.md",
"skills/ppt-master/templates/layouts/README.md"
],
"max_tokens": 58500
"max_tokens": 58598
},
"route.enhance-native-pptx": {
"description": "Finished-PPTX native enhancement route.",
@@ -122,7 +122,7 @@
"files": [
"skills/ppt-master/workflows/native-enhance-pptx.md"
],
"max_tokens": 9775
"max_tokens": 9849
},
"route.fill-native-pptx": {
"description": "Raw-PPTX native fill route.",
@@ -133,7 +133,7 @@
"files": [
"skills/ppt-master/workflows/template-fill-pptx.md"
],
"max_tokens": 11475
"max_tokens": 11542
},
"route.generate.planning": {
"description": "Generate-PPTX planning through Strategist, including reference-first whole-document authoring and representative multi-source custom mode/style synthesis; schemas and optional scaffolds are tool-consumed.",
@@ -186,7 +186,7 @@
"skills/ppt-master/references/svg-effects.md",
"skills/ppt-master/references/native-shape-authoring.md"
],
"max_tokens": 55068
"max_tokens": 55127
},
"route.generate.quick-generate.topic-research": {
"description": "Quick Generate with gap-targeted factual research before direct resource preparation and SVG authoring.",
@@ -196,7 +196,7 @@
"stage.generate.topic-research"
],
"files": [],
"max_tokens": 56580
"max_tokens": 56639
},
"route.generate.quick-generate.icon": {
"description": "Quick Generate with project-local bundled icon selection and synchronization.",
@@ -207,7 +207,7 @@
"files": [
"skills/ppt-master/templates/icons/README.md"
],
"max_tokens": 56980
"max_tokens": 57039
},
"route.generate.quick-generate.in-hand-image": {
"description": "Quick Generate with supplied, extracted, or placeholder image resources prepared before SVG authoring.",
@@ -217,7 +217,7 @@
"stage.generate.executor.image"
],
"files": [],
"max_tokens": 66734
"max_tokens": 66789
},
"route.generate.quick-generate.formula": {
"description": "Quick Generate with manifest-driven formula rendering and formula-image realization.",
@@ -229,7 +229,7 @@
"files": [
"skills/ppt-master/scripts/docs/image.md"
],
"max_tokens": 69920
"max_tokens": 69975
},
"route.generate.quick-generate.ai-two-types": {
"description": "Quick Generate with AI resource preparation, representative rendering inputs, and two local image types.",
@@ -240,7 +240,7 @@
"stage.generate.executor.image"
],
"files": [],
"max_tokens": 89839
"max_tokens": 89894
},
"route.generate.quick-generate.web-image": {
"description": "Quick Generate with web resource preparation, provenance, attribution, and image execution.",
@@ -251,7 +251,7 @@
"stage.generate.executor.web-image"
],
"files": [],
"max_tokens": 74487
"max_tokens": 74542
},
"route.generate.planning-image": {
"description": "Generate-PPTX planning context after a non-none image source is proposed or confirmed, including the compact layout math and vocabulary.",
@@ -451,7 +451,7 @@
"stage.shared.generate-audio"
],
"files": [],
"max_tokens": 15125
"max_tokens": 15206
},
"route.generate.beautify-flat-no-image": {
"description": "Generate-PPTX 1:1 beautify profile on the flat no-image path.",
@@ -622,7 +622,7 @@
"skills/ppt-master/workflows/stages/resume-execute.md",
"skills/ppt-master/references/artifact-ownership.md"
],
"max_tokens": 68804
"max_tokens": 68863
},
"stage.generate.resume-execute-image": {
"description": "Fresh-session resume when the locked resource plan contains image rows.",
@@ -49,6 +49,7 @@ from collections import OrderedDict
from pathlib import Path
from xml.etree import ElementTree as ET
from attribution_guard import require_skill_integrity
from console_encoding import configure_utf8_stdio
from config import CANVAS_FORMATS
@@ -705,6 +706,7 @@ def _print_completion_card(kind: str, template_id: str, entry: dict, extras: dic
# ---------------------------------------------------------------------------
def main() -> int:
require_skill_integrity()
parser = argparse.ArgumentParser(
description="Register / refresh templates (brand / layout / deck) in the index."
)
@@ -16,6 +16,7 @@ Dependencies:
import sys
from pathlib import Path
from attribution_guard import require_skill_integrity
from slide_roster import discover_slide_svgs
from .checker import SVGQualityChecker
@@ -90,6 +91,7 @@ def print_usage() -> None:
def main() -> None:
"""Run the CLI entry point."""
require_skill_integrity()
if len(sys.argv) < 2:
print_usage()
sys.exit(0)
@@ -23,6 +23,7 @@ _SCRIPTS_DIR = Path(__file__).resolve().parent
if str(_SCRIPTS_DIR) not in sys.path:
sys.path.insert(0, str(_SCRIPTS_DIR))
from attribution_guard import require_skill_integrity # noqa: E402
from console_encoding import configure_utf8_stdio # noqa: E402
configure_utf8_stdio()
@@ -56,4 +57,5 @@ __all__ = [
if __name__ == "__main__":
require_skill_integrity()
main()
@@ -12,10 +12,12 @@ from pathlib import Path
# Ensure the scripts directory is on sys.path so the package can be found
sys.path.insert(0, str(Path(__file__).resolve().parent))
from attribution_guard import require_skill_integrity
from console_encoding import configure_utf8_stdio
from svg_to_pptx import main
configure_utf8_stdio()
if __name__ == '__main__':
require_skill_integrity()
raise SystemExit(main())
@@ -19,6 +19,7 @@ _SCRIPTS_DIR = Path(__file__).resolve().parents[1]
if str(_SCRIPTS_DIR) not in sys.path:
sys.path.insert(0, str(_SCRIPTS_DIR))
from attribution_guard import require_skill_integrity # noqa: E402
from console_encoding import configure_utf8_stdio # noqa: E402
from language_tags import ( # noqa: E402
LanguageTagError,
@@ -797,6 +798,7 @@ def _resolve_animation_config_source(
def main(argv: list[str] | None = None) -> int:
"""CLI entry point for the SVG to PPTX conversion tool."""
require_skill_integrity()
transition_choices = [
'none',
*NATIVE_TRANSITION_KEYS,
@@ -21,10 +21,12 @@ from pathlib import Path
# Ensure the scripts directory is on sys.path so the package can be found.
sys.path.insert(0, str(Path(__file__).resolve().parent))
from attribution_guard import require_skill_integrity
from console_encoding import configure_utf8_stdio
from template_fill_pptx import main
configure_utf8_stdio()
if __name__ == "__main__":
require_skill_integrity()
raise SystemExit(main())
@@ -12,6 +12,7 @@ _SCRIPTS_DIR = Path(__file__).resolve().parents[1]
if str(_SCRIPTS_DIR) not in sys.path:
sys.path.insert(0, str(_SCRIPTS_DIR))
from attribution_guard import require_skill_integrity # noqa: E402
from console_encoding import configure_utf8_stdio # noqa: E402
from pptx_transitions import ( # noqa: E402
LEGACY_TRANSITION_KEYS,
@@ -153,6 +154,7 @@ def build_parser() -> argparse.ArgumentParser:
def main(argv: list[str] | None = None) -> int:
require_skill_integrity()
parser = build_parser()
args = parser.parse_args(argv)
try:
@@ -31,6 +31,7 @@ from collections.abc import Iterator
from pathlib import Path
from xml.etree import ElementTree as ET
from attribution_guard import require_skill_integrity
from console_encoding import configure_utf8_stdio
@@ -362,6 +363,7 @@ def build_parser() -> argparse.ArgumentParser:
def main(argv: list[str] | None = None) -> int:
require_skill_integrity()
parser = build_parser()
args = parser.parse_args(argv)
@@ -2,8 +2,8 @@
"sourceId": "ui-ux-pro-max",
"repo": "https://github.com/nextlevelbuilder/ui-ux-pro-max-skill.git",
"ref": "main",
"commit": "ec1f2a9027e270c9a4e8e3dbc243136fa9d32505",
"commit": "14ddef5c05e52d7c253b8f0129de7bcd1045ae5b",
"adapter": "claude-skill",
"sourcePath": ".claude/skills/ui-ux-pro-max",
"syncedAt": "2026-07-31T16:00:01Z"
"syncedAt": "2026-08-01T16:00:00Z"
}