A Swift package providing the Daggerheart model layer — the types that describe adversaries, environments, encounters, and content packs — as well as observable stores and CLI tools built on top of them.
The JSON field names and schema conventions used by this package are derived from
the community ecosystem. If you are proposing changes to existing field names,
the .dhpack JSON Schema, or the adversary/environment JSON format, please
consider compatibility with these sources:
| Project | Contribution |
|---|---|
| seansbox/daggerheart-srd | Primary source for adversaries.json / environments.json field names and SRD content in JSON |
| ly0va/beastvault | Community adversary YAML/JSON import schema used by Obsidian users |
| javalent/fantasy-statblocks | Statblock field naming conventions |
| daggersearch/daggerheart-data | Player-facing SRD content schema (classes, ancestries, items) |
Maintaining compatibility with these schemas is a goal so that content created for the broader community can be imported without transformation.
- Model types in
DaggerheartModels:Adversary,DaggerheartEnvironment,EncounterDefinition,DHPackContent, and related value types - Observable stores in
DaggerheartKit:Compendium,EncounterStore,EncounterSession,SessionRegistry - The
validate-dhpackCLI tool - The
.dhpackJSON Schema atschemas/dhpack.schema.json - Test coverage for all of the above
- SwiftUI views or other UI specific pieces.
- App-level lifecycle, navigation, or settings
- New content types not grounded in the Daggerheart SRD or
.dhpackformat
- Open an issue first. Discuss before writing code.
- A human must be the proposer. AI-generated feature proposals without a human author will not be considered.
- For behavioral changes to
DHPackContentor the.dhpackJSON Schema, explain compatibility impact — existing pack files should continue to decode correctly.
- Language: Swift 6.2,
.swiftLanguageMode(.v6) DaggerheartModelstarget: Foundation-only. Noimport Observation,import AppKit,import UIKit, or any other Apple-platform-only framework. Code in this target must compile and run on Linux.DaggerheartKittarget: Apple-platform@Observablestores. Usesimport Observationandimport DaggerheartModels.MemberImportVisibilityis active. Every file must explicitly import the module that defines the types it uses.import DaggerheartKitdoes not makeAdversaryvisible — addimport DaggerheartModelstoo.- No force-unwrap anywhere in source or test code.
- Access control:
publicon all exported types and their stored properties. - Naming: use Daggerheart game terms as-is (
hp,stress,thresholds).
This project uses swift-format (the built-in Swift toolchain formatter).
The .swift-format file at the project root is the canonical configuration.
Run before every commit:
./Scripts/format.shPRs with formatting violations will be asked to reformat before review.
Tests use Swift Testing (import Testing), not XCTest.
# Run all tests
swift test
# Linux-safe model tests (what CI runs)
swift test --filter DaggerheartModelsTestsGuidelines:
- Write a failing test first — red before green.
- Tests that use
@Observablestores or Apple-only APIs belong inDaggerheartKitTests. - Tests that should also run on Linux belong in
DaggerheartModelsTests. Keep them free ofCompendium,EncounterStore, and other Apple-only types. - Place JSON fixtures in
Tests/DaggerheartModelsTests/Fixtures/and access them viaBundle.module.url(forResource:withExtension:subdirectory: "Fixtures").
- Link to an issue. Every PR must reference the issue it addresses.
- Human author required. AI-generated code is permitted; the PR author and at least one reviewer must be human.
- Tests required. New behavior without tests will not be merged.
- swift-format clean. Run
./Scripts/format.shbefore pushing. - Linux CI must pass. The
DaggerheartModelsTestssuite runs on Linux in CI — do not introduce Linux-incompatible code into theDaggerheartModelstarget.