From 77b4d5a99d1da1ebca6d42bf0d14152f6dc846c2 Mon Sep 17 00:00:00 2001 From: TheDesignFounder Date: Fri, 25 Sep 2026 12:10:14 -0700 Subject: [PATCH] Publish the skills package the OpenAI portal uploads The plugin portal's Skills step takes a ZIP whose root holds a portable Agent Plugins manifest and a skills/ directory. The only skills ZIP we had was built on 2026-09-24, still pinned @dreamlayer/mcp@0.4.0-beta.3, carried the older .codex-plugin compatibility manifest, and lived in an ignored dist/ folder, so nothing kept it in step with the workflows. packaging/openai/build_skills_package.py builds it from plugins/dreamlayer/skills, the canonical source, and the build is byte-reproducible: entries sorted, timestamps fixed. scripts/validate.py now fails when the committed ZIP drifts from the skills, the same guard the host directories already have. The committed package is tracked rather than ignored so the portal can fetch exactly what this repository holds. Co-authored-by: Claude Opus 5 (1M context) --- packaging/openai/build_skills_package.py | 74 +++++++++++++++++++ packaging/openai/dreamlayer-skills-1.0.0.zip | Bin 0 -> 30805 bytes scripts/validate.py | 4 + 3 files changed, 78 insertions(+) create mode 100644 packaging/openai/build_skills_package.py create mode 100644 packaging/openai/dreamlayer-skills-1.0.0.zip diff --git a/packaging/openai/build_skills_package.py b/packaging/openai/build_skills_package.py new file mode 100644 index 0000000..57a1898 --- /dev/null +++ b/packaging/openai/build_skills_package.py @@ -0,0 +1,74 @@ +"""Build the skills-only package the OpenAI plugin portal uploads. + +The portal's Skills step takes a ZIP whose root holds a portable Agent Plugins +manifest and a skills/ directory. Everything inside comes from the canonical +source, so this package can never describe workflows we do not ship. The build +is byte-reproducible: entries are sorted and timestamps fixed, which lets +scripts/validate.py fail when the committed ZIP drifts from the skills. + +Usage: python3 packaging/openai/build_skills_package.py [--check] +""" +import io, json, sys, zipfile +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] +CANONICAL = ROOT / 'plugins/dreamlayer/skills' +PACKAGE = Path(__file__).resolve().parent / 'dreamlayer-skills-1.0.0.zip' +# Fixed so two builds of the same skills produce the same bytes. +TIMESTAMP = (2026, 1, 1, 0, 0, 0) +IGNORED = {'.DS_Store', '__pycache__'} +MANIFEST = { + '$schema': 'https://agent-plugins.org/schemas/1.0.0/plugin.schema.json', + 'name': 'dreamlayer', + 'version': '1.0.0', + 'description': ( + 'Generate and edit images, remove backgrounds, upscale, and build sprite-sheet ' + 'animations, with the credit cost quoted before each job.' + ), + 'author': {'name': 'Mackenzie Derival', 'email': 'Mackenzie@dreamlayer.io', 'url': 'https://dreamlayer.io'}, + 'homepage': 'https://dreamlayer.io/agent', + 'repository': 'https://github.com/TheDesignFounder/dreamlayer-agent-plugin', + 'license': 'MIT', + 'keywords': ['image-generation', 'image-editing', 'sprite-sheets', 'logo-concepts', 'product-images'], +} + + +def contents(): + """The exact file map the package carries, sorted for reproducibility.""" + files = {'plugin.json': (json.dumps(MANIFEST, indent=2) + '\n').encode()} + for path in sorted(CANONICAL.rglob('*')): + relative = path.relative_to(CANONICAL) + if path.is_file() and not IGNORED & set(relative.parts): + files[f'skills/{relative.as_posix()}'] = path.read_bytes() + return files + + +def build(): + buffer = io.BytesIO() + with zipfile.ZipFile(buffer, 'w', zipfile.ZIP_DEFLATED) as archive: + for name, data in sorted(contents().items()): + info = zipfile.ZipInfo(name, date_time=TIMESTAMP) + info.compress_type = zipfile.ZIP_DEFLATED + info.external_attr = 0o644 << 16 + archive.writestr(info, data) + return buffer.getvalue() + + +def main(argv): + built = build() + if '--check' in argv: + if not PACKAGE.exists(): + print(f'MISSING: {PACKAGE.relative_to(ROOT)}; run python3 packaging/openai/build_skills_package.py') + return 1 + if PACKAGE.read_bytes() != built: + print(f'DRIFT: {PACKAGE.relative_to(ROOT)} does not match the canonical skills; rebuild it') + return 1 + print(f'{PACKAGE.name} matches {len(contents()) - 1} canonical files') + return 0 + PACKAGE.write_bytes(built) + print(f'wrote {PACKAGE.relative_to(ROOT)} ({len(built)} bytes, {len(contents())} entries)') + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/packaging/openai/dreamlayer-skills-1.0.0.zip b/packaging/openai/dreamlayer-skills-1.0.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..59716f67f062b9a06852867c0e5c2e076f136cc9 GIT binary patch literal 30805 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