@@ -108,33 +108,27 @@ class TestValidAgenticPatternsConstant:
108108 """
109109
110110 def test_constant_is_exported (self ):
111- """The module exports VALID_AGENTIC_PATTERNS at the top level."""
112111 import tachi_parsers
113112
114113 assert hasattr (tachi_parsers , "VALID_AGENTIC_PATTERNS" )
115114
116115 def test_constant_has_eight_values (self ):
117- """The constant contains exactly 8 enum values per FR-003."""
118116 assert len (VALID_AGENTIC_PATTERNS ) == 8
119117
120118 def test_constant_has_exact_values (self ):
121- """The constant contains exactly the 8 canonical values (no drift)."""
122119 assert set (VALID_AGENTIC_PATTERNS ) == set (CANONICAL_PATTERN_VALUES )
123120
124121 def test_constant_values_are_all_lowercase (self ):
125- """All enum values are lowercase strings (canonical storage format)."""
126122 for value in VALID_AGENTIC_PATTERNS :
127123 assert isinstance (value , str )
128124 assert value == value .lower (), (
129125 f"VALID_AGENTIC_PATTERNS contains non-lowercase value: { value !r} "
130126 )
131127
132128 def test_constant_has_none_sentinel (self ):
133- """The constant contains the `none` sentinel for non-pattern findings."""
134129 assert "none" in VALID_AGENTIC_PATTERNS
135130
136131 def test_constant_has_multiple_sentinel (self ):
137- """The constant contains the `multiple` value for equal-rule matches."""
138132 assert "multiple" in VALID_AGENTIC_PATTERNS
139133
140134
@@ -147,7 +141,6 @@ class TestParseFindingPatternCanonicalValues:
147141
148142 @pytest .mark .parametrize ("canonical_value" , CANONICAL_PATTERN_VALUES )
149143 def test_canonical_value_returns_itself (self , canonical_value ):
150- """Each of the 8 canonical values normalizes to itself (identity)."""
151144 assert parse_finding_pattern (canonical_value ) == canonical_value
152145
153146
@@ -197,7 +190,6 @@ class TestParseFindingPatternBackwardCompat:
197190 """
198191
199192 def test_none_input_returns_none_string (self ):
200- """Python None input returns the string 'none' (not None)."""
201193 assert parse_finding_pattern (None ) == "none"
202194
203195 def test_empty_string_returns_none (self ):
@@ -210,32 +202,25 @@ def test_tabs_and_newlines_return_none(self):
210202 assert parse_finding_pattern ("\t \n \n " ) == "none"
211203
212204 def test_em_dash_unicode_escape_returns_none (self ):
213- """U+2014 em-dash via unicode escape — canonical FR-009 placeholder."""
214205 assert parse_finding_pattern ("\u2014 " ) == "none"
215206
216207 def test_em_dash_literal_returns_none (self ):
217- """U+2014 em-dash as a literal character in source returns 'none'."""
218208 assert parse_finding_pattern ("—" ) == "none"
219209
220210 def test_ascii_hyphen_returns_none (self ):
221- """ASCII hyphen-minus returns 'none' (editor-de-curling tolerance)."""
222211 assert parse_finding_pattern ("-" ) == "none"
223212
224213 def test_unrecognized_string_returns_none (self ):
225- """Unrecognized strings gracefully degrade to 'none' per FR-017."""
226214 assert parse_finding_pattern ("xyz" ) == "none"
227215
228216 def test_almost_canonical_typo_returns_none (self ):
229- """A near-miss typo is not silently corrected — returns 'none'."""
230217 assert parse_finding_pattern ("agent_collusio" ) == "none"
231218
232219 def test_non_string_integer_returns_none (self ):
233- """Non-string input (int) converts + fails validation → 'none'."""
234- # `str(0).strip().lower()` is "0", which is not in VALID_AGENTIC_PATTERNS
220+ # str(0).strip().lower() is "0", not a canonical value — hits the fall-through.
235221 assert parse_finding_pattern (0 ) == "none"
236222
237223 def test_em_dash_with_surrounding_whitespace_returns_none (self ):
238- """Em-dash with surrounding whitespace — strip before comparison."""
239224 assert parse_finding_pattern (" — " ) == "none"
240225
241226
@@ -252,11 +237,9 @@ def findings(self):
252237 return parse_threats_findings (content )
253238
254239 def test_all_findings_parsed (self , findings ):
255- """All 10 rows in the fixture table are parsed."""
256240 assert len (findings ) == 10
257241
258242 def test_every_finding_has_pattern_field (self , findings ):
259- """Every parsed finding has a populated ``agentic_pattern`` field."""
260243 for finding in findings :
261244 assert "agentic_pattern" in finding , (
262245 f"finding { finding .get ('id' )} missing agentic_pattern key"
@@ -265,7 +248,6 @@ def test_every_finding_has_pattern_field(self, findings):
265248 assert finding ["agentic_pattern" ] != ""
266249
267250 def test_every_pattern_is_canonical (self , findings ):
268- """Every emitted agentic_pattern is one of the 8 canonical values."""
269251 for finding in findings :
270252 assert finding ["agentic_pattern" ] in VALID_AGENTIC_PATTERNS , (
271253 f"finding { finding ['id' ]} has non-canonical pattern "
@@ -277,14 +259,12 @@ def test_trust_exploitation_mapped(self, findings):
277259 assert match ["agentic_pattern" ] == "trust_exploitation"
278260
279261 def test_agent_collusion_mapped_twice (self , findings ):
280- """Two separate rows with agent_collusion both parse correctly."""
281262 collusion = [f for f in findings if f ["agentic_pattern" ] == "agent_collusion" ]
282263 assert len (collusion ) == 2
283264 ids = {f ["id" ] for f in collusion }
284265 assert ids == {"AG-2" , "AGP-01" }
285266
286267 def test_em_dash_row_parses_as_none (self , findings ):
287- """The T-3 row with Pattern = `—` parses as `agentic_pattern: 'none'`."""
288268 em_dash_finding = next (f for f in findings if f ["id" ] == "T-3" )
289269 assert em_dash_finding ["agentic_pattern" ] == "none"
290270
@@ -309,7 +289,7 @@ def test_multiple_sentinel_mapped(self, findings):
309289 assert match ["agentic_pattern" ] == "multiple"
310290
311291 def test_explicit_none_value_mapped (self , findings ):
312- """ A literal 'none' value in the table parses as 'none' (not '—')."""
292+ # A literal 'none' string must parse to 'none' the same as the em-dash placeholder.
313293 match = next (f for f in findings if f ["id" ] == "AG-9" )
314294 assert match ["agentic_pattern" ] == "none"
315295
@@ -331,30 +311,24 @@ def findings(self):
331311 return parse_threats_findings (content )
332312
333313 def test_agentic_pattern_header_detected (self , findings ):
334- """The 'Agentic Pattern' spelling is detected (FR-009 canonical)."""
335314 # If header detection failed, every finding would default to 'none'.
336- # We have 4 non-none rows in this fixture, so at least one must be
337- # non-none for detection to have worked.
315+ # The fixture has 4 non-none rows, so any detection failure collapses this count.
338316 non_none = [f for f in findings if f ["agentic_pattern" ] != "none" ]
339317 assert len (non_none ) >= 4
340318
341319 def test_uppercase_value_canonicalized (self , findings ):
342- """AGENT_COLLUSION in a table cell normalizes to 'agent_collusion'."""
343320 match = next (f for f in findings if f ["id" ] == "AG-2" )
344321 assert match ["agentic_pattern" ] == "agent_collusion"
345322
346323 def test_title_case_value_canonicalized (self , findings ):
347- """Trust_Exploitation in a table cell normalizes to 'trust_exploitation'."""
348324 match = next (f for f in findings if f ["id" ] == "S-1" )
349325 assert match ["agentic_pattern" ] == "trust_exploitation"
350326
351327 def test_mixed_case_multiple_canonicalized (self , findings ):
352- """'Multiple' in a cell normalizes to 'multiple'."""
353328 match = next (f for f in findings if f ["id" ] == "AG-4" )
354329 assert match ["agentic_pattern" ] == "multiple"
355330
356331 def test_mixed_case_none_canonicalized (self , findings ):
357- """'None' in a cell normalizes to 'none'."""
358332 match = next (f for f in findings if f ["id" ] == "T-5" )
359333 assert match ["agentic_pattern" ] == "none"
360334
@@ -382,7 +356,6 @@ def test_all_findings_parsed(self, findings):
382356 assert len (findings ) == 3
383357
384358 def test_shifted_column_values_extracted (self , findings ):
385- """Pattern column values extract correctly even at the table end."""
386359 trust_exp = next (f for f in findings if f ["id" ] == "S-1" )
387360 assert trust_exp ["agentic_pattern" ] == "trust_exploitation"
388361
@@ -412,11 +385,9 @@ def findings(self):
412385 return parse_threats_findings (content )
413386
414387 def test_all_findings_parsed (self , findings ):
415- """Four rows in the fixture table are all parsed."""
416388 assert len (findings ) == 4
417389
418390 def test_every_finding_has_none_pattern (self , findings ):
419- """Every em-dash cell canonicalizes to 'none'."""
420391 for finding in findings :
421392 assert finding ["agentic_pattern" ] == "none" , (
422393 f"finding { finding ['id' ]} expected 'none' got "
@@ -442,33 +413,27 @@ def findings(self):
442413 return parse_threats_findings (content )
443414
444415 def test_all_findings_parsed (self , findings ):
445- """All 5 rows of the pre-Feature-142 fixture parse successfully."""
446416 assert len (findings ) == 5
447417
448418 def test_zero_parse_errors (self , findings ):
449- """Parsing produces findings (not an empty list on error)."""
450419 assert findings , "pre-Feature-142 fixture parsed to empty list"
451420
452421 def test_every_finding_has_pattern_key (self , findings ):
453- """Per FR-017, every finding has an ``agentic_pattern`` key populated."""
454422 for finding in findings :
455423 assert "agentic_pattern" in finding
456424
457425 def test_every_finding_defaults_to_none (self , findings ):
458- """Per FR-017, every finding defaults to 'none' (no Pattern column)."""
459426 for finding in findings :
460427 assert finding ["agentic_pattern" ] == "none" , (
461428 f"finding { finding ['id' ]} expected default 'none' got "
462429 f"{ finding ['agentic_pattern' ]!r} "
463430 )
464431
465432 def test_non_pattern_fields_still_parsed (self , findings ):
466- """Existing (non-pattern) fields remain correctly parsed post-FR-017."""
467433 first = findings [0 ]
468434 assert first ["id" ] == "S-1"
469435 assert first ["component" ] == "Auth Service"
470436 assert first ["risk_level" ] == "High"
471- # The mitigation field exercises the unchanged Section 7 extraction path
472437 assert "RS256" in first ["mitigation" ]
473438
474439 def test_no_warnings_emitted (self , capsys , findings ):
0 commit comments