Skip to content

Docstrings: core effects and events - #95

Merged
mmacy merged 2 commits into
mainfrom
docs/api-ref-core-effects-events
Sep 14, 2026
Merged

Docstrings: core effects and events#95
mmacy merged 2 commits into
mainfrom
docs/api-ref-core-effects-events

Conversation

@mmacy

@mmacy mmacy commented Sep 14, 2026

Copy link
Copy Markdown
Owner

A reader who has only the published reference can now work the effects engine and the event log without opening the source. The effects module says up front who calls it (a session at every clock move, cast_spell when a cast lands, and you when you run the rules yourself), what a condition and a modifier are, and that nothing expires until you advance the clock through the ledger. Each Condition member says which rules turn on it and which spell cures it, each MODIFIER_KINDS entry says what combat does with it, and every ledger call says what it returns and when it returns nothing. In the events module, every event class says who emits it, when, which codes it can carry, and why its visibility is what it is, and every field and enum member has an attribute docstring so the rendered rows carry prose instead of bare names. Every example runs under the docs harness.

I corrected three docstrings the code disagreed with, all in src/osrlib/core/effects.py at the line numbers they had before this branch. The EffectsLedger.attach docstring at line 583 said (None, []) came back on a refresh, and a refresh returns the existing effect with an empty event list, so the text now separates the two None cases from the refresh case. The EffectDefinition.expiry docstring at line 476 said an expiry outcome resolves when the duration runs out without saying it runs after the ordinary ending; _expire drops the effect, emits the expiry event, removes the condition and modifiers, and dispatches on expiry last, and the field now states that order. The Condition class docstring at line 86 listed poisoned among the conditions the core rules consume alongside a set of others, which understated the rule that actually applies: grant_condition and EffectsLedger.attach refuse any condition a target's template lists in its defenses' condition_immunities, whichever condition it is, so the class docstring now states that rule once for every member and each member says what else reads it.

A first draft of this branch went the other way and called poisoned, charmed, and afraid vocabulary nothing reads. Review caught it and the second commit fixes it: many monster templates declare immunity to poisoned and to charmed, neutralize poison and remove fear cure two of the three, and the fear cure demands a save versus spells at +1 per caster level before it takes. The same commit documents the second DeathEvent emitter in deal_damage, which carries the permanent code after a hit point report and with no condition event; states that both morale exemptions share combat.morale.exempt and resolve opposite ways, so score is what tells them apart; and narrows the claim that HitPointsReportedEvent is the only event reporting hit points to the only one reporting a standing current and maximum.

Nothing is fenced no-run, and I left nothing undocumented.

I did not use the adaptations register anchor. Neither of these files mentions the register, and the anchor slug contains "pinned", which the vocabulary gate in the docs gates rejects inside a docstring, so the full URL is the form to use if a later batch needs it here.

https://claude.ai/code/session_01GL26QnA6dCrvUc3WmhzFSa

Every public member of osrlib.core.effects and osrlib.core.events now
answers what it does, why you would call it, what you need first, and
what to call next, and every pydantic field and enum member has an
attribute docstring so its rendered row is not a bare name. Examples run
under the docs harness.

Claude-Session: https://claude.ai/code/session_01GL26QnA6dCrvUc3WmhzFSa
The immunity gate in grant_condition and attach reads every condition, so
"nothing in the core rules reads it" was wrong for poisoned and charmed,
which many monster templates declare immunity to, and for afraid, which
remove fear cures behind a save. DeathEvent has a second emitter in
deal_damage with its own ordering. An expiry outcome runs after the
ordinary ending, not instead of it. The two morale exemptions share a
code and resolve opposite ways, and hit points are reported as a standing
total only by HitPointsReportedEvent.

Claude-Session: https://claude.ai/code/session_01GL26QnA6dCrvUc3WmhzFSa
@mmacy
mmacy merged commit c4feeae into main Sep 14, 2026
5 checks passed
@mmacy
mmacy deleted the docs/api-ref-core-effects-events branch September 14, 2026 06:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant