Conversation
Adds WarHub.ArmouryModel.Source.Yaml with YamlBattleScribeReader.ReadSourceNode and YamlToXmlConverter, converting a YAML representation model into the XML shape expected by the existing BattleScribe deserializer. Covered by a single TDD test parsing a minimal gameSystem YAML document into a GamesystemNode. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eader Address code review findings on the YAML-to-XML converter: unguarded YAML node casts now throw YamlBattleScribeFormatException naming the offending key instead of raw InvalidCastException; invalid XML attribute/element names (spaces, colons like xml:lang) now throw the same instead of raw XmlException; scalar keys that are XML child text elements per the XSD (comment, description, customNotes, readme) are now emitted as child elements instead of attributes, fixing silent data loss on deserialize; removed a fabricated "associations" collection mapping with no XSD/model backing; dropped the unused FluentAssertions test dependency; sharpened the raw-string round-trip test with an unquoted ambiguous scalar; and noted that multi-document YAML streams are intentionally unsupported. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, strict mode) Add two new test cases to YamlBattleScribeReaderTests: - ReadSourceNode_preserves_modifiers_costs_constraints_and_text: validates that a real-world catalogue fragment with modifiers, conditionGroups, costs, constraints, profiles with $text characteristics, and comment are all correctly parsed and preserved. - ReadSourceNode_throws_on_unknown_collection_key: verifies that the reader strictly validates collection keys and throws YamlBattleScribeFormatException for unknown collections. Both tests pass; all 6 tests in the suite pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KcYK8hmTmXi8eLWpg9LGKJ
- Add StringComparison.Ordinal to Assert.Contains calls at lines 169 and 189 - Add missing assertions for condition group Type, constraint properties (Field, Value, Id), and entry Comment Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KcYK8hmTmXi8eLWpg9LGKJ
Add Wh40kDataIntegrationTests, a theory over every *.yaml file in WH40K11E_DATA (wh40k-11e on branch json-to-yaml), plus a sanity check that the loaded root has a non-empty Name and at least one populated child collection (catches loads that "succeed" but are structurally hollow due to a scalar key that silently missed the attribute/TextElementNames paths). Extend YamlToXmlConverter to handle two real-data collection keys absent from Catalogue.xsd: `associations` -> `association` (a documented NewRecruit extension, object-shaped items, added to ItemElementNames) and `alias` (a scalar-list Rule extension with no XSD precedent, handled via a new RepeatedTextElementNames mechanism since its items aren't mappings). Also extend ModifierKind (replace, ceil, floor) and ConditionGroupKind (count) - real-data enum literals missing from wham's hand-written enums and from the bundled (stale) Catalogue.xsd. Purely additive, no exhaustive switches over these enums exist within this build's dependency graph. All 47 wh40k-11e files load successfully; largest file (Imperium - Space Marines.yaml, 4.4 MB) loads in ~372ms. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds SetupFromFiles to SpecRosterEngineAdapter so specs/fixtures can drive the wham roster engine from real .cat/.gst (XML) or .yaml data files instead of inline protocol data, using YamlBattleScribeReader for YAML and DeserializeSourceNodeAuto for XML. Mirrors Setup's post-compilation wiring (_catalogCompilation, _coreEngine, _state) exactly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gine
TreatWarningsAsErrors only applies in Release, and CI never builds Release,
so 16 pre-existing CA1822 ("mark as static") errors in WhamRosterEngine.cs
went unnoticed until the muster CLI's Release publish hit them. Public
engine API members (used by SpecRosterEngineAdapter/EditorServices) are
suppressed narrowly via [SuppressMessage] (existing repo convention, see
Binder.cs) to preserve their instance-based signatures; the one private
helper that didn't touch instance state is marked static.
Fixing WhamRosterEngine.cs exposed 4 further Release-only analyzer errors
in RosterEngine.Spec's internal StateMapper (previously masked because the
project it depends on failed to build first): two more CA1822 statics, one
CA1859 parameter-type tightening, and one CA1305 explicit IFormatProvider.
Mechanical modifier/suppression change only; no public API signatures
changed; behavior unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…taSource) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…upFromFiles parse errors Every_wh40k11e_file_loads now uses [Theory(SkipTestWithoutData = true)] so a clean CI run without WH40K11E_DATA skips the integration cases instead of hard-failing on empty MemberData. SpecRosterEngineAdapter.SetupFromFiles wraps per-file parsing so any parse failure (YAML or XML) is rethrown as an InvalidOperationException naming the offending file, with the original exception preserved as InnerException. Adds a regression test asserting the second (malformed) file's name appears in the thrown message. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Picks up the New Recruit console host + public Docker image publishing work (feat/muster-support), needed by Muster's engine adapter chain.
|
Landed as #325, rebased onto the roster-engine stack (#315–#322) rather than onto Two changes during the rebase:
Everything else — the YAML reader, |
What
Foundation work for the muster CI harness (golden-roster regression checks for data repos):
WarHub.ArmouryModel.Source.Yaml: reads YAML-serialized BattleScribe data (the BSData/wh40k-11e format) into the node model via a YAML→XML structural transform feeding the existing serializer. Scalars flow as raw strings (representation model — no typed-deserialization coercion; pinned by test), strict mode throws on unknown collection keys,$text→ element text, text-element keys (comment/description/customNotes/readme) emit child elements. Loads all 47 real wh40k-11e files (integration suite, gated byWH40K11E_DATAenv var, skips cleanly when unset).SetupFromFilesonSpecRosterEngineAdapter(XML + YAML by extension), enabling dataSource-backed conformance specs and muster fixtures; parse failures name the offending file.ModifierKind.Replace/Ceil/Floor,ConditionGroupKind.Count(withXmlEnumattrs → full serializer round-trip).-c Releasebuilds (CI builds Debug only, so these were invisible). Public API signatures unchanged (suppressed on public members, static-ified privates only).Known follow-ups (not in this PR)
associations/aliasYAML keys load but round-trip lossily (no model support; documented).entryLinks— real defect found by muster's pilot fixtures; filed separately with code-level analysis.Verification
Source.Yaml.Tests 54/54 (with data) / green-with-skips (without); RosterEngine.Spec.Tests 31/31; ConformanceTests 351/351 (baseline preserved); Release builds of all touched projects clean.
🤖 Generated with Claude Code
https://claude.ai/code/session_01KcYK8hmTmXi8eLWpg9LGKJ