feat(alarms): say what each rule does, in Poracle's own words - #819
Merged
Conversation
PoracleNG renders a human-readable sentence for every tracking rule and
already returned it on every alarm-list read this site makes. Verified live
against 5.1.0 and 5.2.1: `GET /api/tracking/{type}/{id}` carries
`description` unconditionally, with no query parameter asked for, on all ten
types. Nothing new is fetched -- the field was being discarded at
PoracleJsonHelper.DeserializeList.
Backend: a nullable Description on the ten domain models, and one line in
ShouldStrip so it can never reach PoracleNG on a write. No tracking table has
a description column, and the field travelled three separate write paths --
SerializeToElement, RewriteRows, and PreserveUnmodelled, which was already
echoing the stored description back on every edit. Stripping it in ShouldStrip
covers all three. Deliberately not added to the twenty *Create/*Update DTOs:
the controllers bind those, and a client-stated description is not a thing.
Frontend: app-rule-summary at the foot of nine card types, under a hairline,
below the filter pills. The pills still read first -- they are the scan layer
across forty cards -- and the sentence is what you read once you have stopped
on one. Clamped to two lines with an expand control above 90 characters.
Two gates, both failing to nothing rather than to a placeholder: no
description (an older Poracle) renders no line, and a mismatch between the
alert language Poracle localises the sentence with and the display language
the pills follow renders no line either, so a card never mixes two languages.
The gate uses a new tri-state AlertLanguageService.resolved() rather than
selected(), which coerces to 'en' and would claim a match on a ja/ru/zh-cn
deployment.
Fort changes get the backend field but no card line: upstream still renders
'Fort updates: **pokestop** | distance: 5000m ["name"]' with a raw JSON array
in it, which reads worse than the change-type pills already on the card.
Tests pin both directions and the blast radius: the read carries it, an absent
field leaves it null, all three write paths drop it, every other property
survives the strip, and the collision reconciler stays blind to it (#553/#561
shapes). Watched the three strip tests fail before the ShouldStrip line went
in.
…riptions # Conflicts: # Applications/Pgan.PoracleWebNet.App/ClientApp/src/app/core/models/index.ts # Applications/Pgan.PoracleWebNet.App/ClientApp/src/app/modules/gyms/gym-list.component.ts # Applications/Pgan.PoracleWebNet.App/ClientApp/src/app/modules/max-battles/max-battle-list.component.ts # Applications/Pgan.PoracleWebNet.App/ClientApp/src/app/modules/nests/nest-list.component.ts # Applications/Pgan.PoracleWebNet.App/ClientApp/src/app/modules/pokemon/pokemon-list.component.ts # CHANGELOG.md
AlarmDescriptionPassthroughTests merged without a conflict but stopped compiling, then stopped asserting. Two things landed underneath it: MonsterService gained two constructor parameters -- the uid remapper from #805 and the costume capability from #804 -- and this file was not in either merge's conflict list, so nothing pointed at it. More subtly, #805 moved the pokemon update path from CreateAsync onto the uid-addressed UpdateByUidAsync. The test captured CreateAsync, so an edit wrote nothing into the slot and TryGetProperty threw on a default JsonElement rather than answering the question the test was asking. CaptureUpdates() hooks the call an edit actually makes, and says why in a comment so the next person moving a write path knows to look here.
hokiepokedad2
added a commit
that referenced
this pull request
Aug 24, 2026
…es (#822) #817 shipped the Pokéstop Events feature with its 29 new keys carrying the English text verbatim in da, de, es, fr, it, nl, pl, pt, pt-BR and sv. Key parity held, so nothing rendered as a raw key and no test caught it -- the page simply read in English beside a sidebar that did not. Terminology follows the INVASIONS.EVENT_TYPES block each locale already had, so the event names on the new page match the chips the invasion list has been showing all along. The one departure is French, where SHOWCASE was "Présentation"; Niantic's French term is "Vitrine", so both the existing chip and the new strings now use it. The other five features merged today (#815, #816, #818, #819, #821) were checked the same way and were translated properly. What still matches English in them is legitimately identical in that language: "Costume" in French and Italian, "Event" in German, "Area" in Italian, "Gym", "Pokestop", "Station", "15 min" and the countdown abbreviations.
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.
Closes #810. Merge last — it touches nine list components, seven of which #809 also touches.
A card gave you the species and a row of filter chips, and working out that a rule meant "Bulbasaur within 5 km, 90% IV or better, level 20 to 35" meant decoding the chips. Poracle already writes that sentence — the same wording its bot answers a
!pokemoncommand with — and was returning it on every read of this page, where it was thrown away.It now sits at the foot of each card under a hairline, below the chips, which still read first when you are scanning forty rules. Long ones clamp to two lines with a control to open them.
Two deliberate exclusions
Fort-change cards keep chips only. The sentence Poracle renders for them still has a raw JSON array in the middle of it, so it is worse than what it would replace.
The line appears only when the alert language matches the display language. Poracle localizes the description using the language it writes your alerts in; our chips follow the display language. Those can differ, and a card must never carry two languages at once. When they differ, or on a Poracle too old to send the field, the card is exactly what it was before.
Known limitation, worth a look in review
cleanRuleSummarystrips underscores and backticks anywhere in the string, not only where they are markdown. Nothing in production descriptions contains either today, but area names andoverride_location_labelvalues routinely do. If Poracle ever renders one of those into the sentence, the characters vanish silently. A tighter markdown-only rule would be safer; flagging rather than fixing since it needs a decision about what Poracle actually emits.Verification
Backend 2137 passed. Angular production build passes. Jest 105 suites / 1184 tests.