Skip to content
Back to skills

2651 2026 02 19 Ruamel Yaml Migration Plan 840b543c

ASecurity

> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** Replace all pyyaml usage with a shared frontmatter module backed by ruamel.yaml + python-frontmatter, fix false quoting instructions, and remove CI inline validation. **Architecture:** A shared `frontmatter_utils.py` module provides a `RuamelYAMLHandler` (python-frontmatter `BaseHandler` subclass) and convenience functions. All scripts that parse/write frontmatter import from t...

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
documentationpythongobashcode-reviewgitapidocumentation

Works with

  • claude code
  • cli
  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 2651-2026-02-19-ruamel-yaml-migration-plan_840b543c --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2651 2026 02 19 Ruamel Yaml Migration Plan 840b543c?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2651 2026 02 19 Ruamel Yaml Migration Plan 840b543c
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2651-2026-02-19-ruamel-yaml-migration-plan-840b543/badge)](https://www.skillsdirectory.com/skills/tools-only-2651-2026-02-19-ruamel-yaml-migration-plan-840b543)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Shared Frontmatter Module + ruamel.yaml Migration — Implementation Plan

> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

**Goal:** Replace all pyyaml usage with a shared frontmatter module backed by ruamel.yaml + python-frontmatter, fix false quoting instructions, and remove CI inline validation.

**Architecture:** A shared `frontmatter_utils.py` module provides a `RuamelYAMLHandler` (python-frontmatter `BaseHandler` subclass) and convenience functions. All scripts that parse/write frontmatter import from this module instead of reimplementing extraction. Validator FM009 stays but changes purpose to detect broken YAML from unquoted colons.

**Tech Stack:** ruamel.yaml>=0.18.0, python-frontmatter>=1.1.0, tomlkit>=0.13.0, Pydantic (existing), Typer/Rich (existing)

**Design doc:** [docs/plans/2026-02-19-ruamel-yaml-migration-design.md](./2026-02-19-ruamel-yaml-migration-design.md)

**Delegation:** All Python implementation tasks delegate to `@python3-development:python-cli-architect`. Documentation/instruction updates delegate to `@plugin-creator:contextual-ai-documentation-optimizer`. Activate `/python3-development:python3-development` skill before first delegation.

---

## Task 1: Update pyproject.toml Dependencies

**Files:**
- Modify: `pyproject.toml`

**Step 1: Add ruamel.yaml and tomlkit dev dependencies**

In `pyproject.toml` under `[project.optional-dependencies]` or `[dependency-groups]` dev section:
- Add `"ruamel.yaml>=0.18.0"`
- Add `"tomlkit>=0.13.0"`
- Remove `"types-pyyaml>=6.0.12.20250915"`
- Keep `"python-frontmatter>=1.1.0"` (already present)

**Step 2: Install updated deps**

Run: `uv sync`
Expected: Clean install, no errors

**Step 3: Verify imports work**

Run: `uv run python -c "from ruamel.yaml import YAML; print('ruamel.yaml OK')"`
Run: `uv run python -c "import tomlkit; print('tomlkit OK')"`
Expected: Both print OK

**Step 4: Commit**

```bash
git add pyproject.toml uv.lock
git commit -m "build(deps): add ruamel.yaml and tomlkit, remove types-pyyaml"
```

---

## Task 2: Create Shared Frontmatter Module — Tests

**Files:**
- Create: `plugins/plugin-creator/tests/test_frontmatter_utils.py`

**Step 1: Write tests for RuamelYAMLHandler**

```python
"""Tests for frontmatter_utils shared module."""

from __future__ import annotations

from pathlib import Path

import pytest


class TestRuamelYAMLHandler:
    """Test the custom python-frontmatter handler using ruamel.yaml."""

    def test_load_simple_frontmatter(self, tmp_path: Path) -> None:
        """Handler parses simple frontmatter without quotes."""
        md = tmp_path / "test.md"
        md.write_text("---\ndescription: A simple description\ntools: Bash, Read\n---\nBody content\n")
        from frontmatter_utils import load_frontmatter

        post = load_frontmatter(md)
        assert post["description"] == "A simple description"
        assert post["tools"] == "Bash, Read"
        assert post.content == "Body content"

    def test_load_quoted_frontmatter(self, tmp_path: Path) -> None:
        """Handler preserves quotes when YAML syntax requires them."""
        md = tmp_path / "test.md"
        md.write_text('---\ndescription: "Has: colon in value"\n---\nBody\n')
        from frontmatter_utils import load_frontmatter

        post = load_frontmatter(md)
        assert post["description"] == "Has: colon in value"

    def test_load_no_frontmatter(self, tmp_path: Path) -> None:
        """Handler returns empty metadata for files without frontmatter."""
        md = tmp_path / "test.md"
        md.write_text("Just body content, no frontmatter.\n")
        from frontmatter_utils import load_frontmatter

        post = load_frontmatter(md)
        assert dict(post.metadata) == {}
        assert "Just body content" in post.content

    def test_roundtrip_preserves_unquoted(self, tmp_path: Path) -> None:
        """Round-trip does not add unnecessary quotes."""
        original = "---\ndescription: No quotes needed here\ntools: Bash, Read\n---\nBody\n"
        md = tmp_path / "test.md"
        md.write_text(original)
        from frontmatter_utils import dump_frontmatter, load_frontmatter

        post = load_frontmatter(md)
        result = dump_frontmatter(post)
        assert 'description: No quotes needed here' in result
        assert '"No quotes needed here"' not in result
        assert "'No quotes needed here'" not in result

    def test_roundtrip_preserves_required_quotes(self, tmp_path: Path) -> None:
        """Round-trip keeps quotes where YAML syntax demands them."""
        original = '---\ndescription: "Contains: colon that needs quoting"\n---\nBody\n'
        md = tmp_path / "test.md"
        md.write_text(original)
        from frontmatter_utils import dump_frontmatter, load_frontmatter

        post = load_frontmatter(md)
        result = dump_frontmatter(post)
        # The colon-space in value means quotes are required
        assert "Contains: colon that needs quoting" in result

    def test_roundtrip_removes_unnecessary_quotes(self, tmp_path: Path) -> None:
        """Round-trip strips quotes that YAML does not require."""
        original = '---\ndescription: "No special chars at all"\n---\nBody\n'
        md = tmp_path / "test.md"
        md.write_text(original)
        from frontmatter_utils import dump_frontmatter, load_frontmatter

        post = load_frontmatter(md)
        result = dump_frontmatter(post)
        # ruamel.yaml with preserve_quotes may keep them — verify behavior
        # This test documents actual behavior
        assert "No special chars at all" in result


class TestConvenienceAPI:
    """Test load/dump/update convenience functions."""

    def test_loads_frontmatter_from_string(self) -> None:
        """Parse frontmatter from a string."""
        from frontmatter_utils import loads_frontmatter

        text = "---\ndescription: Test\nmodel: sonnet\n---\nContent here\n"
        post = loads_frontmatter(text)
        assert post["description"] == "Test"
        assert post["model"] == "sonnet"
        assert post.content == "Content here"

    def test_dumps_frontmatter_to_file(self, tmp_path: Path) -> None:
        """Write frontmatter post to a file."""
        from frontmatter_utils import dumps_frontmatter, loads_frontmatter

        text = "---\ndescription: Written to file\n---\nBody\n"
        post = loads_frontmatter(text)
        out = tmp_path / "output.md"
        dumps_frontmatter(post, out)
        assert out.exists()
        content = out.read_text()
        assert "description: Written to file" in content
        assert "Body" in content

    def test_update_field_existing(self, tmp_path: Path) -> None:
        """Update an existing field without re-serializing everything."""
        md = tmp_path / "test.md"
        md.write_text("---\ndescription: Old value\ntools: Bash\n---\nBody\n")
        from frontmatter_utils import load_frontmatter, update_field

        update_field(md, "description", "New value")
        post = load_frontmatter(md)
        assert post["description"] == "New value"
        assert post["tools"] == "Bash"

    def test_update_field_new(self, tmp_path: Path) -> None:
        """Add a new field that did not exist."""
        md = tmp_path / "test.md"
        md.write_text("---\ndescription: Existing\n---\nBody\n")
        from frontmatter_utils import load_frontmatter, update_field

        update_field(md, "model", "sonnet")
        post = load_frontmatter(md)
        assert post["description"] == "Existing"
        assert post["model"] == "sonnet"

    def test_body_content_preserved(self, tmp_path: Path) -> None:
        """Markdown body with code blocks and special chars survives round-trip."""
        body = "# Heading\n\nSome text with `code` and **bold**.\n\n```python\ndef foo():\n    pass\n```\n"
        md = tmp_path / "test.md"
        md.write_text(f"---\ndescription: Test\n---\n{body}")
        from frontmatter_utils import dump_frontmatter, load_frontmatter

        post = load_frontmatter(md)
        result = dump_frontmatter(post)
        # Body content after the closing --- must match
        body_part = result.split("---\n", 2)[2]
        assert "```python" in body_part
        assert "def foo():" in body_part


class TestEdgeCases:
    """Edge cases and error handling."""

    def test_empty_file(self, tmp_path: Path) -> None:
        """Empty file does not crash."""
        md = tmp_path / "empty.md"
        md.write_text("")
        from frontmatter_utils import load_frontmatter

        post = load_frontmatter(md)
        assert dict(post.metadata) == {}

    def test_frontmatter_with_boolean_values(self, tmp_path: Path) -> None:
        """Boolean-like strings in frontmatter are preserved as strings when quoted."""
        md = tmp_path / "test.md"
        md.write_text('---\ndescription: "true"\nuser-invocable: true\n---\nBody\n')
        from frontmatter_utils import load_frontmatter

        post = load_frontmatter(md)
        assert post["user-invocable"] is True

    def test_frontmatter_with_list_values(self, tmp_path: Path) -> None:
        """List values in frontmatter are handled correctly."""
        md = tmp_path / "test.md"
        md.write_text("---\ndescription: Test\ntools:\n  - Bash\n  - Read\n  - Write\n---\nBody\n")
        from frontmatter_utils import load_frontmatter

        post = load_frontmatter(md)
        assert post["tools"] == ["Bash", "Read", "Write"]

    def test_unicode_in_description(self, tmp_path: Path) -> None:
        """Unicode characters survive round-trip."""
        md = tmp_path / "test.md"
        md.write_text("---\ndescription: Handles em\u2014dashes and curly \u201cquotes\u201d\n---\nBody\n")
        from frontmatter_utils import dump_frontmatter, load_frontmatter

        post = load_frontmatter(md)
        result = dump_frontmatter(post)
        assert "\u2014" in result
        assert "\u201c" in result
```

**Step 2: Run tests to verify they fail**

Run: `uv run pytest plugins/plugin-creator/tests/test_frontmatter_utils.py -v`
Expected: FAIL — `ModuleNotFoundError: No module named 'frontmatter_utils'`

**Step 3: Commit test file**

```bash
git add plugins/plugin-creator/tests/test_frontmatter_utils.py
git commit -m "test(frontmatter): add tests for shared frontmatter_utils module"
```

---

## Task 3: Create Shared Frontmatter Module — Implementation

**Files:**
- Create: `plugins/plugin-creator/scripts/frontmatter_utils.py`

**Step 1: Implement the module**

The module provides:
- `RuamelYAMLHandler(BaseHandler)` — custom handler using ruamel.yaml
- `load_frontmatter(path)` — read markdown file, return Post
- `loads_frontmatter(text)` — parse from string
- `dump_frontmatter(post)` — serialize to string
- `dumps_frontmatter(post, path)` — write to file
- `update_field(path, field, value)` — surgical field update

PEP 723 dependencies: `ruamel.yaml>=0.18.0`, `python-frontmatter>=1.1.0`

Delegate to `@python3-development:python-cli-architect` with:
- The test file as the contract
- The `mkapidocs` `yaml_utils.py` pattern as reference
- The `python-frontmatter` `BaseHandler` API documented in the design doc

**Step 2: Run tests to verify they pass**

Run: `uv run pytest plugins/plugin-creator/tests/test_frontmatter_utils.py -v`
Expected: All tests PASS

**Step 3: Run linting**

Run: `uv run prek run --files plugins/plugin-creator/scripts/frontmatter_utils.py`
Expected: Clean

**Step 4: Set executable bit**

Run: `chmod +x plugins/plugin-creator/scripts/frontmatter_utils.py`

**Step 5: Commit**

```bash
git add plugins/plugin-creator/scripts/frontmatter_utils.py
git commit -m "feat(frontmatter): add shared frontmatter_utils module with ruamel.yaml handler"
```

---

## Task 4: Delete CI Inline YAML/TOML Validation

**Files:**
- Modify: `.github/workflows/code-quality.yml`

**Step 1: Identify the inline blocks**

The inline Python blocks at lines ~430-479 that run:
- `uv run python -c "import tomllib; ..."` for TOML syntax checking
- `uv run --with pyyaml python -c "import yaml; yaml.safe_load(...)"` for YAML syntax checking

**Step 2: Delete the inline blocks**

Remove the entire step(s) containing inline Python for YAML/TOML syntax validation. Pre-commit hooks `check-yaml` and `check-toml` (`.pre-commit-config.yaml` lines 39, 42) already cover this.

**Step 3: Verify CI workflow is valid YAML**

Run: `uv run prek run --files .github/workflows/code-quality.yml`
Expected: Clean

**Step 4: Commit**

```bash
git add .github/workflows/code-quality.yml
git commit -m "ci: remove inline YAML/TOML validation duplicated by pre-commit hooks"
```

---

## Task 5: Migrate plugin_validator.py to Shared Module

**Files:**
- Modify: `plugins/plugin-creator/scripts/plugin_validator.py`
- Test: `plugins/plugin-creator/tests/test_frontmatter_validator.py`

**Step 1: Run existing tests to confirm baseline**

Run: `uv run pytest plugins/plugin-creator/tests/test_frontmatter_validator.py -v`
Expected: All PASS

**Step 2: Migrate import and extraction**

Replace:
- `import yaml` with `from frontmatter_utils import load_frontmatter, loads_frontmatter`
- Module-level `extract_frontmatter()` function — delegate extraction to shared module
- `yaml.safe_load()` calls in `FrontmatterValidator` — use shared module
- `yaml.dump()` calls in `_apply_fixes()` — use shared module's ruamel.yaml instance
- PEP 723 dep: `"pyyaml>=6.0"` → `"ruamel.yaml>=0.18.0"`, add `"python-frontmatter>=1.1.0"`

Delegate to `@python3-development:python-cli-architect` with file paths, test file path, and the constraint that all existing tests must continue to pass.

**Step 3: Run tests**

Run: `uv run pytest plugins/plugin-creator/tests/test_frontmatter_validator.py -v`
Expected: All PASS (behavior unchanged)

**Step 4: Run linting**

Run: `uv run prek run --files plugins/plugin-creator/scripts/plugin_validator.py`
Expected: Clean

**Step 5: Commit**

```bash
git add plugins/plugin-creator/scripts/plugin_validator.py
git commit -m "refactor(plugin-validator): migrate from pyyaml to shared frontmatter_utils module"
```

---

## Task 6: Migrate validate_frontmatter.py to Shared Module

**Files:**
- Modify: `plugins/plugin-creator/scripts/validate_frontmatter.py`

**Step 1: Migrate import and extraction**

Same pattern as Task 5:
- Replace `import yaml` with shared module imports
- Replace `yaml.safe_load()` and `yaml.dump()` calls
- Update PEP 723 deps

Delegate to `@python3-development:python-cli-architect`.

**Step 2: Run the script to verify it works**

Run: `uv run plugins/plugin-creator/scripts/validate_frontmatter.py --help`
Expected: Help output, no import errors

**Step 3: Run linting**

Run: `uv run prek run --files plugins/plugin-creator/scripts/validate_frontmatter.py`
Expected: Clean

**Step 4: Commit**

```bash
git add plugins/plugin-creator/scripts/validate_frontmatter.py
git commit -m "refactor(validate-frontmatter): migrate from pyyaml to shared frontmatter_utils module"
```

---

## Task 7: Migrate Remaining Scripts (5 files)

**Files:**
- Modify: `plugins/plugin-creator/skills/skill-creator/scripts/quick_validate.py`
- Modify: `plugins/python3-development/skills/implementation-manager/scripts/task_format.py`
- Modify: `plugins/python3-development/scripts/migrate_task_format.py`
- Modify: `plugins/python3-development/scripts/split_task_file.py`
- Modify: `plugins/gitlab-skill/skills/gitlab-skill/scripts/sync_gitlab_docs.py`

**Step 1: Migrate each script**

For each file:
- Replace `import yaml` with shared module imports
- Replace `yaml.safe_load()` calls with shared module functions
- Update PEP 723 deps: `"pyyaml>=6.0"` → `"ruamel.yaml>=0.18.0"`, add `"python-frontmatter>=1.1.0"`

Delegate to `@python3-development:python-cli-architect` with all 5 file paths.

**Step 2: Verify each script runs**

Run each with `--help` or a dry-run mode to confirm no import errors.

**Step 3: Run linting on all modified files**

Run: `uv run prek run --files <each file>`
Expected: Clean for all

**Step 4: Commit**

```bash
git add plugins/plugin-creator/skills/skill-creator/scripts/quick_validate.py \
      plugins/python3-development/skills/implementation-manager/scripts/task_format.py \
      plugins/python3-development/scripts/migrate_task_format.py \
      plugins/python3-development/scripts/split_task_file.py \
      plugins/gitlab-skill/skills/gitlab-skill/scripts/sync_gitlab_docs.py
git commit -m "refactor(scripts): migrate 5 scripts from pyyaml to shared frontmatter_utils module"
```

---

## Task 8: Migrate discover_linters.py (Non-Frontmatter YAML)

**Files:**
- Modify: `plugins/holistic-linting/skills/holistic-linting/scripts/discover_linters.py`

**Step 1: Migrate YAML handling**

This script reads `.pre-commit-config.yaml` (not frontmatter). It needs ruamel.yaml directly, not the frontmatter module:
- Replace lazy `import yaml` fallback with `from ruamel.yaml import YAML`
- Replace `yaml.safe_load(f)` with `YAML(typ='safe').load(f)`
- PEP 723: remove `"types-pyyaml>=6.0.0"`, change `"pyyaml>=6.0"` to `"ruamel.yaml>=0.18.0"`, keep `"tomlkit>=0.13.0"`

Delegate to `@python3-development:python-cli-architect`.

**Step 2: Verify script runs**

Run: `uv run plugins/holistic-linting/skills/holistic-linting/scripts/discover_linters.py --help`
Expected: No import errors

**Step 3: Run linting**

Run: `uv run prek run --files plugins/holistic-linting/skills/holistic-linting/scripts/discover_linters.py`
Expected: Clean

**Step 4: Commit**

```bash
git add plugins/holistic-linting/skills/holistic-linting/scripts/discover_linters.py
git commit -m "refactor(discover-linters): migrate from pyyaml to ruamel.yaml"
```

---

## Task 9: Remove Dead pyyaml Dependency from fix_tool_formats.py

**Files:**
- Modify: `plugins/plugin-creator/scripts/fix_tool_formats.py`

**Step 1: Remove pyyaml from PEP 723 deps**

Remove `"pyyaml>=6.0.0"` from the PEP 723 `dependencies` list. No code changes — pyyaml is never imported.

**Step 2: Run linting**

Run: `uv run prek run --files plugins/plugin-creator/scripts/fix_tool_formats.py`
Expected: Clean

**Step 3: Commit**

```bash
git add plugins/plugin-creator/scripts/fix_tool_formats.py
git commit -m "fix(fix-tool-formats): remove unused pyyaml dependency"
```

---

## Task 10: Update Validator FM009 Purpose and Tests

**Files:**
- Modify: `plugins/plugin-creator/scripts/plugin_validator.py` (FM009 messaging)
- Modify: `plugins/plugin-creator/tests/test_frontmatter_validator.py` (FM009 test assertions)
- Modify: `plugins/plugin-creator/tests/conftest.py` (fixtures if needed)

**Step 1: Update FM009 error message and suggestion**

In `plugin_validator.py`, find the FM009 emission code. Change:
- Message: from "quote the description or remove colons" to "description contains unquoted colons — this will break YAML parsing. Quote the value or remove colons"
- Suggestion: from "Quote the description" to "Quote the description value or avoid colons. ruamel.yaml handles quoting on write, but hand-edited YAML with unquoted colons fails to parse"
- Keep the auto-fix behavior (adding quotes) unchanged

**Step 2: Update FM009 test**

In `test_frontmatter_validator.py`, update `test_autofix_unquoted_colon` assertions to match new message text.

**Step 3: Run tests**

Run: `uv run pytest plugins/plugin-creator/tests/test_frontmatter_validator.py -v`
Expected: All PASS

**Step 4: Commit**

```bash
git add plugins/plugin-creator/scripts/plugin_validator.py \
      plugins/plugin-creator/tests/test_frontmatter_validator.py
git commit -m "refactor(validator): update FM009 to detect broken YAML, not enforce quoting convention"
```

---

## Task 11: Update Error Code Documentation

**Files:**
- Modify: `plugins/plugin-creator/references/ERROR_CODES.md`
- Modify: `plugins/plugin-creator/docs/ERROR_CODES.md`
- Modify: `plugins/plugin-creator/references/ARCHITECTURE.md`
- Modify: `plugins/plugin-creator/references/USAGE.md`

**Step 1: Update FM009 descriptions**

In both ERROR_CODES.md files:
- Change FM009 description from "Unquoted description with colons" to "Unquoted colons in description — breaks YAML parsing"
- Update fix guidance to match new purpose

In ARCHITECTURE.md and USAGE.md:
- Update FM009 references to match new description
- Update any pyyaml references to ruamel.yaml

Delegate to `@plugin-creator:contextual-ai-documentation-optimizer`.

**Step 2: Run linting on modified files**

Run: `uv run prek run --files <each file>`
Expected: Clean

**Step 3: Commit**

```bash
git add plugins/plugin-creator/references/ERROR_CODES.md \
      plugins/plugin-creator/docs/ERROR_CODES.md \
      plugins/plugin-creator/references/ARCHITECTURE.md \
      plugins/plugin-creator/references/USAGE.md
git commit -m "docs(error-codes): update FM009 description and pyyaml references"
```

---

## Task 12: Update Active Instruction Files (9 files)

**Files:**
- Modify: `plugins/plugin-creator/skills/write-frontmatter-description/SKILL.md`
- Modify: `plugins/plugin-creator/skills/skill-creator/SKILL.md`
- Modify: `plugins/plugin-creator/skills/claude-skills-overview-2026/SKILL.md`
- Modify: `plugins/plugin-creator/agents/contextual-ai-documentation-optimizer.md`
- Modify: `plugins/plugin-creator/agents/refactor-validator.md`
- Modify: `.claude/skills/agent-creator/references/agent-schema.md`
- Modify: `plugins/plugin-creator/skills/agent-creator/references/agent-schema.md`
- Modify: `.claude/skills/optimize-claude-md/SKILL.md`
- Modify: `.claude/commands/write-to-skill-file-original.md`

**Step 1: Update quoting guidance in all 9 files**

Change all instances of:
- "always quote descriptions" → "avoid colons in descriptions; quote only when YAML syntax requires it"
- "use quoted single-line strings" → "use single-line strings; quote only when YAML syntax requires it (colons, leading special chars, boolean literals)"
- "Description is single-line quoted string" → "Description is single-line string (quoted only if YAML syntax requires)"
- "colons trigger YAML quoting" → "colons in descriptions break YAML parsing if unquoted — avoid colons or quote the value"

Keep all FM004/multiline indicator guidance unchanged — that is a real Claude Code platform limitation.

Delegate to `@plugin-creator:contextual-ai-documentation-optimizer` with all 9 file paths and the exact guidance changes.

**Step 2: Run linting**

Run: `uv run prek run --files <each file>`
Expected: Clean

**Step 3: Commit**

```bash
git add <all 9 files>
git commit -m "docs(skills): fix false quoting convention in 9 instruction files"
```

---

## Task 13: Update CLAUDE.md / README Files (4 files)

**Files:**
- Modify: `plugins/plugin-creator/CLAUDE.md`
- Modify: `plugins/plugin-creator/scripts/CLAUDE.md`
- Modify: `plugins/plugin-creator/README.md`
- Modify: `plugins/plugin-creator/scripts/README.md`

**Step 1: Update auto-fix capability descriptions**

Change: "Multiline descriptions → single-line quoted strings" → "Multiline descriptions → single-line strings"
Change: "Unquoted descriptions with colons" → "Unquoted colons in descriptions — adds quotes to prevent YAML parsing failures"

Delegate to `@plugin-creator:contextual-ai-documentation-optimizer`.

**Step 2: Run linting**

Run: `uv run prek run --files <each file>`
Expected: Clean

**Step 3: Commit**

```bash
git add <all 4 files>
git commit -m "docs(plugin-creator): update auto-fix descriptions for new quoting rules"
```

---

## Task 14: Update Project Convention Docs (6 files)

**Files:**
- Modify: `.claude/docs/TASK_FILE_FORMAT.md`
- Modify: `plugins/plugin-creator/references/ARCHITECTURE.md`
- Modify: `plugins/plugin-creator/references/USAGE.md`
- Modify: `plugins/plugin-creator/skills/add-doc-updater/references/doc-updater-template.md`
- Modify: `plugins/python3-development/agents/code-reviewer.md`
- Modify: `plugins/python3-development/agents/python-cli-design-spec.md`

**Step 1: Update pyyaml references to ruamel.yaml**

In each file, replace pyyaml code examples and references with ruamel.yaml equivalents:
- `import yaml` → `from ruamel.yaml import YAML` or `from frontmatter_utils import load_frontmatter`
- `yaml.safe_load()` → `YAML(typ='safe').load()` or shared module call
- `pyyaml>=6.0` dependency references → `ruamel.yaml>=0.18.0`
- "pyyaml" library name references → "ruamel.yaml"

Delegate to `@plugin-creator:contextual-ai-documentation-optimizer` for skill/agent docs, `@python3-development:python-cli-architect` for python3-development agent docs.

**Step 2: Run linting**

Run: `uv run prek run --files <each file>`
Expected: Clean

**Step 3: Commit**

```bash
git add <all 6 files>
git commit -m "docs: update pyyaml references to ruamel.yaml in project convention docs"
```

---

## Task 15: Update Third-Party Library Reference Docs (5+ files)

**Files:**
- Modify: `plugins/holistic-linting/skills/holistic-linting/references/rules/bandit/deserialization.md`
- Modify: `plugins/python3-development/skills/python3-development/references/modern-modules/box.md`
- Modify: `plugins/python3-development/skills/python3-development/references/modern-modules/shiv.md`
- Modify: `plugins/python3-development/skills/hatchling/references/` (multiple files with pyyaml examples)
- Modify: `plugins/python3-development/skills/python3-development/planning/reference-document-architecture.md`

**Step 1: Update pyyaml examples to ruamel.yaml**

Replace pyyaml code examples with ruamel.yaml equivalents. For bandit deserialization docs, update `yaml.safe_load()` examples to show ruamel.yaml safe mode. For hatchling/box/shiv, update dependency references.

Delegate to `@plugin-creator:contextual-ai-documentation-optimizer`.

**Step 2: Run linting**

Run: `uv run prek run --files <each file>`
Expected: Clean

**Step 3: Commit**

```bash
git add <all modified files>
git commit -m "docs: update pyyaml examples to ruamel.yaml in library reference docs"
```

---

## Task 16: Add CLAUDE.md Convention Statement

**Files:**
- Modify: `.claude/CLAUDE.md` (project-level)

**Step 1: Add library convention**

Add a section to the project CLAUDE.md stating:

```markdown
## YAML and TOML Libraries

This repository uses `ruamel.yaml` for all YAML operations and `tomlkit` for TOML read-write operations. Never use `pyyaml` (`import yaml`). `tomllib` (stdlib) is acceptable for read-only TOML in stdlib-only contexts.

For frontmatter parsing/writing, use the shared module: `from frontmatter_utils import load_frontmatter, dump_frontmatter`.
```

**Step 2: Run linting**

Run: `uv run prek run --files .claude/CLAUDE.md`
Expected: Clean

**Step 3: Commit**

```bash
git add .claude/CLAUDE.md
git commit -m "docs(CLAUDE.md): add ruamel.yaml and tomlkit convention statement"
```

---

## Task 17: Mechanical Quote Normalization

**Files:**
- Modify: All frontmatter-bearing component files (skills, agents, commands, rules)

**Step 1: Write normalization script**

Create a script that:
1. Uses `plugin_validator.py`'s `FileType` enum to discover frontmatter-bearing files
2. For each file, calls `load_frontmatter()` then `dumps_frontmatter()` to round-trip through ruamel.yaml
3. Reports which files were modified (diff detection)
4. Has `--dry-run` mode that reports changes without writing

Delegate to `@python3-development:python-cli-architect`.

**Step 2: Run in dry-run mode**

Run: `uv run plugins/plugin-creator/scripts/normalize_frontmatter.py --dry-run`
Expected: List of files that would change, with diff preview

**Step 3: Review dry-run output**

Inspect the reported changes. Verify:
- Unnecessary quotes are removed
- Required quotes (colons, special chars) are preserved
- No content corruption

**Step 4: Run for real**

Run: `uv run plugins/plugin-creator/scripts/normalize_frontmatter.py`
Expected: Files updated

**Step 5: Run full validation**

Run: `uv run prek run --all-files`
Expected: Clean

**Step 6: Commit**

```bash
git add -A
git commit -m "style(frontmatter): normalize YAML quoting across all component files"
```

---

## Task 18: Final Verification

**Step 1: Run full test suite**

Run: `uv run pytest plugins/plugin-creator/tests/ -v`
Expected: All PASS

**Step 2: Run full linting**

Run: `uv run prek run --all-files`
Expected: Clean

**Step 3: Verify no pyyaml imports remain in scripts**

Run: `grep -rn "^import yaml$\|^from yaml import" plugins/ .github/ --include="*.py"`
Expected: Zero matches

**Step 4: Verify no pyyaml deps remain in PEP 723 blocks**

Run: `grep -rn "pyyaml" plugins/ --include="*.py" | grep -v "planning/" | grep -v "tests/"`
Expected: Zero matches (or only detection/instruction references)

**Step 5: Run plugin validator on a known-good skill**

Run: `uv run plugins/plugin-creator/scripts/plugin_validator.py plugins/plugin-creator/`
Expected: Passes validation

**Step 6: Verify FM009 still catches unquoted colons**

Create a temp file with `description: has: colon` (unquoted), run validator, confirm FM009 fires.

**Step 7: Verify FM004 still catches multiline indicators**

Create a temp file with `description: >-\n  multiline`, run validator, confirm FM004 fires.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…