Agent-almanac add-puzzle-type
git clone https://github.com/pjt222/agent-almanac
T=$(mktemp -d) && git clone --depth=1 https://github.com/pjt222/agent-almanac "$T" && mkdir -p ~/.claude/skills && cp -r "$T/i18n/de/skills/add-puzzle-type" ~/.claude/skills/pjt222-agent-almanac-add-puzzle-type-fbeba4 && rm -rf "$T"
i18n/de/skills/add-puzzle-type/SKILL.mdPuzzletyp hinzufuegen
Einen neuen Puzzletyp ueber alle Pipeline-Integrationspunkte in jigsawR aufsetzen.
Wann verwenden
- Einen komplett neuen Puzzletyp zum Paket hinzufuegen
- Der etablierten Integrations-Checkliste folgen (CLAUDE.md 10-Punkte-Pipeline)
- Sicherstellen, dass nichts uebersehen wird, wenn ein neuer Typ End-to-End verdrahtet wird
Eingaben
- Erforderlich: Name des neuen Typs (Kleinbuchstaben, z.B.
)"triangular" - Erforderlich: Geometriebeschreibung (wie Teile geformt/angeordnet sind)
- Erforderlich: Ob der Typ externe Pakete benoetigt (zu Suggests hinzufuegen)
- Optional: Parameterliste ueber die Standard-Parameter hinaus (grid, size, seed, tabsize, offset)
- Optional: Referenzimplementierung oder Algorithmusquelle
Vorgehensweise
Schritt 1: Kern-Puzzlemodul erstellen
R/<type>_puzzle.R mit der internen Generierungsfunktion erstellen:
#' Generate <type> puzzle pieces (internal) #' @noRd generate_<type>_pieces_internal <- function(params, seed) { # 1. RNG-Zustand initialisieren # 2. Teilegeometrien generieren # 3. Kantenpfade erstellen (SVG-Pfaddaten) # 4. Adjazenz berechnen # 5. Liste zurueckgeben: pieces, edges, adjacency, metadata }
Dem Muster in
R/voronoi_puzzle.R oder R/snic_puzzle.R fuer die Struktur folgen.
Erwartet: Funktion gibt eine Liste mit
$pieces, $edges, $adjacency, $metadata zurueck.
Bei Fehler: Die Rueckgabestruktur mit
generate_voronoi_pieces_internal() vergleichen, um fehlende Listenelemente oder falsche Typen zu identifizieren.
Schritt 2: In jigsawR_clean.R verdrahten
R/jigsawR_clean.R bearbeiten:
zum"<type>"
-Vektor hinzufuegenvalid_types- Typspezifische Parameterextraktion im Params-Abschnitt hinzufuegen
- Validierungslogik fuer typspezifische Beschraenkungen hinzufuegen
- Dateinamenpraefixzuordnung hinzufuegen (z.B.
->"<type>"
)"<type>_"
# In valid_types valid_types <- c("rectangular", "hexagonal", "concentric", "voronoi", "snic", "<type>")
Erwartet:
generate_puzzle(type = "<type>") wird ohne "unknown type"-Fehler akzeptiert.
Bei Fehler: Sicherstellen, dass der Typ-String exakt wie geschrieben zu
valid_types hinzugefuegt wurde und dass die Parameterextraktion alle erforderlichen typspezifischen Argumente abdeckt.
Schritt 3: In unified_piece_generation.R verdrahten
R/unified_piece_generation.R bearbeiten:
- Dispatch-Fall in
hinzufuegengenerate_pieces_internal() - Fusionsbehandlung hinzufuegen, falls der Typ PILES-Notation unterstuetzt
# Im switch/dispatch "<type>" = generate_<type>_pieces_internal(params, seed)
Erwartet: Teile werden generiert, wenn der Typ dispatcht wird.
Bei Fehler: Bestaetigen, dass der Dispatch-Fall-String exakt mit dem Typnamen uebereinstimmt und dass
generate_<type>_pieces_internal definiert und aus dem Puzzlemodul exportiert ist.
Schritt 4: In piece_positioning.R verdrahten
R/piece_positioning.R bearbeiten:
Positionierungs-Dispatch fuer den neuen Typ hinzufuegen. Die meisten Typen verwenden gemeinsame Positionierungslogik, aber einige benoetigen benutzerdefinierte Behandlung.
Erwartet:
apply_piece_positioning() behandelt den neuen Typ ohne Fehler und Teile werden an korrekten Koordinaten platziert.
Bei Fehler: Pruefen, ob der neue Typ benutzerdefinierte Positionierungslogik benoetigt oder den gemeinsamen Positionierungspfad wiederverwenden kann. Einen Dispatch-Fall hinzufuegen, falls der Standardpfad nicht gilt.
Schritt 5: In unified_renderer.R verdrahten
R/unified_renderer.R bearbeiten:
- Rendering-Fall in
hinzufuegenrender_puzzle_svg() - Kantenpfadfunktion hinzufuegen:
get_<type>_edge_paths() - Teilenamenfunktion hinzufuegen:
get_<type>_piece_name()
Erwartet: SVG-Ausgabe wird fuer den neuen Typ mit korrekten Teileumrissen und Kantenpfaden generiert.
Bei Fehler: Sicherstellen, dass
get_<type>_edge_paths() gueltige SVG-Pfaddaten zurueckgibt und get_<type>_piece_name() eindeutige Bezeichner fuer jedes Teil erzeugt.
Schritt 6: In adjacency_api.R verdrahten
R/adjacency_api.R bearbeiten:
Nachbar-Dispatch hinzufuegen, damit
get_neighbors() und get_adjacency() fuer den neuen Typ funktionieren.
Erwartet:
get_neighbors(result, piece_id) gibt korrekte Nachbarn fuer jedes Teil im Puzzle zurueck.
Bei Fehler: Pruefen, ob der Adjazenz-Dispatch die korrekte Datenstruktur zurueckgibt. Mit einem kleinen Raster testen und Nachbarschaftsbeziehungen manuell gegen die Geometrie verifizieren.
Schritt 7: ggpuzzle Geom-Layer hinzufuegen
R/geom_puzzle.R bearbeiten:
geom_puzzle_<type>() unter Verwendung der make_puzzle_layer()-Factory erstellen:
#' @export geom_puzzle_<type> <- function(mapping = NULL, data = NULL, ...) { make_puzzle_layer(type = "<type>", mapping = mapping, data = data, ...) }
Erwartet:
ggplot() + geom_puzzle_<type>(aes(...)) rendert ohne Fehler.
Bei Fehler: Sicherstellen, dass
make_puzzle_layer() den korrekten Typ-String erhaelt und dass die Geom-Funktion im NAMESPACE ueber @export exportiert wird.
Schritt 8: Stat-Dispatch hinzufuegen
R/stat_puzzle.R bearbeiten:
- Typspezifische Standardparameter hinzufuegen
- Dispatch-Fall in
hinzufuegencompute_panel()
Erwartet: Der Stat-Layer berechnet die Puzzlegeometrie korrekt und erzeugt die erwartete Anzahl von Polygonen.
Bei Fehler: Pruefen, ob der
compute_panel()-Dispatch-Fall einen Data Frame mit den erforderlichen Spalten (x, y, group, piece_id) zurueckgibt und ob die Standardparameter fuer den neuen Typ sinnvoll sind.
Schritt 9: DESCRIPTION aktualisieren
DESCRIPTION bearbeiten:
- Neuen Typ zum Description-Feldtext hinzufuegen
- Neue Pakete zu
hinzufuegen (falls externe Abhaengigkeit)Suggests:
aktualisieren, um die neue R-Datei einzuschliessen (alphabetische Reihenfolge)Collate:
Erwartet:
devtools::document() ist erfolgreich. Kein NOTE ueber nicht aufgelistete Dateien.
Bei Fehler: Pruefen, ob die neue R-Datei im
Collate:-Feld in alphabetischer Reihenfolge aufgefuehrt ist und ob neue Suggests-Pakete korrekt mit Versionsbeschraenkungen geschrieben sind.
Schritt 10: config.yml aktualisieren
inst/config.yml bearbeiten:
Standards und Beschraenkungen fuer den neuen Typ hinzufuegen:
<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 # Typspezifische Parameter hier hinzufuegen
Erwartet: Konfiguration ist gueltiges YAML. Standardwerte erzeugen ein funktionierendes Puzzle bei Verwendung durch
generate_puzzle().
Bei Fehler: YAML mit
yaml::yaml.load_file("inst/config.yml") validieren. Sicherstellen, dass Standard-Grid- und Size-Werte ein sinnvolles Puzzle erzeugen (nicht zu klein oder zu gross).
Schritt 11: Shiny-App erweitern
inst/shiny-app/app.R bearbeiten:
- Den neuen Typ zum UI-Typ-Selektor hinzufuegen
- Bedingte UI-Panels fuer typspezifische Parameter hinzufuegen
- Serverseitige Generierungslogik hinzufuegen
Erwartet: Shiny-App zeigt den neuen Typ im Dropdown an und generiert Puzzles bei Auswahl.
Bei Fehler: Pruefen, ob der Typ zum
choices-Argument des UI-Selektors hinzugefuegt wurde, ob das bedingte Panel fuer typspezifische Parameter conditionalPanel(condition = "input.type == '<type>'") verwendet und ob der serverseitige Handler die korrekten Parameter uebergibt.
Schritt 12: Testsuite erstellen
tests/testthat/test-<type>-puzzles.R erstellen:
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", { ... })
Falls der Typ ein externes Paket benoetigt, Tests mit
skip_if_not_installed() umschliessen.
Erwartet: Alle Tests bestehen. Keine Skips, es sei denn, eine externe Abhaengigkeit fehlt.
Bei Fehler: Jeden Integrationspunkt einzeln pruefen. Das haeufigste Problem sind fehlende Dispatch-Faelle --
grep -rn "switch\|valid_types" R/ ausfuehren, um alle Dispatch-Stellen zu finden.
Validierung
-
erzeugt gueltige Ausgabegenerate_puzzle(type = "<type>") - Alle 10 Integrationspunkte sind korrekt verdrahtet
-
besteht mit neuen Testsdevtools::test() -
gibt 0 Fehler, 0 Warnungen zurueckdevtools::check() - Shiny-App rendert den neuen Typ
- Konfigurationsbeschraenkungen werden durchgesetzt (Min/Max-Validierung)
- Adjazenz und Fusion funktionieren korrekt
- ggpuzzle Geom-Layer rendert ohne Fehler
-
ist erfolgreich (NAMESPACE aktualisiert)devtools::document()
Haeufige Fehler
- Fehlender Dispatch-Fall: Das Vergessen einer der 10+ Dateien verursacht stilles Versagen oder "unknown type"-Fehler
- strsplit mit negativen Zahlen: Beim Erstellen von Adjazenz-Schluesseln mit
erzeugen negative Teile-Labels Schluessel wiepaste(a, b, sep = "-")
. Stattdessen"1--1"
als Trennzeichen verwenden und mit"|"
splitten."\\|" - Verwendung von
fuer Ausgabe: Immercat()
-Paket-Logging-Wrapper verwenden (cli
,log_info
, etc.)log_warn - Collate-Reihenfolge: Das DESCRIPTION Collate-Feld muss alphabetisch oder abhaengigkeitsgeordnet sein
- Config.yml-Format: Sicherstellen, dass YAML gueltig ist; mit
testenyaml::yaml.load_file("inst/config.yml")
Verwandte Skills
-- Den neuen Typ nach dem Aufsetzen testengenerate-puzzle
-- Die vollstaendige Testsuite zur Verifizierung der Integration ausfuehrenrun-puzzle-tests
-- Fusion mit dem neuen Typ testenvalidate-piles-notation
-- Allgemeine Muster zum Schreiben von Testswrite-testthat-tests
-- Die neue Geom-Funktion dokumentierenwrite-roxygen-docs