mirror of
https://github.com/MadsLorentzen/ai-job-search.git
synced 2026-09-17 00:26:26 +00:00
Step 3 gains rule 7: a posting whose stored posted_date is more than 30 days old at rank time carries a visible staleness marker with its age spelled out alongside the score - FLAG treatment like location and language, never an exclusion. No posted_date or null means no flag and no guess (never inferred from first_seen), and rule 6's defensive-parse rule applies wherever the stored value is compared. Age is re-derived each run and never persisted. Four new spec pins in test_rank_command.py, each verified to fail against the rule-less spec.
This commit is contained in:
@@ -419,5 +419,70 @@ class RankCommandSpec(unittest.TestCase):
|
||||
self.assertEqual(result.returncode, 0, f"lint_skills.py failed:\n{result.stdout}{result.stderr}")
|
||||
|
||||
|
||||
class PostedDateStalenessSpec(unittest.TestCase):
|
||||
"""Step 3 must consume the posted_date #391 persists.
|
||||
|
||||
The field exists because a 27-month-old posting ranked Strong Fit at
|
||||
position 1 of 133 (#390): the scoring agent noticed the age and wrote it
|
||||
into prose nothing reads. Persistence alone changes nothing - these pin
|
||||
that /rank actually derives a signal from the stored date, and that the
|
||||
signal keeps the schema's own boundary rules (flag never veto, no
|
||||
inference for absent values, rule 6's defensive parse).
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.step3 = _sections(COMMAND.read_text(encoding="utf-8")).get(
|
||||
"Step 3: Aggregate and Rank", ""
|
||||
)
|
||||
self.assertTrue(self.step3, "Step 3 section missing from rank.md")
|
||||
# The spec hard-wraps its prose; assertions match against collapsed
|
||||
# whitespace so a rewrap never fails a pin the text still honors.
|
||||
self.flat = " ".join(self.step3.split())
|
||||
|
||||
def test_step3_consumes_posted_date(self):
|
||||
self.assertIn(
|
||||
"`posted_date`",
|
||||
self.step3,
|
||||
"Step 3 never reads the posted_date /scrape persists, so a posting's "
|
||||
"age is stored but still invisible at rank time - the exact #390 gap",
|
||||
)
|
||||
self.assertIn(
|
||||
"⚠",
|
||||
self.step3.split("`posted_date`", 1)[1][:600],
|
||||
"the staleness rule must surface age as a visible ⚠ marker, like the "
|
||||
"location and language FLAG treatments",
|
||||
)
|
||||
|
||||
def test_staleness_is_a_flag_never_a_veto(self):
|
||||
self.assertRegex(
|
||||
self.flat,
|
||||
r"[Aa]ge is a signal, never a veto",
|
||||
"staleness must keep FLAG semantics - the #390 posting was 27 months "
|
||||
"old AND still live, so excluding on age would bury real openings",
|
||||
)
|
||||
|
||||
def test_staleness_never_inferred_for_absent_values(self):
|
||||
self.assertRegex(
|
||||
self.flat,
|
||||
r"no `posted_date`.*no flag and no guess",
|
||||
"entries predating the field must get no staleness signal - inferring "
|
||||
"age from first_seen would flag jobs on a date nobody posted",
|
||||
)
|
||||
self.assertIn(
|
||||
"`first_seen`",
|
||||
self.step3,
|
||||
"the rule must name first_seen as the forbidden inference source",
|
||||
)
|
||||
|
||||
def test_staleness_parses_posted_date_defensively(self):
|
||||
self.assertRegex(
|
||||
self.flat,
|
||||
r"defensive-parse rule applies wherever a stored `posted_date` is compared",
|
||||
"posted_date comparisons must carry rule 6's defensive-parse rule - the "
|
||||
"contract test pins the field's presence, not its format, and portals "
|
||||
"have shipped free-text shapes into stored date fields before",
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user