add-puzzle-type
About
This skill scaffolds a new puzzle type across jigsawR's 10+ pipeline integration points. It generates the core module, connects it to generation, placement, rendering, and adjacency pipelines, and updates related components. Use it when adding a fully new puzzle type to ensure end-to-end coverage without missing integration points.
Quick Install
Claude Code
Recommendednpx skills add pjt222/agent-almanac -a claude-code/plugin add https://github.com/pjt222/agent-almanacgit clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/add-puzzle-typeCopy and paste this command in Claude Code to install this skill
Documentation
name: add-puzzle-type description: > jigsawRの10以上のパイプライン統合ポイントにまたがる新しいパズルタイプを スキャフォールドする。コアパズルモジュールを作成し、統合パイプライン (生成、配置、レンダリング、隣接)に接続し、ggpuzzleのgeom/statレイヤーを 追加し、DESCRIPTIONとconfig.ymlを更新し、Shinyアプリを拡張し、包括的な テストスイートを作成する。パッケージに完全に新しいパズルタイプを追加する場合や、 10ポイント統合チェックリストに従ってエンドツーエンドで漏れがないようにする場合に使用する。 license: MIT allowed-tools: Read Write Edit Bash Grep Glob metadata: author: Philipp Thoss version: "1.0" domain: jigsawr complexity: advanced language: R tags: jigsawr, puzzle-type, pipeline, integration, scaffold locale: ja source_locale: en source_commit: 6f65f316 translator: claude-sonnet-4-6 translation_date: 2026-03-16
パズルタイプの追加
jigsawRのすべてのパイプライン統合ポイントにまたがる新しいパズルタイプをスキャフォールドする。
使用タイミング
- パッケージに完全に新しいパズルタイプを追加する場合
- 確立された統合チェックリスト(CLAUDE.md 10ポイントパイプライン)に従う場合
- 新しいタイプをエンドツーエンドで接続する際に漏れがないようにする場合
入力
- 必須: 新しいタイプ名(小文字、例:
"triangular") - 必須: ジオメトリの説明(ピースの形状/配置方法)
- 必須: 外部パッケージが必要かどうか(Suggestsに追加)
- 任意: 標準パラメータ(grid、size、seed、tabsize、offset)以外のパラメータリスト
- 任意: 参照実装またはアルゴリズムソース
手順
ステップ1: コアパズルモジュールの作成
内部生成関数を持つR/<type>_puzzle.Rを作成する:
#' Generate <type> puzzle pieces (internal)
#' @noRd
generate_<type>_pieces_internal <- function(params, seed) {
# 1. RNG状態の初期化
# 2. ピースジオメトリの生成
# 3. エッジパスの構築(SVGパスデータ)
# 4. 隣接関係の計算
# 5. リストを返す: pieces, edges, adjacency, metadata
}
構造についてはR/voronoi_puzzle.RまたはR/snic_puzzle.Rのパターンに従う。
期待結果: 関数が$pieces、$edges、$adjacency、$metadataを含むリストを返す。
失敗時: generate_voronoi_pieces_internal()の返却構造と比較して、不足しているリスト要素や不正な型を特定する。
ステップ2: jigsawR_clean.Rへの接続
R/jigsawR_clean.Rを編集する:
valid_typesベクトルに"<type>"を追加- paramsセクションにタイプ固有のパラメータ抽出を追加
- タイプ固有の制約のバリデーションロジックを追加
- ファイル名プレフィックスマッピングを追加(例:
"<type>"->"<type>_")
# valid_typesに追加
valid_types <- c("rectangular", "hexagonal", "concentric", "voronoi", "snic", "<type>")
期待結果: generate_puzzle(type = "<type>")が「unknown type」エラーなく受け入れられる。
失敗時: タイプ文字列が正確なスペルでvalid_typesに追加されているか、パラメータ抽出が必要なタイプ固有引数をすべてカバーしているか確認する。
ステップ3: unified_piece_generation.Rへの接続
R/unified_piece_generation.Rを編集する:
generate_pieces_internal()にディスパッチケースを追加- タイプがPILES記法をサポートする場合、フュージョン処理を追加
# switch/dispatchに追加
"<type>" = generate_<type>_pieces_internal(params, seed)
期待結果: タイプがディスパッチされるとピースが生成される。
失敗時: ディスパッチケース文字列がタイプ名と正確に一致し、generate_<type>_pieces_internalがパズルモジュールから定義・エクスポートされているか確認する。
ステップ4: piece_positioning.Rへの接続
R/piece_positioning.Rを編集する:
新しいタイプの配置ディスパッチを追加する。ほとんどのタイプは共有配置ロジックを使用するが、カスタム処理が必要なものもある。
期待結果: apply_piece_positioning()が新しいタイプをエラーなく処理し、ピースが正しい座標に配置される。
失敗時: 新しいタイプにカスタム配置ロジックが必要か、共有配置パスを再利用できるか確認する。デフォルトパスが適用されない場合はディスパッチケースを追加する。
ステップ5: unified_renderer.Rへの接続
R/unified_renderer.Rを編集する:
render_puzzle_svg()にレンダリングケースを追加- エッジパス関数を追加:
get_<type>_edge_paths() - ピース名関数を追加:
get_<type>_piece_name()
期待結果: 正しいピース輪郭とエッジパスを持つ新しいタイプのSVG出力が生成される。
失敗時: get_<type>_edge_paths()が有効なSVGパスデータを返し、get_<type>_piece_name()が各ピースに一意の識別子を生成しているか確認する。
ステップ6: adjacency_api.Rへの接続
R/adjacency_api.Rを編集する:
get_neighbors()とget_adjacency()が新しいタイプで動作するようにネイバーディスパッチを追加する。
期待結果: get_neighbors(result, piece_id)がパズル内の任意のピースに対して正しいネイバーを返す。
失敗時: 隣接ディスパッチが正しいデータ構造を返しているか確認する。小さなグリッドでテストし、ジオメトリに対してネイバー関係を手動で検証する。
ステップ7: ggpuzzle Geomレイヤーの追加
R/geom_puzzle.Rを編集する:
make_puzzle_layer()ファクトリーを使用してgeom_puzzle_<type>()を作成する:
#' @export
geom_puzzle_<type> <- function(mapping = NULL, data = NULL, ...) {
make_puzzle_layer(type = "<type>", mapping = mapping, data = data, ...)
}
期待結果: ggplot() + geom_puzzle_<type>(aes(...))がエラーなくレンダリングされる。
失敗時: make_puzzle_layer()が正しいタイプ文字列を受け取り、geom関数が@export経由でNAMESPACEにエクスポートされているか確認する。
ステップ8: Statディスパッチの追加
R/stat_puzzle.Rを編集する:
- タイプ固有のデフォルトパラメータを追加
compute_panel()にディスパッチケースを追加
期待結果: statレイヤーがパズルジオメトリを正しく計算し、期待される数のポリゴンを生成する。
失敗時: compute_panel()ディスパッチケースが必要なカラム(x、y、group、piece_id)を含むデータフレームを返し、デフォルトパラメータが新しいタイプに適切か確認する。
ステップ9: DESCRIPTIONの更新
DESCRIPTIONを編集する:
- Descriptionフィールドのテキストに新しいタイプを追加
- 新しいパッケージを
Suggests:に追加(外部依存がある場合) Collate:を更新して新しいRファイルを含める(アルファベット順)
期待結果: devtools::document()が成功する。リストされていないファイルに関するNOTEがない。
失敗時: 新しいRファイルがCollate:フィールドにアルファベット順でリストされており、新しいSuggestsパッケージがバージョン制約とともに正しくスペルされているか確認する。
ステップ10: config.ymlの更新
inst/config.ymlを編集する:
新しいタイプのデフォルトと制約を追加する:
<type>:
grid:
default: [3, 3]
min: [2, 2]
max: [20, 20]
size:
default: [300, 300]
min: [100, 100]
max: [2000, 2000]
tabsize:
default: 20
min: 5
max: 50
# タイプ固有のパラメータをここに追加
期待結果: 設定が有効なYAMLである。デフォルト値がgenerate_puzzle()で使用されたとき動作するパズルを生成する。
失敗時: yaml::yaml.load_file("inst/config.yml")でYAMLを検証する。デフォルトのgridとsize値が適切なパズルを生成するか確認する(小さすぎず大きすぎず)。
ステップ11: Shinyアプリの拡張
inst/shiny-app/app.Rを編集する:
- UIタイプセレクターに新しいタイプを追加
- タイプ固有パラメータの条件付きUIパネルを追加
- サーバーサイドの生成ロジックを追加
期待結果: Shinyアプリのドロップダウンに新しいタイプが表示され、選択するとパズルが生成される。
失敗時: UIセレクターのchoices引数にタイプが追加されており、タイプ固有パラメータの条件付きパネルがconditionalPanel(condition = "input.type == '<type>'")を使用し、サーバーサイドハンドラーが正しいパラメータを渡しているか確認する。
ステップ12: テストスイートの作成
tests/testthat/test-<type>-puzzles.Rを作成する:
test_that("<type> puzzle generates correct piece count", { ... })
test_that("<type> puzzle respects seed reproducibility", { ... })
test_that("<type> adjacency returns valid neighbors", { ... })
test_that("<type> fusion merges pieces correctly", { ... })
test_that("<type> geom layer renders without error", { ... })
test_that("<type> SVG output is well-formed", { ... })
test_that("<type> config constraints are enforced", { ... })
タイプが外部パッケージを必要とする場合、テストをskip_if_not_installed()でラップする。
期待結果: すべてのテストがパスする。外部依存が欠落していない限りスキップはない。
失敗時: 各統合ポイントを個別にチェックする。最も一般的な問題はディスパッチケースの欠落である — grep -rn "switch\|valid_types" R/を実行してすべてのディスパッチ場所を見つける。
バリデーション
-
generate_puzzle(type = "<type>")が有効な出力を生成する - 10のすべての統合ポイントが正しく接続されている
-
devtools::test()が新しいテストでパスする -
devtools::check()が0エラー、0警告を返す - Shinyアプリが新しいタイプをレンダリングする
- 設定制約が強制される(最小/最大バリデーション)
- 隣接関係とフュージョンが正しく動作する
- ggpuzzle geomレイヤーがエラーなくレンダリングされる
-
devtools::document()が成功する(NAMESPACEが更新される)
よくある落とし穴
- ディスパッチケースの欠落: 10以上のファイルのうち1つを忘れるとサイレントな失敗や「unknown type」エラーが発生する
- 負の数でのstrsplit:
paste(a, b, sep = "-")で隣接キーを作成する際、負のピースラベルが"1--1"のようなキーを生成する。代わりに"|"セパレータを使用し、"\\|"で分割する - 出力に
cat()を使用: 常にcliパッケージのロギングラッパー(log_info、log_warnなど)を使用する - Collate順: DESCRIPTIONのCollateフィールドはアルファベット順または依存関係順でなければならない
- Config.yml形式: YAMLが有効か確認する。
yaml::yaml.load_file("inst/config.yml")でテストする
関連スキル
generate-puzzle— スキャフォールド後に新しいタイプをテストするrun-puzzle-tests— 統合を検証するための完全なテストスイートを実行するvalidate-piles-notation— 新しいタイプでフュージョンをテストするwrite-testthat-tests— テスト記述の一般的なパターンwrite-roxygen-docs— 新しいgeom関数のドキュメントを作成する
GitHub Repository
Related Skills
llamaguard
OtherLlamaGuard is Meta's 7-8B parameter model for moderating LLM inputs and outputs across six safety categories like violence and hate speech. It offers 94-95% accuracy and can be deployed using vLLM, Hugging Face, or Amazon SageMaker. Use this skill to easily integrate content filtering and safety guardrails into your AI applications.
cost-optimization
OtherThis Claude Skill helps developers optimize cloud costs through resource rightsizing, tagging strategies, and spending analysis. It provides a framework for reducing cloud expenses and implementing cost governance across AWS, Azure, and GCP. Use it when you need to analyze infrastructure costs, right-size resources, or meet budget constraints.
quantizing-models-bitsandbytes
OtherThis skill quantizes LLMs to 8-bit or 4-bit precision using bitsandbytes, achieving 50-75% memory reduction with minimal accuracy loss. It's ideal for running larger models on limited GPU memory or accelerating inference, supporting formats like INT8, NF4, and FP4. The skill integrates with HuggingFace Transformers and enables QLoRA training and 8-bit optimizers.
dispatching-parallel-agents
OtherThis Claude Skill dispatches multiple agents to investigate and fix 3+ independent problems concurrently. It is designed for scenarios involving unrelated failures that can be resolved without shared state or dependencies. The core capability is parallel problem-solving, assigning one agent per independent problem domain to maximize efficiency.
