test_sync_brand_to_tokens.py drives sync-brand-to-tokens.cjs through
subprocess.run with text=True but no explicit encoding, so Python decodes the
pipe with the locale codec. Three of the script's messages carry emoji whose
UTF-8 bytes land on cp1252's undefined slots: 0x8F in the "no base hex found"
warning (sync-brand-to-tokens.cjs:132), 0x9D in the "brand guidelines not found"
error (:198), and 0x8F in the dry-run notice (:223). Decoding then raises inside
subprocess's reader thread, the stream comes back as None, and any assertion
against it fails with `TypeError: argument of type 'NoneType' is not a
container` -- which hides the real result behind an unrelated error.
The existing test passes today only because the bundled starter fixture happens
to take none of those three paths.
Pin the pipe to UTF-8, extracted into a shared _run helper to match the idiom in
design-system's test module, and add a regression test for the missing-guidelines
path -- the default state of any project that has not run the brand skill yet.
That test fails without the encoding fix (stderr is None) and passes with it.
Follow-up to #460
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
cli/assets had fallen out of sync with src/ui-ux-pro-max ahead of this
change (unrelated to the motion-domain feature) - colors.csv, products.csv,
google-fonts.csv, draft.csv, several platform templates, and sub-skill
scripts/tests had all drifted. Ran the project's own `sync-assets.mjs`
to bring cli/assets back in line with the source of truth per the
documented Sync Rules; `--check` now reports assets as in sync.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* fix(cli): install all 7 skills via uipro init, not just the orchestrator
`uipro init` rendered only the orchestrator (ui-ux-pro-max) and never
delivered the 6 sibling skills (banner-design, brand, design,
design-system, slides, ui-styling), so users got 1 of 7 skills (#362).
- sync-assets.mjs: bundle the 6 sub-skills into cli/assets/skills/ as
static copies (source of truth: .claude/skills/), with sync + check
coverage. Excludes ui-styling/canvas-fonts (~5.8MB of TTF) and
__pycache__/.pyc cruft — a skill registers from its SKILL.md, not its
fonts — so the bundle adds ~0.9MB, not ~6.6MB.
- template.ts: after rendering the orchestrator, install each bundled
sub-skill as a sibling. The skills parent is derived from the
platform's skillPath (skills/ for most, prompts/ for copilot,
steering/ for kiro) rather than hardcoded.
- uninstall.ts: remove the sub-skills too.
Verified: check:assets in sync, tsc passes, and a per-platform install
harness delivers all 7 skills to the correct parent dir with no fonts.
Closes#362
* fix(cli): filter excluded files from target side of check:assets
check:assets filtered sourceFiles with isExcludedAssetFile but not
targetFiles, so a stray cli/assets/scripts/__pycache__/*.pyc (generated
by a local Python run) was reported as an "extra asset file" and failed
the gate. Apply the same predicate to targetFiles in both the
dirsToSync and sub-skill loops.
Verified: check:assets now passes with __pycache__/*.pyc present in the
target tree; typecheck passes.
* fix(cli): uninstall from each platform's real skills dir, not hardcoded skills/
removeSkillDir() hardcoded <folder>/skills/<name>, but the installer
places skills under each platform config's skillPath parent — copilot in
.github/prompts/, kiro in .kiro/steering/. So uninstall left those
platforms' skills (orchestrator + sub-skills) behind.
Derive the install parent from loadPlatformConfig(aiType).folderStructure
(same source the installer uses), and keep the legacy <folder>/skills/
cleanup (incl. .shared/) for older installs. Deduped via a Set.
Verified: typecheck passes; an install+uninstall harness removes all 7
skills with zero leftovers for claude (.claude/skills), copilot
(.github/prompts) and kiro (.kiro/steering).
* fix(cli): re-sync bundled sub-skills after #385 stripped ckm- names
#385 merged to main and removed the ckm- prefix from the six
.claude/skills/*/SKILL.md name fields. This branch's bundled copies
under cli/assets/skills/ still carried the old ckm- names, so after the
PR merges with main the source no longer matched the bundle and the
check-asset-sync CI gate failed (stale asset file: skills/*/SKILL.md).
Merge main and regenerate the bundle so cli/assets/skills matches the
current .claude/skills source of truth. check:assets and typecheck pass.