Skill YAML invalid + missing typecheck-hook install on mosaic@0.0.30 #515

Open
opened 2026-05-14 01:40:25 +00:00 by jason.woltje · 0 comments
Owner

Summary

Fresh mosaic claude session on @mosaicstack/mosaic@0.0.30 surfaces three startup warnings that all originate from the shipped framework — two malformed skill manifests and a hook that the audit requires but the installer never lays down.

⚠ Skipped loading 2 skill(s) due to invalid SKILL.md files.
⚠ /home/localadmin/.config/mosaic/skills/mosaic-woodpecker/SKILL.md: invalid YAML: mapping values are not allowed in this context at line 2 column 245
⚠ /home/localadmin/.config/mosaic/skills/mosaic-deploy/SKILL.md:      invalid YAML: mapping values are not allowed in this context at line 2 column 67
[mosaic] Claude Code settings audit:
  ⚠ Missing PostToolUse hook: typecheck-hook.sh

1. Invalid YAML in shipped SKILL.md frontmatter

Both description: values are unquoted and contain a : (colon-space) sequence, which YAML 1.2 parses as a nested mapping separator. Claude Code's skill loader uses a strict parser and drops the skill entirely — mosaic-woodpecker and mosaic-deploy are unavailable in every Claude session until this is fixed.

framework/skills/mosaic-woodpecker/SKILL.md (line 2, col 245 — CI URL: https://...)

---
name: mosaic-woodpecker
description: Manage Woodpecker CI pipelines for Mosaic Stack projects. ... CI URL: https://ci.mosaicstack.dev.
---

framework/skills/mosaic-deploy/SKILL.md (line 2, col 67 — Mosaic Stack projects: push branch ...)

---
name: mosaic-deploy
description: Full end-to-end deploy flow for Mosaic Stack projects: push branch -> open PR -> wait for CI -> merge -> redeploy Portainer stack. ...
---

Fix

Single-quote both description: values (no embedded single quotes, so this is safe and minimal). Verified locally with yaml.safe_load:

description: 'Manage Woodpecker CI pipelines ... CI URL: https://ci.mosaicstack.dev.'
description: 'Full end-to-end deploy flow for Mosaic Stack projects: push branch -> open PR -> ...'

(Optionally replace the arrow characters in the deploy description with -> to keep the frontmatter ASCII-only.)

A repo-wide guard would be cheap insurance — e.g. a CI step that runs yaml.safe_load on the frontmatter of every framework/skills/*/SKILL.md. Happy to send a PR with the two edits plus a validator if helpful.

2. typecheck-hook.sh audited but not installed

mosaic launch (dist/commands/launch.js:80) declares:

const requiredPostToolUse = ['qa-hook-stdin.sh', 'typecheck-hook.sh'];

and framework/runtime/claude/settings.json defines a PostToolUse entry for ~/.config/mosaic/tools/qa/typecheck-hook.sh. But on this install:

  • ~/.config/mosaic/tools/qa/typecheck-hook.sh does not exist (other QA hooks in the same dir do — qa-hook-stdin.sh, qa-hook-handler.sh, etc.)
  • ~/.claude/settings.json PostToolUse only contains the qa-hook-stdin.sh entry; the typecheck-hook.sh entry was never written.

So the audit reliably fires on every launch and the suggested remediation (mosaic doctor) does not appear to repair it (need to confirm — possibly doctor only warns, doesn't sync).

Manual repair that resolved it locally:

cp ~/.npm-global/lib/node_modules/@mosaicstack/mosaic/framework/tools/qa/typecheck-hook.sh \
   ~/.config/mosaic/tools/qa/typecheck-hook.sh
chmod +x ~/.config/mosaic/tools/qa/typecheck-hook.sh
# + append the matching PostToolUse entry from framework/runtime/claude/settings.json
#   to ~/.claude/settings.json

Likely root cause

Either the installer's qa-tools sync step is missing typecheck-hook.sh from its file list, or it was added to the audit (launch.js) and runtime template after the install/sync logic was updated, leaving prior installs out of sync.

Suggested fix

  • Have mosaic doctor actively repair the two settings-audit failures (copy missing scripts from framework/tools/qa/ into ~/.config/mosaic/tools/qa/, merge missing hook entries into ~/.claude/settings.json from the framework template) — and exit non-zero if it can't.
  • Verify the installer copies the full framework/tools/qa/ directory rather than an explicit allowlist.

Bonus: tools/git/issue-create.sh shell-injects the body string

Discovered while filing this issue. ~/.config/mosaic/tools/git/issue-create.sh builds the tea command as a string and runs it with eval:

CMD="tea issue create --title \"$TITLE\""
[[ -n "$BODY" ]] && CMD="$CMD --description \"$BODY\""
...
eval "$CMD"

Any markdown body containing backticked command names, $(...) substitutions, parentheses, or special chars (: , , ;, etc.) is re-interpreted by the shell. Filing this very issue failed with ~30 spurious errors (command not found, syntax error near unexpected token '(') before I routed around it via the API. Should pass tea's args as a real argv array (no eval), and likewise for the GitHub gh path if it has the same shape.

Happy to open a separate issue for this if preferred.

Environment

  • @mosaicstack/mosaic version: 0.0.30
  • Runtime: Claude Code (Opus 4.7)
  • OS: Debian (Linux 6.1.0-42-amd64)

Workaround applied locally

  • Quoted the two description: fields in ~/.config/mosaic/skills/mosaic-*/SKILL.md
  • Copied typecheck-hook.sh into ~/.config/mosaic/tools/qa/ and appended the PostToolUse hook entry to ~/.claude/settings.json

All three warnings cleared on next launch (pending session restart to confirm in CI/loader output).

## Summary Fresh `mosaic claude` session on `@mosaicstack/mosaic@0.0.30` surfaces three startup warnings that all originate from the shipped framework — two malformed skill manifests and a hook that the audit requires but the installer never lays down. ``` ⚠ Skipped loading 2 skill(s) due to invalid SKILL.md files. ⚠ /home/localadmin/.config/mosaic/skills/mosaic-woodpecker/SKILL.md: invalid YAML: mapping values are not allowed in this context at line 2 column 245 ⚠ /home/localadmin/.config/mosaic/skills/mosaic-deploy/SKILL.md: invalid YAML: mapping values are not allowed in this context at line 2 column 67 [mosaic] Claude Code settings audit: ⚠ Missing PostToolUse hook: typecheck-hook.sh ``` ## 1. Invalid YAML in shipped SKILL.md frontmatter Both `description:` values are unquoted and contain a `: ` (colon-space) sequence, which YAML 1.2 parses as a nested mapping separator. Claude Code's skill loader uses a strict parser and drops the skill entirely — `mosaic-woodpecker` and `mosaic-deploy` are unavailable in every Claude session until this is fixed. **`framework/skills/mosaic-woodpecker/SKILL.md`** (line 2, col 245 — `CI URL: https://...`) ```yaml --- name: mosaic-woodpecker description: Manage Woodpecker CI pipelines for Mosaic Stack projects. ... CI URL: https://ci.mosaicstack.dev. --- ``` **`framework/skills/mosaic-deploy/SKILL.md`** (line 2, col 67 — `Mosaic Stack projects: push branch ...`) ```yaml --- name: mosaic-deploy description: Full end-to-end deploy flow for Mosaic Stack projects: push branch -> open PR -> wait for CI -> merge -> redeploy Portainer stack. ... --- ``` ### Fix Single-quote both `description:` values (no embedded single quotes, so this is safe and minimal). Verified locally with `yaml.safe_load`: ```yaml description: 'Manage Woodpecker CI pipelines ... CI URL: https://ci.mosaicstack.dev.' description: 'Full end-to-end deploy flow for Mosaic Stack projects: push branch -> open PR -> ...' ``` (Optionally replace the arrow characters in the deploy description with `->` to keep the frontmatter ASCII-only.) A repo-wide guard would be cheap insurance — e.g. a CI step that runs `yaml.safe_load` on the frontmatter of every `framework/skills/*/SKILL.md`. Happy to send a PR with the two edits plus a validator if helpful. ## 2. `typecheck-hook.sh` audited but not installed `mosaic launch` (`dist/commands/launch.js:80`) declares: ```js const requiredPostToolUse = ['qa-hook-stdin.sh', 'typecheck-hook.sh']; ``` and `framework/runtime/claude/settings.json` defines a PostToolUse entry for `~/.config/mosaic/tools/qa/typecheck-hook.sh`. But on this install: - `~/.config/mosaic/tools/qa/typecheck-hook.sh` **does not exist** (other QA hooks in the same dir do — `qa-hook-stdin.sh`, `qa-hook-handler.sh`, etc.) - `~/.claude/settings.json` PostToolUse only contains the `qa-hook-stdin.sh` entry; the `typecheck-hook.sh` entry was never written. So the audit reliably fires on every launch and the suggested remediation (`mosaic doctor`) does not appear to repair it (need to confirm — possibly `doctor` only warns, doesn't sync). Manual repair that resolved it locally: ```bash cp ~/.npm-global/lib/node_modules/@mosaicstack/mosaic/framework/tools/qa/typecheck-hook.sh \ ~/.config/mosaic/tools/qa/typecheck-hook.sh chmod +x ~/.config/mosaic/tools/qa/typecheck-hook.sh # + append the matching PostToolUse entry from framework/runtime/claude/settings.json # to ~/.claude/settings.json ``` ### Likely root cause Either the installer's qa-tools sync step is missing `typecheck-hook.sh` from its file list, or it was added to the audit (`launch.js`) and runtime template after the install/sync logic was updated, leaving prior installs out of sync. ### Suggested fix - Have `mosaic doctor` actively repair the two settings-audit failures (copy missing scripts from `framework/tools/qa/` into `~/.config/mosaic/tools/qa/`, merge missing hook entries into `~/.claude/settings.json` from the framework template) — and exit non-zero if it can't. - Verify the installer copies the full `framework/tools/qa/` directory rather than an explicit allowlist. ## Bonus: `tools/git/issue-create.sh` shell-injects the body string Discovered while filing this issue. `~/.config/mosaic/tools/git/issue-create.sh` builds the `tea` command as a string and runs it with `eval`: ```bash CMD="tea issue create --title \"$TITLE\"" [[ -n "$BODY" ]] && CMD="$CMD --description \"$BODY\"" ... eval "$CMD" ``` Any markdown body containing backticked command names, `$(...)` substitutions, parentheses, or special chars (`: `, `→`, `;`, etc.) is re-interpreted by the shell. Filing this very issue failed with ~30 spurious errors (`command not found`, `syntax error near unexpected token '('`) before I routed around it via the API. Should pass `tea`'s args as a real argv array (no `eval`), and likewise for the GitHub `gh` path if it has the same shape. Happy to open a separate issue for this if preferred. ## Environment - `@mosaicstack/mosaic` version: `0.0.30` - Runtime: Claude Code (Opus 4.7) - OS: Debian (Linux 6.1.0-42-amd64) ## Workaround applied locally - Quoted the two `description:` fields in `~/.config/mosaic/skills/mosaic-*/SKILL.md` - Copied `typecheck-hook.sh` into `~/.config/mosaic/tools/qa/` and appended the PostToolUse hook entry to `~/.claude/settings.json` All three warnings cleared on next launch (pending session restart to confirm in CI/loader output).
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#515