Fix phantom "Important:" header stealing a taking-fire report's deadline
Turned out to be one bug, not two: "Answer by <time>" phrasing was
already covered by _TAKING_FIRE_TIME_RE ('before|by <time>'). The real
bug was the last-resort bare-"<Name>:" header fallback matching a
same-message "Important:" follow-up line as a brand new named entity
(nothing excluded common prose lead-ins), creating a bogus
Target#Important that stole the deadline into its own requested_time
instead of the real report's. Fixed with a blocklist on that fallback
rule (important/note/warning/attention/caution/alert/reminder/priority).
New regression test, 55 total passing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+16
-1
@@ -375,6 +375,17 @@ _NAMED_HEADER_RE = re.compile(rf"^{_TYPE_ID_FRAGMENT}\s*:?\s*(.*)$")
|
||||
# one), nothing else anchors this match, so an optional colon would
|
||||
# false-positive on an ordinary clue-continuation line's leading word.
|
||||
_BARE_NAME_HEADER_RE = re.compile(r"^([A-Za-z][A-Za-z0-9]*)\s*:\s*(.*)$")
|
||||
# Even requiring the colon isn't quite enough: a prose lead-in word right
|
||||
# before a genuinely useful follow-up line ("Important: TEAR Shell first,
|
||||
# then HE Shell.") false-positives the same way -- confirmed live against
|
||||
# a real taking-fire message, where "Important:" got read as a brand new
|
||||
# named entity ("Target#Important"), stealing the actual report's own
|
||||
# "Answer by <time>" deadline into that bogus entry instead of the real
|
||||
# one. None of these read as an actual thing being spotted/named, only
|
||||
# ever as a prose interjection.
|
||||
_BARE_NAME_HEADER_BLOCKLIST = {
|
||||
"important", "note", "warning", "attention", "caution", "alert", "reminder", "priority",
|
||||
}
|
||||
|
||||
# Ad-hoc enemy installations are named in plain English rather than given a
|
||||
# Type#N id ("Enemy Signal Station:", "Bearing 034 from Enemy Signal
|
||||
@@ -908,7 +919,11 @@ def parse_intel_blocks(text: str) -> list[dict]:
|
||||
# 'Target'), not a Reference Point, a named thing giving its own
|
||||
# clues is being spotted, not a fixed landmark spotters aim off
|
||||
# of, same reasoning as the "Target is at-" calibration line.
|
||||
bare_m = next((m for c in candidates if (m := _BARE_NAME_HEADER_RE.match(c))), None)
|
||||
bare_m = next(
|
||||
(m for c in candidates if (m := _BARE_NAME_HEADER_RE.match(c))
|
||||
and m.group(1).lower() not in _BARE_NAME_HEADER_BLOCKLIST),
|
||||
None,
|
||||
)
|
||||
if bare_m:
|
||||
flush()
|
||||
name = bare_m.group(1)
|
||||
|
||||
Reference in New Issue
Block a user