diff --git a/config/external-sources.lock.json b/config/external-sources.lock.json index 520abf66..377e7e92 100644 --- a/config/external-sources.lock.json +++ b/config/external-sources.lock.json @@ -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" } ] } diff --git a/plugins/codex/plugins/mcp-playwright/MCP_SOURCE.json b/plugins/codex/plugins/mcp-playwright/MCP_SOURCE.json index b6f70626..7dffed8f 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-07-31T16:01:47Z" + "syncedAt": "2026-08-01T16:01:45Z" } diff --git a/plugins/codex/plugins/next-skills/THIRD_PARTY_SOURCE.json b/plugins/codex/plugins/next-skills/THIRD_PARTY_SOURCE.json index 270b3f1b..adcb4be6 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": "7612eaeda1d70daa5abaef01aa255541f8dc3fb8", + "commit": "ccd47cfe53c7fef5e6b7ad472a3a020605a23608", "adapter": "skill-collection", "sourcePath": "skills", - "syncedAt": "2026-07-31T16:00:01Z" + "syncedAt": "2026-08-01T16:00:00Z" } diff --git a/plugins/codex/plugins/oh-my-codex/THIRD_PARTY_SOURCE.json b/plugins/codex/plugins/oh-my-codex/THIRD_PARTY_SOURCE.json index 47f98b5e..747ed5d6 100644 --- a/plugins/codex/plugins/oh-my-codex/THIRD_PARTY_SOURCE.json +++ b/plugins/codex/plugins/oh-my-codex/THIRD_PARTY_SOURCE.json @@ -2,8 +2,8 @@ "sourceId": "oh-my-codex", "repo": "https://github.com/Yeachan-Heo/oh-my-codex.git", "ref": "main", - "commit": "bf497e67604f788fe4e85f0f13ec086e50857c5d", + "commit": "a62d5bd77bef6d2bc7df467dcae68082b8616239", "adapter": "codex-plugin", "sourcePath": "plugins/oh-my-codex", - "syncedAt": "2026-07-31T16:00:01Z" + "syncedAt": "2026-08-01T16:00:00Z" } diff --git a/plugins/codex/plugins/ppt-master/THIRD_PARTY_SOURCE.json b/plugins/codex/plugins/ppt-master/THIRD_PARTY_SOURCE.json index 1e1a511b..46c21687 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": "6b42a6a652f9d6e9fc0c81e634c9fdfe771eee10", + "commit": "8858c4960b870f12baf952994fbd0c76ab5ba4ec", "adapter": "claude-skill", "sourcePath": "skills/ppt-master", - "syncedAt": "2026-07-31T16:00:01Z" + "syncedAt": "2026-08-01T16:00:00Z" } diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/LICENSE b/plugins/codex/plugins/ppt-master/skills/ppt-master/LICENSE new file mode 100644 index 00000000..9c261c3d --- /dev/null +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/LICENSE @@ -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. diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/SKILL.md b/plugins/codex/plugins/ppt-master/skills/ppt-master/SKILL.md index 475eda60..f20ebc6c 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/SKILL.md +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/SKILL.md @@ -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 | |---|---| diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/attribution_guard.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/attribution_guard.py new file mode 100644 index 00000000..d43cb2be --- /dev/null +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/attribution_guard.py @@ -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()) diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/console_encoding.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/console_encoding.py index 0d2dd9bf..6d3a1862 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/console_encoding.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/console_encoding.py @@ -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) diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/native_enhance_pptx.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/native_enhance_pptx.py index 42a2e23f..0a87bb16 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/native_enhance_pptx.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/native_enhance_pptx.py @@ -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()) diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/native_enhance_pptx_core.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/native_enhance_pptx_core.py index dfe3753f..378f470b 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/native_enhance_pptx_core.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/native_enhance_pptx_core.py @@ -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: diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/project_management/cli.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/project_management/cli.py index b34b1b1e..2ff337c7 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/project_management/cli.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/project_management/cli.py @@ -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() diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/project_manager.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/project_manager.py index 957a698a..d307f095 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/project_manager.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/project_manager.py @@ -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()) diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/prompt_audit_manifest.json b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/prompt_audit_manifest.json index 21c9bfa4..c67fed07 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/prompt_audit_manifest.json +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/prompt_audit_manifest.json @@ -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.", diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/register_template.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/register_template.py index a270b1cf..a3f726ac 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/register_template.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/register_template.py @@ -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." ) diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_quality/cli.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_quality/cli.py index b3819dff..18ec329a 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_quality/cli.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_quality/cli.py @@ -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) diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_quality_checker.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_quality_checker.py index 319219dd..60133912 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_quality_checker.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_quality_checker.py @@ -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() diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_to_pptx.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_to_pptx.py index 4f091d7b..4240b639 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_to_pptx.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_to_pptx.py @@ -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()) diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_to_pptx/pptx_package/cli.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_to_pptx/pptx_package/cli.py index 9d34b037..b17ec473 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_to_pptx/pptx_package/cli.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/svg_to_pptx/pptx_package/cli.py @@ -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, diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/template_fill_pptx.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/template_fill_pptx.py index 8dff9987..80baef83 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/template_fill_pptx.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/template_fill_pptx.py @@ -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()) diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/template_fill_pptx/cli.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/template_fill_pptx/cli.py index a04aa0e2..53b5ce85 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/template_fill_pptx/cli.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/template_fill_pptx/cli.py @@ -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: diff --git a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/template_preview_pptx.py b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/template_preview_pptx.py index 90be017c..693ac02e 100644 --- a/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/template_preview_pptx.py +++ b/plugins/codex/plugins/ppt-master/skills/ppt-master/scripts/template_preview_pptx.py @@ -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) 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 58209e64..3f717eb5 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": "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" }