fix: model-scoped buff gate, released as 1.2.1 - #109
Open
wn-mitch wants to merge 2 commits into
Open
Conversation
…nits
Core rule 19.04: a rule that affects a single specified model only ever applies
to that model, even while that model is part of an attached unit. The buff layer
treated the DSL targets `self`/`bearer` exactly like `unit`, so every ability
pooled onto a combined unit from an attached member buffed the whole squad — an
attached Archon handed its personal 4+ invulnerable save to ten Kabalite
Warriors, understating their expected damage taken by a quarter.
Two defects had to be fixed together, because either half alone regresses:
- The translator now drops `self`/`bearer` effects whose buff source is
`abilityKind: "attached"`, reporting one `unsupported` diagnostic instead of
silently discarding them. Keyed on the source kind rather than on the DSL
condition, so it also covers the personal buffs that carry no `is-attached`
gate (Shadowfield, Rampart, Moment Shackle, The Emperor's Grace, …), and it
fires under both perspectives — a leader's personal keyword grant should not
ride the squad's weapons either. `abilityKind: "support"` is left ungated.
- 28 abilities were mis-authored `target: "self"` while their prose scopes to
the unit ("models in that unit have a 4+ invulnerable save"). They are now
`target: "unit"`, which both keeps their buff — the gate would otherwise have
deleted ten legitimate unit-wide invulnerable saves — and fixes the describer,
which had been rendering them as "this model has …". Three of them
(Shrouding, Trifold Path of Shadow, Shroud of Disease) also carried the
offensive `attack-restriction` shape for a defensive rule and are re-encoded
as `targeting-permission`.
Verified by sweeping every leader/bodyguard attachment pair before and after:
828 attached-source buff rows become 797, with no additions, every removal a
genuinely model-scoped personal buff, and no re-authored ability losing its buff.
TS, Python and Go each carry the gate and its tests; Rust has no buff-collection
port. Pinned cross-implementation by new `abilities-resolver` corpus cases in
both directions (drop and non-drop), SPEC_VERSION 86 -> 87.
Closes #105
wn-mitch
force-pushed
the
wnmitch/release-1.2.1
branch
from
July 27, 2026 14:24
ee941af to
58639eb
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Cuts 1.2.1 as a patch release carrying the model-scoped buff fix.
What's in it
#108 — core rule 19.04 model-scoped buff gate. Abilities that affect a single specified model no longer pool onto the whole squad when that model is part of an attached unit.
self/bearerbuffs are dropped from the combined unit when the buff source is an attached model, emitting anunsupporteddiagnostic rather than discarding silently, across TypeScript, Python, and Go. Alongside it, 28 abilities are re-authored where their prose genuinely scopes to the unit rather than the model — which also fixes the describer sentences those entries were rendering.SPEC_VERSION86 → 87, with newabilities-resolvercases pinning both directions: the drop, and the non-drop for genuinely unit-scoped rules.Why patch, not minor
Per
CLAUDE.md, minor is reserved for points/MFM data drops. This is a correction to existing behaviour, so it rides a patch.Scope
This release deliberately carries no terrain changes. The three open terrain PRs (#103, #104, #107) are all left open — #107's re-sourced geometry did not hold up on review and that work is being restarted, so none of it lands here.
Verification
just preflightgreen: TypeScript, Rust, Python and Go suites, conformance, the generated-artifact drift gate, and version lockstep at 1.2.1 acrosstools/package.json,crates/wh40kdc/Cargo.toml,python/src/wh40kdc/_version.py,go/version.goandCargo.lock.