add-puzzle-type
关于
This Claude Skill scaffolds a new puzzle type across all 10+ integration points in the jigsawR package. It automates the creation of the core module, pipeline wiring, ggplot layers, configuration updates, Shiny app extensions, and a test suite. Use it when adding a completely new puzzle type to ensure no integration step is missed.
快速安装
Claude Code
推荐npx 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-type在 Claude Code 中复制并粘贴此命令以安装该技能
技能文档
Add Puzzle Type
Scaffold new puzzle type across pipeline integration points jigsawR.
Use When
- Add new puzzle type to pkg
- Follow 10-point pipeline checklist (CLAUDE.md)
- Nothing missed wiring new type end-to-end
In
- Required: New type name (lowercase, e.g.
"triangular") - Required: Geometry desc (piece shape/arrangement)
- Required: Needs external pkgs? (Suggests)
- Optional: Params beyond standard (grid, size, seed, tabsize, offset)
- Optional: Ref impl or algo source
Do
Step 1: Core Puzzle Module
Create R/<type>_puzzle.R:
#' Generate <type> puzzle pieces (internal)
#' @noRd
generate_<type>_pieces_internal <- function(params, seed) {
# 1. Initialize RNG state
# 2. Generate piece geometries
# 3. Build edge paths (SVG path data)
# 4. Compute adjacency
# 5. Return list: pieces, edges, adjacency, metadata
}
Follow pattern R/voronoi_puzzle.R or R/snic_puzzle.R.
→ Fn returns list: $pieces, $edges, $adjacency, $metadata.
If err: Compare return structure against generate_voronoi_pieces_internal() → missing elements or wrong types.
Step 2: Wire jigsawR_clean.R
Edit R/jigsawR_clean.R:
- Add
"<type>"tovalid_types - Type-specific param extraction
- Valid. logic type-specific constraints
- Filename prefix mapping (e.g.,
"<type>"->"<type>_")
# In valid_types
valid_types <- c("rectangular", "hexagonal", "concentric", "voronoi", "snic", "<type>")
→ generate_puzzle(type = "<type>") accepted, no "unknown type" err.
If err: Verify type string in valid_types exact, param extraction covers required type-specific args.
Step 3: Wire unified_piece_generation.R
Edit R/unified_piece_generation.R:
- Dispatch case
generate_pieces_internal() - Fusion handling if PILES notation
# In the switch/dispatch
"<type>" = generate_<type>_pieces_internal(params, seed)
→ Pieces generated on dispatch.
If err: Confirm dispatch string exact, generate_<type>_pieces_internal defined + exported.
Step 4: Wire piece_positioning.R
Edit R/piece_positioning.R:
Add positioning dispatch. Most use shared, some need custom.
→ apply_piece_positioning() handles new type no err, pieces at correct coords.
If err: Check if needs custom or reuse shared path. Add dispatch if default no apply.
Step 5: Wire unified_renderer.R
Edit R/unified_renderer.R:
- Render case
render_puzzle_svg() - Edge path fn:
get_<type>_edge_paths() - Piece name fn:
get_<type>_piece_name()
→ SVG out generated new type, correct outlines + edge paths.
If err: Verify get_<type>_edge_paths() returns valid SVG path, get_<type>_piece_name() unique IDs.
Step 6: Wire adjacency_api.R
Edit R/adjacency_api.R:
Neighbor dispatch → get_neighbors() + get_adjacency() work.
→ get_neighbors(result, piece_id) returns correct neighbors.
If err: Check dispatch returns correct structure. Test small grid, manually verify against geometry.
Step 7: ggpuzzle Geom Layer
Edit R/geom_puzzle.R:
geom_puzzle_<type>() using make_puzzle_layer():
#' @export
geom_puzzle_<type> <- function(mapping = NULL, data = NULL, ...) {
make_puzzle_layer(type = "<type>", mapping = mapping, data = data, ...)
}
→ ggplot() + geom_puzzle_<type>(aes(...)) renders no err.
If err: Verify make_puzzle_layer() correct type, geom exported via @export.
Step 8: Stat Dispatch
Edit R/stat_puzzle.R:
- Type-specific default params
- Dispatch case
compute_panel()
→ Stat layer computes geometry, produces expected polygons.
If err: compute_panel() dispatch returns df w/ x, y, group, piece_id, defaults sensible.
Step 9: DESCRIPTION
Edit DESCRIPTION:
- New type in Description text
- New pkgs →
Suggests: Collate:include new R file (alphabetical)
→ devtools::document() succeeds. No NOTE unlisted files.
If err: New R file in Collate: alphabetical, new Suggests pkgs spelled correct w/ ver constraints.
Step 10: config.yml
Edit inst/config.yml:
Defaults + constraints:
<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
# Add type-specific params here
→ Config valid YAML. Defaults → working puzzle via generate_puzzle().
If err: Validate yaml::yaml.load_file("inst/config.yml"). Defaults sensible (not too small/large).
Step 11: Shiny App
Edit inst/shiny-app/app.R:
- Add type → UI selector
- Conditional UI panels type-specific params
- Server-side generation
→ Shiny shows new type, generates on select.
If err: Type in choices of selector, conditional panel conditionalPanel(condition = "input.type == '<type>'"), server passes correct params.
Step 12: Test Suite
Create 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", { ... })
External dep → skip_if_not_installed().
→ All pass. No skips unless dep missing.
If err: Check each point individually. Common: missing dispatch → grep -rn "switch\|valid_types" R/.
Check
-
generate_puzzle(type = "<type>")produces valid out - All 10 points wired
-
devtools::test()passes new tests -
devtools::check()→ 0 err, 0 warn - Shiny renders new type
- Config constraints enforced (min/max valid.)
- Adjacency + fusion work
- ggpuzzle geom renders no err
-
devtools::document()succeeds (NAMESPACE updated)
Traps
- Missing dispatch: One of 10+ files forgotten → silent fail or "unknown type"
- strsplit neg nums:
paste(a, b, sep = "-")→"1--1". Use"|"+ split"\\|". cat()for out: Alwaysclilogging wrappers (log_info,log_warn, etc.)- Collate order: alphabetical or dep-ordered
- config.yml format: Valid YAML; test
yaml::yaml.load_file("inst/config.yml")
→
generate-puzzle— test new type after scaffoldrun-puzzle-tests— full suite verify integrationvalidate-piles-notation— test fusion w/ new typewrite-testthat-tests— general test patternswrite-roxygen-docs— document new geom fn
GitHub 仓库
相关推荐技能
content-collections
元Content Collections 是一个 TypeScript 优先的构建工具,可将本地 Markdown/MDX 文件转换为类型安全的数据集合。它专为构建博客、文档站和内容密集型 Vite+React 应用而设计,提供基于 Zod 的自动模式验证。该工具涵盖从 Vite 插件配置、MDX 编译到生产环境部署的完整工作流。
polymarket
元这个Claude Skill为开发者提供完整的Polymarket预测市场开发支持,涵盖API调用、交易执行和市场数据分析。关键特性包括实时WebSocket数据流,可监控实时交易、订单和市场动态。开发者可用它构建预测市场应用、实施交易策略并集成实时市场预测功能。
creating-opencode-plugins
元该Skill帮助开发者创建OpenCode插件,用于接入命令、文件、LSP等25+种事件。它提供了插件结构、事件API规范和JavaScript/TypeScript实现模式,适合需要拦截操作、扩展功能或自定义事件处理的场景。开发者可通过它快速构建响应式模块来增强OpenCode AI助手的能力。
sglang
元SGLang是一个专为LLM设计的高性能推理框架,特别适用于需要结构化输出的场景。它通过RadixAttention前缀缓存技术,在处理JSON、正则表达式、工具调用等具有重复前缀的复杂工作流时,能实现极速生成。如果你正在构建智能体或多轮对话系统,并追求远超vLLM的推理性能,SGLang是理想选择。
