Skip to content

Fix manasight/manasight-parser#221: emit ChoiceResult / LinkInfo annotation details#222

Merged
timc-enthrall merged 3 commits into
mainfrom
issue/221-choiceresult-linkinfo-annotations
Jun 15, 2026
Merged

Fix manasight/manasight-parser#221: emit ChoiceResult / LinkInfo annotation details#222
timc-enthrall merged 3 commits into
mainfrom
issue/221-choiceresult-linkinfo-annotations

Conversation

@timc-enthrall

Copy link
Copy Markdown
Member

Summary

  • Parser now extracts AnnotationType_ChoiceResult and AnnotationType_LinkInfo detail fields instead of dropping them at the no-op catch-all, so "name a card" choices and their link metadata reach the desktop.

Changes Made

  • Added ANNOTATION_TYPE_CHOICE_RESULT / ANNOTATION_TYPE_LINK_INFO consts and match arms in add_type_specific_fields.
  • Added add_choice_result_fields / add_link_info_fields extractors (permissive, mirroring add_designation_fields — generic per-domain emit, no special-casing CardName).
  • Emitted fields — ChoiceResult: choice_value (always), choice_domain, choice_sentiment; LinkInfo: choose_link_type, source_ability_grp_id, link_type.
  • Updated the extract_annotations doc-comment to document both new types.

Testing

  • New mod choice_result_extraction (3 tests: Domain=5, value-only, Domain=13 CardName live capture shape) and mod link_info_extraction (2 tests: ChooseLinkType="Type" with sourceAbilityGRPID + LinkType; ChooseLinkType="CardName" minimal case).
  • All tests passing; lint clean; formatted.
  • Coverage estimate: Δ ≈ +5 tests, ~30 new tested LOC vs ~30 new production LOC — net neutral to slight positive on coverage ratio.

Stacked PR

Base: main — single PR, no stack.

Closes #221

🤖 Generated with Claude Code

@timc-enthrall

Copy link
Copy Markdown
Member Author

Code review

Found 1 issue:

  1. Missing edge-case test coverage for the two new permissive extractors. add_choice_result_fields falls back to choice_value: 0 via unwrap_or(0) when Choice_Value is absent, but no test exercises that absent-value fallback path. Likewise add_link_info_fields can emit zero type-specific fields when all three detail keys are absent, and that all-keys-absent case is untested. The repo CLAUDE.md testing policy requires "New/updated tests for every code change" and "Test behavior, not implementation" — the permissive fallback behavior is new and should be locked in. (CLAUDE.md says "New/updated tests for every code change")

/// variants pass through cleanly with whatever fields they happen to carry.
fn add_choice_result_fields(
obj: &mut serde_json::Map<String, serde_json::Value>,
details: &[serde_json::Value],
) {
obj.insert(
"choice_value".into(),
serde_json::json!(detail_int(details, "Choice_Value").unwrap_or(0)),
);
if let Some(d) = detail_int(details, "Choice_Domain") {
obj.insert("choice_domain".into(), serde_json::json!(d));
}
if let Some(s) = detail_int(details, "Choice_Sentiment") {
obj.insert("choice_sentiment".into(), serde_json::json!(s));
}
}
/// Adds `LinkInfo` fields to an annotation result.
///
/// Conditionally emits `choose_link_type`, `source_ability_grp_id`, and
/// `link_type` when found in `details`.
///
/// The implementation is intentionally permissive: every key is looked up
/// unconditionally via the existing `detail_str` / `detail_int` helpers and
/// inserted only when found. Never branches on the `ChooseLinkType` value —
/// undocumented variants pass through cleanly with whatever fields they carry.
fn add_link_info_fields(
obj: &mut serde_json::Map<String, serde_json::Value>,
details: &[serde_json::Value],
) {
if let Some(t) = detail_str(details, "ChooseLinkType") {
obj.insert("choose_link_type".into(), serde_json::json!(t));
}
if let Some(g) = detail_int(details, "sourceAbilityGRPID") {
obj.insert("source_ability_grp_id".into(), serde_json::json!(g));
}
if let Some(lt) = detail_int(details, "LinkType") {
obj.insert("link_type".into(), serde_json::json!(lt));
}
}

The new test modules cover present-key cases but not the absent-key fallbacks:

mod choice_result_extraction {
use super::*;

@timc-enthrall

Copy link
Copy Markdown
Member Author

Code review

Found 1 issue:

  1. Missing positive-path test for the new choice_sentiment conditional emit. add_choice_result_fields conditionally emits choice_sentiment when Choice_Sentiment is present in details, but every ChoiceResult test only asserts choice_sentiment is absent — no test exercises the present-and-emitted path. The sibling field choice_domain (same if let Some(...) pattern) has a positive test (test_choice_result_domain5_value_and_domain_emitted), so this is a coverage gap relative to the file's own convention. The repo CLAUDE.md testing policy requires "New/updated tests for every code change" and "Test behavior, not implementation" — the present-path emit of choice_sentiment is new behavior that should be locked in. (CLAUDE.md says "New/updated tests for every code change")

Emit site (no positive-path test covers this branch):

}
if let Some(s) = detail_int(details, "Choice_Sentiment") {
obj.insert("choice_sentiment".into(), serde_json::json!(s));
}

Tests only ever assert absence:

assert_eq!(ann["choice_domain"], 5);
// choice_sentiment absent when not in details.
assert!(ann.get("choice_sentiment").is_none());
}

@timc-enthrall

Copy link
Copy Markdown
Member Author

Code review

No blocking issues found. Checked for bugs and CLAUDE.md/CONVENTIONS compliance across five independent passes (CLAUDE.md adherence, shallow bug scan, git-history context, prior-PR comments, code-comment compliance).

Both findings from the earlier review rounds are resolved:

  • absent-Choice_Value and LinkInfo all-keys-absent edge cases (iteration 2)
  • positive-path choice_sentiment emit test (iteration 3): test_choice_result_sentiment_emitted_when_present

One sub-threshold observation was scored below the confidence bar and filtered: the add_choice_result_fields doc-comment rationale doesn't spell out the unwrap_or(0) fallback. The behavior itself is correct, intentional house style (mirrors add_zone_transfer_fields / add_designation_fields), and is unit-tested (test_choice_result_absent_choice_value_defaults_to_zero).

@timc-enthrall timc-enthrall marked this pull request as ready for review June 15, 2026 00:21
timc-enthrall and others added 3 commits June 14, 2026 18:56
The GRE annotation types AnnotationType_ChoiceResult and AnnotationType_LinkInfo
were hitting the no-op catch-all arm in add_type_specific_fields, silently
discarding all choice details (Choice_Value, Choice_Domain, ChooseLinkType, etc.).
This meant "name a card" effects (Pithing Needle, Meddling Mage, Petrified Hamlet)
reached the desktop with base fields only — the chosen card name was lost.

Changes:
- Added ANNOTATION_TYPE_CHOICE_RESULT / ANNOTATION_TYPE_LINK_INFO consts.
- Added two match arms in add_type_specific_fields routing to the new extractors.
- Added add_choice_result_fields (always emits choice_value; conditionally emits
  choice_domain and choice_sentiment — permissive, no branching on domain value).
- Added add_link_info_fields (conditionally emits choose_link_type,
  source_ability_grp_id, link_type — permissive, no branching on link-type value).
- Updated extract_annotations doc-comment to document both new annotation types.
- Added mod choice_result_extraction (3 tests: Domain=5, value-only, Domain=13
  CardName live capture) and mod link_info_extraction (2 tests: Type+source+link,
  CardName-only) mirroring the existing mod designation_extraction test style.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add edge-case tests for the permissive ChoiceResult/LinkInfo extractors:
- ChoiceResult with absent Choice_Value -> choice_value falls back to 0, no domain/sentiment
- LinkInfo with all detail keys absent -> no type-specific fields emitted

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add positive-path test for the choice_sentiment conditional emit. Every
prior ChoiceResult test only asserted choice_sentiment absence; its sibling
optional field choice_domain had a positive (Domain=5) test, leaving the
symmetric choice_sentiment emit path uncovered. New test feeds a
Choice_Sentiment detail and asserts choice_sentiment is emitted alongside
choice_value/choice_domain.
@timc-enthrall timc-enthrall force-pushed the issue/221-choiceresult-linkinfo-annotations branch from 91feeb0 to b5044fb Compare June 15, 2026 01:56
@timc-enthrall timc-enthrall merged commit b3f4758 into main Jun 15, 2026
6 checks passed
@timc-enthrall timc-enthrall deleted the issue/221-choiceresult-linkinfo-annotations branch June 15, 2026 02:01
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.

Parser drops AnnotationType_ChoiceResult / LinkInfo details — "name a card" choices lost

1 participant