.agents/skills/lorcana-test-generation/SKILL.md
Generate focused Lorcana card-behavior tests using the current multiplayer test engine and helper syntax, and write minimal engine repro tests when a card exposes a suspected runtime gap.
npx skillsauth add TheCardGoat/lorcana-engine lorcana-test-generationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Write focused Bun tests for Lorcana card behavior using the current engine helpers in packages/lorcana/lorcana-cards.
todo stubs as syntax references.missingImplementation, missingTests, or an empty ability list is not valid migration coverage.Use lorcana-find-card to find similar cards, and use them to guide test development.
Use @tcg/lorcana-engine/testing.
LorcanaMultiplayerTestEngine is the default for gameplay behavior, pending effects, chosen-player flows, response flows, bag triggers, songs, locations, and cross-turn duration checks.LorcanaTestEngine is only for narrow model or keyword checks that do not require gameplay flow.createMockCharacter(...) is appropriate when printed identity does not matter.import { describe, expect, it } from "bun:test";
import {
LorcanaMultiplayerTestEngine,
createMockCharacter,
} from "@tcg/lorcana-engine/testing";
deck is omitted, the harness injects 10 placeholder cards.deck: [] when the test must avoid hidden draws.CardInput.Test behavior only. Do not add metadata snapshots or metadata-only blocker tests.
lorcana-engine, prefer a minimal engine or simulator repro near the affected resolver, targeting, activation, or trigger code.should have correct stats and abilities.Use the narrowest helper that keeps the test readable.
expect(
testEngine.asPlayerOne().playCard(cardUnderTest, {
targets: [targetCard],
}),
).toBeSuccessfulCommand();
expect(
testEngine.asPlayerOne().playCardWithChoice(cardUnderTest, 0, {
targets: [targetCard],
}),
).toBeSuccessfulCommand();
expect(
testEngine.asPlayerOne().playCardForPlayer(cardUnderTest, PLAYER_TWO),
).toBeSuccessfulCommand();
expect(
testEngine.asPlayerOne().playCardWithDestinations(cardUnderTest, {
zone: "deck-top",
cards: [firstCard, secondCard, thirdCard],
}),
).toBeSuccessfulCommand();
expect(
testEngine.asPlayerOne().activateAbility(cardUnderTest, {
ability: "ABILITY NAME",
}),
).toBeSuccessfulCommand();
expect(
testEngine.asPlayerOne().activateAbility(cardUnderTest, {
ability: "ABILITY NAME",
targets: [targetCard],
}),
).toBeSuccessfulCommand();
expect(
testEngine.asPlayerOne().activateAbility(cardUnderTest, {
costs: {
discardCards: [cardToDiscard],
},
}),
).toBeSuccessfulCommand();
Use only the cost key the card actually needs, for example exertCharacters, discardCards, or banishItems.
expect(
testEngine.asPlayerOne().resolvePendingEffect(cardUnderTest, {
resolveOptional: true,
}),
).toBeSuccessfulCommand();
expect(
testEngine.asPlayerOne().resolvePendingEffect(cardUnderTest, {
namedCard: "Simba",
}),
).toBeSuccessfulCommand();
expect(testEngine.asPlayerTwo().resolveNextPending({ choiceIndex: 1 })).toBeSuccessfulCommand();
expect(testEngine.asPlayerTwo().respondWith(firstTarget, secondTarget)).toBeSuccessfulCommand();
expect(testEngine.asPlayerTwo().respondWithChoice(0)).toBeSuccessfulCommand();
const [bagEffect] = testEngine.asPlayerOne().getBagEffects();
expect(
testEngine.asPlayerOne().resolveBag(bagEffect!.id, {
resolveOptional: true,
}),
).toBeSuccessfulCommand();
const discardId = testEngine.findCardInstanceId(cardToRecover, "discard", "p1");
expect(
testEngine.asPlayerOne().respondWith(discardId),
).toBeSuccessfulCommand();
expect(testEngine.asPlayerOne().singSong(songCard, singerCard)).toBeSuccessfulCommand();
expect(
testEngine.asPlayerOne().playSongTogether(songCard, [singerA, singerB]),
).toBeSuccessfulCommand();
Prefer the matcher surface provided by @tcg/lorcana-engine/testing:
toBeSuccessfulCommand()toHaveZoneCounts({ hand, deck, play, inkwell, discard })toHaveLore({ card, value })toHaveKeyword({ card, keyword, value? })toHaveRestriction({ card, restriction })toHaveGrantedAbility({ card, ability })toHaveCardsUnder({ card, count })toBeAtLocation({ card, location })toHavePendingEffectCount(n)toBeReady(card)toBeExerted(card)toBeInZone("deck" | "hand" | "play" | "discard" | "inkwell")Use runtime methods only when no matcher exists:
getCardZone(card)getZonesCardCount()getCard(card)getCardStrength(card)getCardLore(card)getDamage(card)getKeywordValue(card, "Resist")hasKeyword(card, keyword)getBagCount()getBagEffects()getPendingEffects()isExerted(card)getCardPublicFaceState(card, "inkwell")findCardInstanceId(card, zone, "p1" | "p2")getAuthoritativeState() for hidden-zone or exact-zone-key assertions that the player view cannot safely expressUse LorcanaTestEngine model helpers only for non-gameplay checks:
const testEngine = new LorcanaTestEngine({
play: [cardUnderTest],
});
expect(testEngine.getCardModel(cardUnderTest).hasBodyguard()).toBe(true);
playCardForPlayer(...); responder-side choices usually resolve with asPlayerTwo().resolveNextPending(...).upTo or zero-target branches, assert the legal minimal target bundle the runtime actually accepts rather than forcing dummy selections.findCardInstanceId(...).Use this when you want another agent to create or update a card test:
Use `lorcana-test-generation`.
Create or update the test for `<CARD_NAME>` in `packages/lorcana/lorcana-cards`.
Requirements:
- If the engine does support yet the card, we must expand the current engine to ensure it supports the card.
- Find the card definition first and use the matching active local test file if it exists.
- Use only current patterns from `@tcg/lorcana-engine/testing`.
- Write focused Bun behavior tests for the printed card text only.
- Prefer `LorcanaMultiplayerTestEngine` unless this is only a narrow keyword/model check.
- Use semantic matchers like `toHaveZoneCounts`, `toHaveLore`, `toHaveKeyword`, `toHaveRestriction`, `toHaveGrantedAbility`, `toBeAtLocation`, or `toHavePendingEffectCount` when possible.
- If the card has pending choices, chosen-player flow, bag triggers, or cross-turn duration, use the current helper APIs as appropriate.
- Run only the targeted test file after editing.
- Do not run repo-wide checks unless the targeted test passes and broader verification is clearly needed.
Success criteria:
- The test is active, uses current syntax, and proves the real printed behavior of the card.
- The targeted Bun test passes.
documentation
One-time setup that gathers design context for your project and saves it to your AI config file. Run once to establish persistent design guidelines.
tools
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.
development
--- name: review-pr-comments description: Systematically process GitHub pull request review feedback end-to-end: pick a target PR, identify unanswered or unresolved comments, handle each thread sequentially, implement required code updates, run repository verification checks, and post clear responses. Use when asked to review PR comments, resolve review threads, or address reviewer suggestions/questions. --- # Review PR Comments Process pull request feedback one thread at a time and finish wit
testing
Tone down overly bold or visually aggressive designs. Reduces intensity while maintaining design quality and impact.