CodeEvolver Memory
memory last updated at iteration number: 24
Run id: 20260615073201 Seed branch: codeevolver-20260615073201-main Seed architecture: DSPy ReAct Agent with ColBERT Retrieval over PhantomWiki Fictional QA Corpus
Overall Progress
- Iteration 0 (Seed Program): ~0.345 F1 (subsample baseline, measured at iteration 1)
- Iteration 1: 0.5152 F1 on valset (+49% from baseline); 0.497 F1 on subsample
- Iteration 2: 0.4754 F1 on valset (−7.7% from best); 0.4878 F1 on subsample (+7.4% over parent)
- Iteration 3: 0.5074 F1 on valset (−1.5% from best); 0.5574 F1 on subsample (+9.9% over parent). Built on iteration 1 (not 2).
- Iteration 4: REJECTED — subsample 0.5666 vs parent baseline 0.5921 on new seed (−4.4%). Valset never scored. Built on iteration 3.
- Iteration 5: 0.5425 F1 on valset (NEW BEST, +5.3% from previous best); 0.4800 F1 on subsample (+14.2% over parent 0.4207). Built on iteration 1 (not 3/4). Branch:
codeevolver-20260615073543-475dd6. - Iteration 6: 0.5530 F1 on valset (NEW BEST, +1.9% from previous best); 0.5826 F1 on subsample (+4.3% over parent 0.5586). Built on iteration 5. Branch:
codeevolver-20260615073543-7ea7e9. - Iteration 7: 0.5464 F1 on valset (−1.2% regression from best 0.5530); 0.5611 F1 on subsample (+2.8% over parent 0.5363). Built on iteration 6. Branch:
codeevolver-20260615073543-9293b4. Valset REGRESSED despite subsample gain. Best program remains iteration 6. - Iteration 8: 0.5839 F1 on valset (NEW BEST, +5.6% from previous best 0.5530); 0.5985 F1 on subsample (+7.9% over parent 0.5546). Built on iteration 6 (candidate 5). Branch:
codeevolver-20260615073543-781dad. Valset NEW BEST — largest single-step improvement since iteration 1. The structural DOB exact-match index was the key unlock. - Iteration 9: SKIPPED — coding agent never ran; two prompt experiments (MULTI-COUNT ITERATION + ATTRIBUTE FAN-OUT, then ATTRIBUTE FAN-OUT alone) were both reverted after subsample regressions of −5.8% and −6.8% vs parent 0.6633. Valset: never scored.
- Iteration 10: 0.5533 F1 on valset (−5.3% regression from best 0.5839); 0.5249 F1 on subsample (+34.5% over parent 0.3903). Built on iteration 1 (candidate 1). Branch:
codeevolver-20260615073543-17c6db. Two phases tried: (1) two-phase EntityFinder+AnswerComputer: −14.9% subsample (Phase 1 ambiguity for counting questions); (2) single-phase with all proven wins: +34.5% over parent. Valset is below best — partly because it branches from candidate 1 (not iteration 8's superior candidate 7 lineage). - Iteration 11: SKIPPED — coding agent never ran. Outcome reflection confirmed two-phase with Python-determined question_type was the right path forward, and recommended building on candidate 7. Valset: never scored.
- Iteration 12: 0.6417 F1 on valset (NEW BEST, +9.9% from previous best 0.5839); 0.7134 F1 on subsample (+2.1% over parent 0.6985). Built on iteration 8 (candidate 7). Branch:
codeevolver-20260615073543-4b676c. Two rounds: Round 1 full two-phase all types −13.4% subsample → rejected. Round 2 hybrid (two-phase only for count_pivot) +2.1% subsample → accepted, NEW BEST valset, largest single-step improvement since iteration 1. - Iteration 13: 0.6153 F1 on valset (−4.1% regression from best 0.6417); 0.7047 F1 on subsample (+1.6% over parent 0.6933). Built on iteration 12 (candidate 9). Branch:
codeevolver-20260615073543-785aac. Round 1 (hobby/occupation as ReAct LLM tools): −4.4% subsample → rejected. Round 2 (Python-level routing: simple anchor bypass for"does the person whose hobby/occupation is Y have?"+ ANCHOR HINT injection for complex chains): +1.6% subsample → accepted. Valset REGRESSED (0.6417→0.6153, −4.1%) despite subsample gain. Best program remains iteration 12, candidate 9. ANCHOR HINT for complex chains appears to be the culprit. - Iteration 14: REJECTED — subsample 0.7112 vs parent 0.7137 (−0.25%, within noise range). Valset: never scored. Built on iteration 13 (candidate 10). Branch:
codeevolver-20260615073543-74b3a9. Change: surgical removal of the ANCHOR HINT injection block for complex chain count_pivot questions (keeping simple anchor bypass and Phase 2 cap=30 unchanged). The trace confirms the ANCHOR HINT removal is beneficial: Ex 85/35 (farm manager complex chain) went from 0.25 → 0.83 (+0.58). The nominal subsample regression was driven entirely by stochastic single-phase entity failures (Ex 35/51/55 = second uncle of Rosina Robey, Frederic Koons, Miller siblings) on the UNMODIFIED code path. The rejection is likely over-conservative — the architectural change itself is correct. Best program remains iteration 12, candidate 9 (0.6417). - Iteration 15: 0.6343 F1 on valset (+1.9% from previous accepted valset 0.6153, −1.1% from all-time best 0.6417); 0.7447 F1 on subsample (+2.93% over parent 0.7154). Built on iteration 13 (candidate 10). Branch:
codeevolver-20260615073543-f280a2. Two rounds: Round 1 (structuredanchor_hintDSPy InputField in EntityFinderSig): −14.8% subsample → FAILED — DSPy InputField changes prompt structure for ALL calls through the module even when empty, causing widespread count_pivot regression. Round 2 (clean ANCHOR HINT freetext removal only, no new fields): +2.93% subsample → accepted (candidate 11). Valset partially recovered from the iteration 13 regression (0.6153→0.6343), but still 1.1% below best (0.6417). Ex 85 (farm manager complex chain) confirmed fixed at 0.833. Key round 1 lesson: DSPy InputFields are invasive — adding any new field to a Signature changes the LLM prompt for every call through that module. - Iteration 16: 0.6217 F1 on valset (−2.0% regression from iteration 15, −3.1% below all-time best 0.6417); 0.7137 F1 on subsample (+4.51% over parent 0.6829). Built on iteration 15 (candidate 11). Branch:
codeevolver-20260615073543-1b655b. Addedsearch_by_hobbyandsearch_by_occupationas Phase 1 (entity_finder) tools only; updatedEntityFinderSigdocstring OCCUPATION/HOBBY ANCHORS section to instruct Phase 1 to call these tools first. Specific wins: ex_id=13 (video editor complex chain: 0.22→0.77), ex_id=78 (sports therapist: 0.67→0.91), ex_id=31 (tea bag collecting: 0.33→0.57). Valset REGRESSED despite strong subsample gain (+4.51%). Best program remains iteration 12, candidate 9. Key failures: corpus/Prolog mismatch amplified by 100% anchor recall (exact index returns ALL hobby/occupation persons, including those outside Prolog's closed-world scope → spurious Phase 2 counts); Phase 1 budget exhaustion for 3+ hop kinship chains from anchor (ex_id=102: Phase 1 called search_by_hobby("gongoozling"), got all anchors, but exhausted max_iters=40 traversing to niece-of-great-granddaughter pivots → empty target_entities → single-phase fallback also fails → 0.0). - Iteration 17: REJECTED — subsample 0.7630 (parent, candidate 9) → 0.7176 (−6.0%). Valset: N/A. Built on iteration 12 (candidate 9, all-time best). Added
attribute_deepclassification (attribute questions with ≥2 "of the" occurrences and no "person whose" anchor) + newAttributeAnswerSigPhase 2 + newself.attribute_answerdspy.ReAct (max_iters=20) + dispatch inforward(). Round 1 (basic attribute_deep routing): 0.7630→0.7270 (−4.7%). Round 2 (added SIBLING CROSS-REFERENCE instruction to EntityFinderSig COMPLETENESS section): 0.7270→0.7176 (−6.0%). Primary motivation (Deon Gall occupation chain, gold=12) remained at 0.0 — Phase 1 returned same 3 wrong entities as single-phase (Round 1), then 8 completely wrong entities after Round 2. Best program remains iteration 12, candidate 9 (0.6417). Current live program after rejection reverts to candidate 9. - Iteration 18: 0.6526 F1 on valset (NEW BEST, +1.7% from previous best 0.6417); 0.7204 F1 on subsample (+6.5% over parent 0.6764). Built on iteration 12 (candidate 9). Branch:
codeevolver-20260615073543-c10f8d, candidate 13. Entity questions now route through Phase 1 (EntityFinderSig, question_type='entity') instead of single-phase PhantomWikiQA. EntityFinderSig docstring strengthened with one-hop-at-a-time guidance for 3+ hop chains. ex_id=12 (male cousin of great-grandchild of Adelaida Brice: 0.0→1.0), ex_id=35 (second uncle of Rosina Robey: 0.0→0.667 with over-inclusion of aunts). Still failing: ex_id=23 (Phase 1 returned empty→fallback 0.0), ex_id=80 (same 3/12 Deon Gall great-grandchildren), ex_id=89 and 90 (wrong traversal paths). Subsample question-type avg (14 entity: ~0.695, 10 attribute: ~0.789, 22 count_pivot: ~0.655, 4 count_answer: 0.75). - Iteration 19: 0.6021 F1 on valset (−7.7% regression from best 0.6526); 0.7073 F1 on subsample (+15.5% over parent 0.6123). Built on iteration 18 (candidate 13). Branch:
codeevolver-20260615073543-ebe82e, candidate 14. Added SINGULAR FORM ≠ UNIQUE note and GENDER QUALIFIER definitional clarification to EntityFinderSig docstring. Three rounds of edits; round 3 final (+15.5% subsample): gender qualifier changed from filter trigger phrase ("Include only entities that match the specified gender" → caused surname-confusion: returned 48 "Cousin"-surnamed entities) to purely definitional form ("grandfather = male grandparent; uncle = male sibling of parent; aunt = female..."). ex_id=54 (grandfather of brother of Douglass Libby: Phase 1 now returns only 2 male grandparents instead of all 4 → 1.0), ex_id=58 (sister-in-law of friend of friend: 0.182→0.889). Valset REGRESSED: 0.6526→0.6021 (−7.7%). Best program remains iteration 18, candidate 13. Subsample score by type: entity 13 ex avg=0.716, attribute 10 ex avg=0.729, count_pivot 23 ex avg=0.686, count_answer 4 ex avg=0.750. - Iteration 20: REJECTED — subsample 0.6802 vs parent baseline 0.7190 (−3.9%). Valset: N/A. Built on iteration 18 (candidate 13). Branch:
codeevolver-20260615073543-192490. Two rounds: Round 1 (entity_finder max_iters 40→50 + gender filter via 10-passage search_wiki, threshold 1.2): −3.6% subsample → REVERTED. Round 2 (gender filter only via first-passage self.retrieve(), threshold 1.5, max_iters kept at 40): −3.9% subsample → REJECTED. Critical new finding: callingself.retrieve()insideforward()outside of a DSPy ReAct module context causes systematic Phase 1 behavior changes — ex_id=35 (Rosina Robey second uncle: 1.0→0.0) and ex_id=55 (Miller first cousins once removed: 1.0→0.0) failed identically in both children, ruling out the ad-hoc-retrieval approach for gender filtering. Best program remains iteration 18, candidate 13 (0.6526). Current live program reverted to candidate 13. - Iteration 21: 0.6867 F1 on valset (NEW BEST, +5.2% from previous best 0.6526); 0.7154 F1 on subsample (+3.9% over parent 0.6883). Built on iteration 18 (candidate 13). Branch:
codeevolver-20260615073543-c7abb8, candidate 15. Four additive docstring additions tophantomwiki_module.py(direct Edit, no coding agent): (1) RECIPROCAL COUSINHOOD in EntityFinderSig entity block — multiple grandchildren of X are mutual first cousins; (2) DOB/ATTRIBUTE MULTI-ANCHOR EXPANSION in EntityFinderSig entity block — traverse kinship chain from EACH of N anchors; (3) HOP-BY-HOP TRAVERSAL in EntityFinderSig count_pivot block — forbids compound-phrase searches, requires step-by-step; (4) FINDING ANCESTORS OF THE PIVOT in CountComputerSig RULES — search pivot's own article for parent names, then hop upward. Key win: ex_id=81 (cousin of grandchild of Eldon Ridenour: 0.333→1.0, reciprocal cousinhood definitively fixed). ex_id=30, 26, 40 also fixed. Persistent failures: ex_id=65 (Geraldine Ruch hobby contamination: 0.000, 21st+ consecutive), ex_id=96 (Deon Gall occupation: 0.000, 15th+ consecutive), ex_id=4 (DOB multi-anchor entity: Phase 1 budget exhaustion with 7+ anchors), ex_id=88 (company secretary grandfather ancestors: 0.250), ex_id=93 (DOB father-in-law: 0.143). NEW BEST valset. - Iteration 22: 0.6112 F1 on valset (−11.0% regression from best 0.6867); 0.6382 F1 on subsample (+2.8% over parent 0.6208). Built on iteration 21 (candidate 15). Branch:
codeevolver-20260615073543-dfc4b7, candidate 16. Two changes: (1) Separateentity_finder_entitymodule (max_iters=60) for entity questions — sameEntityFinderSigbut with 50% more budget; (2) Phase 2 cap 20→30 for count_pivot. Subsample accepted; valset is a major regression (−11.0%). The higher budget for entity Phase 1 did NOT fix the known hard cases (ex_id=93 0.143→0.167 marginally, ex_id=58 and ex_id=90 still 0.0) and likely caused valset regressions on entity questions that previously worked at max_iters=40. Best program remains iteration 21, candidate 15 (0.6867). Next iterations MUST branch from candidate 15, NOT candidate 16. - Iteration 23: 0.6625 F1 on valset (−3.5% regression from best 0.6867); 0.7392 F1 on subsample (+7.0% over parent 0.6906). Built on iteration 21 (candidate 15). Branch:
codeevolver-20260615073543-8feff1, candidate 17. Two changes: (1) Phase 1 output deduplication (order-preserving, seen-set before Phase 2 loop); (2) Phase 2 entity cap 20→50 for count_pivot. Subsample strongly accepted (+7.0%). Valset REGRESSED to 0.6625 (−3.5% from best). Cap=50 genuinely helps moderate-sized entity sets (ex_id=68 microbiology: 0.74→0.86; ex_id=75 DOB cousins: 0.50→0.80). But cap=50 hurts via corpus/Prolog mismatch for large populations: ex_id=91 (axe throwing, 130 entities): spurious '4','8' count values added by entities 21-50 → 0.800→0.667; ex_id=101 (clinical research associate): 48 of 50 Phase 2 calls return '0'; Prolog entities with counts {1,3,4,5,7} are NOT in top-50 ColBERT results — sequential top-N is systematically biased. Best program remains iteration 21, candidate 15 (0.6867). All next iterations MUST branch from candidate 15, NOT candidate 17. - Iteration 24: 0.6118 F1 on valset (−11.0% regression from best 0.6867, −7.6% from iteration 23); 0.6994 F1 on subsample (+8.2% over parent 0.6463). Built on iteration 21 (candidate 15). Branch:
codeevolver-20260615073543-62729b, candidate 18. Two changes: (1) Phase 1 output deduplication (same zero-cost improvement as iteration 23, ported from candidate 15); (2) Phase 2 random sampling — replacedentities[:20]withrandom.sample(entities, 20)using a deterministic per-question seed (random.Random(hash(question))). Rationale: sequential top-N was confirmed to be biased against Prolog entities in iteration 23. Subsample: +8.2% accepted (ex_id=36 0.0→1.0; ex_id=41 0.67→1.0 — structural count_pivot wins from random sampling). Valset major regression (−11.0%, 0.6867→0.6118). Stochastic gains on unchanged entity/attribute paths (ex_id=67, 11, 74) drove the subsample score but don't generalize. Structural count_pivot effect is slightly negative: 2 wins (ex_id=36, 41) vs 6 losses (ex_id=10, 18, 20, 29, 31, 63) in the subsample. Random sampling introduces too much per-question variance — the correct pivots are just as likely to be missed as they were with sequential top-20 for any individual question. Best program remains iteration 21, candidate 15 (0.6867). All next iterations MUST branch from candidate 15, NOT candidate 18.
Current Program Valset Score
0.6118 — iteration 24 ACCEPTED on subsample (parent 0.6463 → child 0.6994, +8.2%), but the valset scored 0.6118 — a major regression (−11.0%) from the all-time best 0.6867 and −7.6% from iteration 23. The current live program is candidate 18 (iteration 24), branch codeevolver-20260615073543-62729b. Changes: Phase 1 output deduplication + Phase 2 random sampling (random.sample(entities, 20) with per-question deterministic seed). The large subsample gain was driven by stochastic wins on unchanged entity/attribute paths (do not generalize) and a slightly net-negative structural count_pivot effect. Random sampling introduces too much per-question variance: correct pivots are missed just as often as spurious pivots. All next iterations should branch from candidate 15 (iteration 21), NOT candidate 18.
Best Program Valset Score
0.6867 (iteration 21, candidate 15). Branch: codeevolver-20260615073543-c7abb8. Previous best was 0.6526 (iteration 18, candidate 13).
Macro Approaches
Approach 1: Enriched DSPy Signature + Retrieval Parameter Tuning
- Approach: Replace bare
"question -> answer: list[str]"string signature with a properPhantomWikiQA(dspy.Signature)class that has a detailed docstring guiding multi-answer exhaustive search, explicit Do/Don't instructions, and clear field descriptions. Also increased k from 7 to 10. - Result: Subsample 0.345 → 0.497 (+44%); Valset 0.5152
- Observation: The bare signature caused two key failure modes: (1) single-entity assumption — model stopped after finding one answer, (2) single-branch traversal — model didn't explore sibling branches. A secondary issue was output format contamination where the model added person names alongside attribute answers (e.g., "journalist (Blake Mauldin)" instead of "journalist"). The enriched signature with explicit anti-contamination instructions fixed this. Valset score (0.5152) slightly exceeds subsample (0.497), suggesting the changes generalize well — no overfitting detected.
- Remaining opportunity: Still failing on (a) exact date-based lookups (ColBERT cannot match exact date strings), (b) "how many" questions that have multiple starting entities (each with a different count — model only computes one count), (c) very deep multi-hop chains (3+ hops with multiple branches), (d) questions returning empty lists from retrieval failure.
Approach 2: Workspace Scratchpad Tools (note_finding / recall_findings) + Mandatory Enumeration Rules
- Approach: Added
note_finding(label, content)andrecall_findings()as explicit ReAct tools backed by thread-local storage. Rewrote the signature docstring with three mandatory workspace usage rules (RECORD, ENUMERATE, CHECK) and a six-step process for "how many" questions with an example. Thread-local ensures concurrent calls don't share state; workspace reset on eachforward()call. - Result: Subsample 0.4543 → 0.4878 (+7.4%); Valset 0.5152 → 0.4754 (−7.7% from best). Net regression on valset despite subsample gain. The best program remains iteration 1.
- Observation: The workspace tools helped targeted multi-path "how many" questions on the subsample (e.g., great-grandparent-friend-count: 0.20→1.00; friend-of-friend sister-in-law: 0.50→1.00). But three failure modes caused valset regression: (1) Over-branching with type constraints — when the question has a downstream type filter ("mother of parent"), the model notes ALL parents (both M and F) via the workspace and explores wrong branches; the tool's "explore ALL entities" instruction overrides the semantic constraint. (2) False confidence from incomplete workspace —
recall_findings()confirms whatever is in the workspace without knowing if the search was complete; model locks in incomplete intermediate state and finalizes early. (3) Workspace overhead wastes tool budget — mandatory note_finding/recall_findings calls consume turn budget (max_iters=50) that could be spent on more searches, degrading complex question performance. The subsample gain reflected the specific set of multi-path "how many" examples in that seed; the valset has a broader distribution where the three failure modes collectively outweigh the gains. - Remaining opportunity: The core concept (tracking intermediate entity sets explicitly) is sound. The failure is in the implementation details: (a) mandatory vs. optional usage — making workspace calls suggested rather than required could preserve gains without wasting turns on simpler questions; (b) the workspace could be smarter about type constraints — if the downstream relation requires a filtered entity type, the model should only note compatible intermediates. The workspace idea should NOT be abandoned; it should be made lighter and constraint-aware.
Approach 3: Enriched BFS Docstring + Kinship Term Definitions + k=12 (Iteration 3 — Incremental)
- Approach: Built on iteration 1 (not 2). Replaced the 6-step HOW TO SEARCH guidance with a "BREADTH-FIRST ENUMERATION IS MANDATORY" section including a fully worked 7-step concrete example (Deon Gall great-grandchild traversal). Added a NON-STANDARD KINSHIP TERMS section defining second uncle, second cousin, first cousin once removed, great-uncle, grand-nephew with step-by-step derivation instructions. Added DATE-OF-BIRTH ANCHOR SEARCHES guidance. Added two new DO NOT bullets. Increased k from 10 to 12.
- Result: Subsample 0.5072 → 0.5574 (+9.9%); Valset 0.5152 → 0.5074 (−1.5% from best). Net small regression on valset despite large subsample gain.
- Observation: The BFS guidance genuinely helps multi-hop traversal on the subsample (Deon Gall great-grandchild: 0.29→0.92; sibling of cousin chain: 0.00→0.89; aunt questions: 0.67→1.00). However, the valset regressed slightly, consistent with the subsample gains being concentrated on complex multi-hop questions while the valset has a broader distribution including simpler questions. Key regressions: (a) Over-exploration on simple questions — subsample examples 65, 71, 83 (simple hobby or single-relative lookups) scored 0.00 after scoring 1.00 with iteration 1; BFS guidance makes the model enumerate unnecessarily even when there's 1 answer. (b) Intermediate entity answer contamination — for "great-uncle of great-uncle" and "second uncle chain" chains (trace entries 28, 34), the model returns hobbies/attributes of INTERMEDIATE entities rather than the final target; BFS reasoning increases exposure to intermediates' attributes during traversal. (c) Generation-level confusion — trace entry [4] (great-grandsons count): model correctly identified Frederic Koons as great-grandson but then searched for Frederic's children (one level too deep) and returned 0; trace entry [44] (cousin of great-grandchild): model returned grandchildren-generation entities as "cousins" instead of great-grandchildren-generation entities (one level too shallow). This is a systematic off-by-one generation error.
- Remaining opportunity: (1) Add a qualifier to BFS guidance: "Apply BFS only for chains with 2+ hops. For simple single-hop questions, 3–5 targeted searches suffice." (2) Add explicit "generation tracking" guidance: "When the question asks 'how many X does Y have?', identify exactly which generation level X refers to and count entities AT that level — not their children or parents." (3) The kinship term definitions are working for standard cases but multi-level kinship chains (great-uncle of great-uncle) cause answer contamination — need to add: "At each hop, track WHICH level you are at and only record the attribute of the FINAL target, not intermediates."
Approach 4: Second Aunt/Uncle Fix + Conditional "How Many" Multi-Count Guidance + NEVER ABANDON + Generation Level Tracking (Iteration 4 — Incremental, REJECTED)
- Approach: Built on iteration 3. Three changes were combined in the final submitted code (attempt 2): (1) Fixed second aunt/uncle definition from "parent's first cousin" (wrong) to "great-grandparent's sibling" (correct per PhantomWiki Prolog:
second_aunt(X, Y) :- parent(P, Y), great_aunt(X, P)); (2) Added "FOR HOW MANY QUESTIONS WITH MULTI-VALUED CHAINS" section with conditional guidance: enumerate ALL entities the chain resolves to and count X separately for EACH when the chain "may resolve to multiple entities"; (3) Added "NEVER ABANDON" rule (always return partial results); (4) Added "GENERATION LEVEL TRACKING" section (count at exact target level; report only final-hop attributes). An attempt 1 version used prescriptive Step A/B/C counting (score −11.2% vs parent). Attempt 2 softened to conditional language (score −4.4% vs parent). A third "final state" rolled back to parent + second-aunt/uncle fix only, but this was never evaluated (evals exhausted). The rejected score (0.5666) is from attempt 2; the committed code on the current branch is attempt 2. - Result: Subsample 0.5921 (parent, new seed) → 0.5666 (attempt 2, −4.4%). REJECTED. Valset: not scored. Current code on branch
codeevolver-20260615073543-616b80is attempt 2's state. - Observation: (a) Prescriptive counting instructions destabilize simple questions: attempt 1's mandatory Step A/B/C approach caused entries 0, 30, 41 (simple 1-count questions) to go from 1.0→0.0. Even attempt 2's conditional language still caused modest regression on some simple questions (entry 0 still 0.0 — model found 1 of 2 second aunts; entry 39 still 0.0). (b) Second aunt/uncle fix is directionally correct: entry 11 (uncles of second aunt, 1.0), entry 41 (second uncles of Juan Arevalo, 1.0). The definition "great-grandparent's sibling" is now applied correctly in traversal. However, entry 0 (second aunts of Alan Denney) still scores 0.0 — model found 1 of 2 second aunts, missing one great-grandparent line. Entry 39 (uncle of second aunt) scored 0.0 — model correctly identified the second aunt (Delpha Allison) but then returned second aunt's sibling (Werner Corrigan) as the uncle instead of searching for Delpha's parents' brothers. This is a generation confusion within the second aunt chain itself. (c) NEVER ABANDON section did not fix empty-answer failures: entries 9, 22 still returned [] despite the instruction, because the model genuinely explored only one branch and found nothing to report. (d) Generation Level Tracking section may have over-corrected: the instruction "count at the exact target level — not their children or parents" appears to have caused new regressions on some entries where the model second-guesses correct answers. (e) Multi-count fan-out failures are persistent and unchanged: entries 3, 5, 9, 15, 24, 27, 29, 32, 34 all return 1–2 answers when 5–12 are needed.
- Remaining opportunity: The second aunt/uncle definition fix (without the other additions) is high-confidence and should be re-applied cleanly on top of iteration 3. The remaining issue with second-aunt chains (entry 39: uncle of second aunt) is a traversal bug — model finds second aunt correctly but then applies uncle-of-self's-sibling instead of uncle-of-second-aunt's-parent. Explicitly adding: "To find the uncle of Person X, search for X's parents and then find THEIR brothers" would clarify this. The "how many" multi-count problem requires a more fundamentally different approach, not just prompt guidance.
Approach 6: Exact-Match DOB Index Tool — search_by_date_exact (Iteration 8 — CURRENT BEST)
- Approach: A code-level structural change that completely bypasses ColBERT for date-of-birth anchor questions. Pre-built a 494MB JSON file (
date_passages.json) mapping every YYYY-MM-DD date string to the full article texts of ALL people in the wiki born on that date (1M articles, 109K unique dates, up to 46 people per date). Added a module-level singleton_load_date_index()that lazy-loads and caches this index. Replaced thesearch_by_datetool (5-format ColBERT queries, proven ineffective in iteration 7) withsearch_by_date_exact(date_str)— an O(1) dict lookup that returns ALL matching articles guaranteed. Updated signature prompt to remove DOB workaround guidance and replace with "this tool returns EVERY person born on that date; read ALL returned articles and extract the relevant attribute for EACH." Side effect: the coding agent also weakened the ATTRIBUTE FAN-OUT guidance (from "5+ queries" to "2+ queries") when updating the prompt. - Result: Subsample 0.5546 → 0.5985 (+7.9%); Valset 0.5530 → 0.5839 (NEW BEST, +5.6%). Largest single-step valset improvement since iteration 1.
- Observation: (1) Structural code change outperforms prompt engineering for structural retrieval failures: Four semantic interventions (k=30, k=50, 5-format search_by_date, DOB guidance) all failed to break ColBERT's ceiling of 1–2 people per DOB. The exact index returns 100% recall in one O(1) call. Subsample trace confirms: Ex 11 (1/17 hobbies → 17/17), Ex 15 (2/7 occupations → 7/7), Ex 38 (1/9 occupations → 9/9). DOB-anchor questions avg 0.772 on subsample vs ~0.2 in prior iterations. (2) Cascading DOB fan-out still partially fails: Ex 46 "father-in-law of friend of person whose DOB is 0881-04-27" → gold=7, pred=1. The exact index finds all 7 people born on that date, but then finding ALL their friends and ALL their friends' fathers-in-law is still an incomplete fan-out. The DOB lookup problem is solved; the downstream multi-hop fan-out is not. (3) Coding agent weakened ATTRIBUTE FAN-OUT: When implementing the change, the coding agent merged the ATTRIBUTE FAN-OUT section into MULTI-ENTITY ENUMERATION and reduced "5+ varied queries" to "2+ queries". This caused regressions in hobby/occupation-anchored multi-count questions (Ex 13, 16, 37 all returned []). It also weakened multi-entity enumeration guidance, likely causing Ex 40 (female first cousin once removed of Sara Leyva) to regress from 1.0 (iteration 6) to 0.333 (iteration 8). (4) Multi-count fan-out persists: 9 of 19 failing examples (~47% of failures) are multi-count fan-out failures (Ex 4, 5, 8, 13, 16, 18, 37, 42, 44). Avg score on multi-count questions: 0.407 on subsample.
- Remaining opportunity: (1) Restore ATTRIBUTE FAN-OUT section (HIGH PRIORITY, LOW RISK — the coding agent weakened it as a side effect; re-adding the original "5+ queries" guidance should recover Ex 13, 16, 37 regressions without hurting DOB performance). (2) Restore full MULTI-ENTITY ENUMERATION guidance to recover Ex 40 regression. (3) Cascading DOB fan-out (multi-hop from DOB anchor) is partially improved but not solved. (4) Multi-count fan-out remains architecturally unsolved.
Approach 7: Two-Phase ReAct Architecture — EntityFinder → AnswerComputer (Iteration 10, Attempt 1 — FAILED)
- Approach: Replaced the single
PhantomWikiReActmodule with a two-module pipeline.entity_finder(ReAct, max_iters=35, all three tools) usesEntityFinderSigto output onlytarget_entities: list[str]— person names at the end of the traversal chain.answer_computer(ReAct, max_iters=20, search tools only) usesAnswerComputerSigwith a 3-case dispatch: entity questions → return target_entities as-is; attribute questions → look up attribute for each entity; counting questions → for EACH entity compute count independently.forward()sequences phase1 → phase2. Built on candidate 1 (clean base, not iteration 8's candidate 7). - Result: Subsample 0.3903 → 0.3318 (−14.9%). FAILED. Reverted within same iteration.
- Observation: The handoff between phases has a fundamental semantic ambiguity for counting questions. For "How many X does Y have?" questions: Phase 1 outputs X's (the counted entities, e.g., great-grandsons of Carlotta Freeland = ['Frederic Koons']). Phase 2 receives target_entities=['Frederic Koons'] and interprets them as the pivot Y's — so it asks "How many great-grandsons does Frederic Koons have?" (0) instead of returning count(target_entities)=1. The same signature cannot unambiguously encode BOTH "the Xs I found (please count them)" AND "the Ys I found (please count X for each Y)." This caused Ex 14, 22, 82 (simple counting questions) to drop from 1.0→0.0. Secondary issue: Phase 1 sometimes called
finish()with no arguments, dropping entities entirely. Additionally, both phases together consume more iteration budget than the single-phase (35+20=55 vs 50), with no compensating benefit for non-counting questions. - Remaining opportunity: The architecture is correct for ATTRIBUTE and ENTITY questions (no ambiguity there). To fix counting: add
question_type: stroutput field to Phase 1 (entity,attribute,count_pivot,count_answer). Thenforward()can handle each case: forcount_answer, return[str(len(target_entities))]directly; forcount_pivot, call Phase 2 to count X for each Y in target_entities. The challenge is building a reliable question_type classifier at the Phase 1 level — this may require its own ReAct-like reasoning or a separate classification step before Phase 1. A simpler fix: give Phase 1 an explicit instruction "For counting questions, output Y (the pivot entities), not X (the things being counted); include ais_counting: boolflag." Code inforward()can then either return len() directly or call Phase 2.
Approach 8: Single-Phase with All Proven Wins Restored (Iteration 10, Attempt 2 — ACCEPTED, valset 0.5533)
- Approach: After two-phase failed, reverted to single-phase
PhantomWikiReActon candidate 1 (iteration 1 base, same as iteration 10's parent). Kept all three tools (search_wiki k=10, search_wiki_broad k=30, search_by_date_exact exact-index). Restored all proven prompt wins from iterations 5-8: HOW MANY FORMAT RULE (with WRONG/RIGHT example), MULTI-ENTITY ENUMERATION (bilateral ancestor search, "at least 2 more follow-up searches"), ATTRIBUTE FAN-OUT (at least 5 different query phrasings for attribute-anchored questions), IMPLICIT RELATIONSHIPS traversal, NON-STANDARD KINSHIP TERMS (second aunt/uncle = great-grandparent's sibling), DATE-OF-BIRTH ANCHOR (use search_by_date_exact + tautological short-circuit), and DO NOT bullets. max_iters=50. - Result: Subsample 0.3903 → 0.5249 (+34.5%); Valset 0.5533 (−5.3% from best 0.5839). ACCEPTED but regression from best.
- Observation: (1) Valset regression despite strong subsample gain: The +34.5% subsample gain reflects the very low parent baseline (candidate 1: 0.3903), not genuine improvement over the best program. The valset (0.5533) is below both iteration 8 (0.5839) and iteration 6 (0.5530). The program contains the same tools as iteration 8 but was built on a different lineage (candidate 1 vs candidate 7), which likely explains the gap. (2) ATTRIBUTE FAN-OUT 5+ queries with broad search: Ex 26 (0.909) and Ex 47 (0.842) show the model successfully iterating over 20+ intermediate entities for attribute-anchor multi-count questions ("person whose hobby is microbiology" / "person whose occupation is biochemist"). However, it fails for rarer attributes like "financial controller" (Ex 14: pred=['2'], gold 9 values) and "crystals hobby" (Ex 42: pred=['0'], gold 9 values) — likely ColBERT cannot reliably retrieve all instances of rarer attributes even with 5+ query phrasings. (3) Over-enumeration false positive problem: The ATTRIBUTE FAN-OUT and MULTI-ENTITY ENUMERATION guidance causes the model to over-search on some simple questions: Ex 8 (pred=['1','2'], gold=['1'] — found extra false second aunt, computed extra count); Ex 46 (pred includes 2 wrong extra cousin entities). (4) Intermediate contamination persists: Ex 25, 27, 40, 45 — same questions fail exactly the same way as all prior iterations. (5) Multi-count fan-out improvement is partial: Multi-count works for common attributes (microbiology, biochemist) but not rare ones. (6) New observation — Ex 30: "cousins of male second cousin of Reinaldo Pettus" → pred=['0','0','0','0'], gold=['10','7','8']. Model correctly found 4 second cousins (bilateral traversal working!) but returned '0' cousin count for all of them. This is a retrieval failure at the final hop (ColBERT cannot enumerate all cousins of a given person), NOT a structural/counting failure. The traversal and counting loop are working; the retrieval tool is failing.
- Remaining opportunity: (1) Always branch from iteration 8's candidate 7 (best valset lineage), not candidate 1. The candidate 7 base likely has better generalization properties. (2) Investigate whether there's any difference between candidate 1 and candidate 7's programs (the seed-base may include subtly better tokenization/retrieval defaults). (3) The multi-count partial successes (Ex 26, 47) are promising — common-attribute fan-out is now working; rare-attribute fan-out is the remaining gap. A brute-force index of (attribute_type, attribute_value) → [person_list] analogous to the DOB index would fix this structurally.
Approach 9: Hybrid Two-Phase Architecture — Two-Phase ONLY for count_pivot, Single-Phase for All Other Types (Iteration 12 Round 2 — CURRENT BEST, valset 0.6417)
- Approach: Built on candidate 7 (iteration 8, best valset 0.5839). Added Python-level
_classify_question()function (deterministic lexical rules — no LLM classification) that routes each question to one of four types:count_pivot("how many … does the [CHAIN] have?"),count_answer("how many … does [NAME] have?"),attribute("what is/are/was/were"),entity(everything else). Forcount_pivotquestions: Phase 1 (EntityFinderSig, max_iters=40) finds all pivot entities; then Phase 2 (CountComputerSig, max_iters=15) is called ONCE PER PIVOT ENTITY to compute the count, guaranteeing per-entity counting and eliminating the enumerate-then-collapse failure mode. Forentity,attribute, andcount_answerquestions: the original single-phasePhantomWikiQAReAct (max_iters=50) is used directly, preserving existing strong performance. Fallback: if Phase 1 returns empty entities for a count_pivot question, the system falls back to single-phase. Round 1 (full two-phase for all types) was tried first and rejected (−13.4% subsample) because Phase 1 over-enumerated for attribute questions and corpus dead-ends caused cascades. - Result: Subsample 0.6985 → 0.7134 (+2.1%); Valset 0.5839 → 0.6417 (NEW BEST, +9.9%). Largest single-step valset improvement in the entire run.
- Observation: (1) Per-entity Phase 2 counting definitively solves enumerate-then-collapse for count_pivot: Ex 9 (iteration 12 reflection) went 0.364→0.714, Ex 13 0.222→0.545, Ex 39 0.400→0.857, Ex 63 0.0→0.571, Ex 78 0.286→0.800. The mechanism works: each pivot entity gets an independent search session with its own max_iters=15 budget. (2) The Python classifier correctly routes 30% of questions to the two-phase path (count_pivot type) and 70% to the single-phase. The deterministic routing eliminates the LLM classification errors that caused iteration 11's Phase 1 to misclassify "attribute" questions as "entity" and return entity names instead of attributes. (3) count_pivot performance by subsample (iteration 12 trace): avg 0.668 across 16 examples. Six reach 1.0 or near-1.0 (Ex 10, 40, 42, 49). Failures cluster into two patterns: Phase 1 under-enumeration (Ex 8, 9, 15 — finds too few pivots → missing distinct counts) and Phase 1 over-enumeration from corpus/Prolog mismatch (Ex 14, 20, 27, 43 — finds too many pivots → spurious counts). (4) Corpus/Prolog mismatch over-enumeration is a new failure mode: The text corpus has more people with certain attributes (occupation, hobby, DOB) than the Prolog knowledge graph used to generate gold answers. Phase 1 finds all corpus matches; the extra ones produce wrong counts that dilute the answer set's F1. Ex 20: found 4 great-grandfathers, gold has 2 — the other 2 are in the corpus but not in the Prolog reasoning chain. Ex 43: found ~20 clinical research associates (19 returning count=0, 1 returning count=2), gold has 7 distinct values — the corpus has far more people with this occupation than the Prolog used. (5) Phase 1 for attribute questions was the fatal flaw in Round 1: Ex 77 (reflection) shows search_by_date_exact returning 7 people for a DOB where Prolog has 1 → Phase 1 computes mother-in-law for all 7, producing 6 wrong answers. The hybrid correctly keeps attribute questions on the single-phase path where the model exercises its own judgment about which entities are relevant. (6) Subsample score by type (iteration 12 trace): entity=0.817, attribute=0.714, count_pivot=0.668, count_answer=0.333. count_answer is worst — 2/3 examples fail (Ex 0: corpus dead-end, Ex 6: undercounting). count_pivot is 3rd despite being the hybrid's target — Phase 1 reliability is the remaining bottleneck.
- Remaining opportunity: (1) Phase 1 under-enumeration for count_pivot: Phase 1 consistently finds fewer pivot entities than exist in the knowledge graph, especially for rare hobby/occupation anchors (Ex 9: stone collecting; Ex 15: tea bag collecting) and deep kinship chains (Ex 8: cousin of DOB person → great-grandmother). A pre-built hobby/occupation index (search_by_hobby, search_by_occupation, analogous to DOB index) would give 100% recall for attribute-anchor pivots, the same way the DOB index solved DOB-anchor recall. (2) Corpus/Prolog over-enumeration for count_pivot: Phase 1 finds too many corpus entities for common occupations/hobbies. Difficult to fix without constraining Phase 1's search. One heuristic: cap the entity list by confidence/frequency (e.g., only use entities that appear in >1 retrieval query result). (3) count_answer failures (Ex 0, 6) are single-phase failures for simple "how many does [NAME] have?" questions — the model undercounts because of corpus dead-ends (parents not in wiki). No clear fix without structural traversal guarantees. (4) Attribute fan-out still partial (Ex 3, 13, 41): deep kinship chains in attribute questions still produce incomplete or wrong attribute sets — the single-phase has the same traversal limitations as before.
Approach 11: ANCHOR HINT Removal — Surgical Revert for Complex Chain Count Pivot (Iteration 14 REJECTED → Iteration 15 ACCEPTED, valset 0.6343)
- Approach: Built on iteration 13 (candidate 10). Removed the ANCHOR HINT freetext injection block in
PhantomWikiReAct.forward()for complex chain count_pivot questions (theelsebranch ofis_simple_anchor). Previously, complex chains prepended up to 25 anchor person names as freetext[ANCHOR HINT: ...]to Phase 1's question input. After this change, complex chains pass the original question directly to Phase 1, allowing it to use its own ColBERT search strategy. Simple anchor bypass and Phase 2 entity cap=30 were retained unchanged. - Result (iteration 14): Subsample 0.7137 → 0.7112 (−0.25%, within noise). REJECTED.
- Result (iteration 15, Round 2): Subsample 0.7154 → 0.7447 (+2.93%). Valset 0.6153 → 0.6343 (ACCEPTED, candidate 11). Partial recovery from iteration 13 regression.
- Observation: The change is confirmed structurally correct. Iteration 14 rejection was over-conservative (noise). In iteration 15, with a different seed, the same change produced a clean +2.93% subsample gain. Ex 85 (farm manager complex chain) improved 0.600→0.833 after removal, consistent across both iteration 14 and 15 traces. The ANCHOR HINT freetext mechanism was the main culprit of the iteration 13 valset regression (−4.1%); its removal recovered about 60% of that regression (+1.9% valset). The remaining ~40% gap (0.6343 vs 0.6417) may be residual stochastic noise or a small structural regression from the simple anchor bypass mechanism introduced in iteration 13 (which is still in place). The lesson: freetext injection into Phase 1's question field corrupts its traversal strategy; structured data (if ever needed) must be passed without modifying the question text.
- Remaining opportunity: The 0.6417→0.6343 gap is small but worth closing. Adding Phase 1 tools (
search_by_hobby_exact,search_by_occupation_exact) as actual callable tools available to Phase 1 is the most promising next step — it would give Phase 1 complete anchor recall without injecting anything into the question.
Approach 12: DSPy InputField as Structured Anchor Data for Phase 1 (Iteration 15 Round 1 — CATASTROPHICALLY FAILED)
- Approach: Built on iteration 13 (candidate 10). Added
anchor_hint: str = dspy.InputField(...)toEntityFinderSigwith a detailed desc explaining how to use the comma-separated list of anchor names. Modifiedforward()to pass up to 10 anchor names from the hobby/occupation index via this field (instead of freetext injection). The ANCHOR HINT freetext prefix was removed (replaced by the structured field). Updated the OCCUPATION/HOBBY ANCHORS docstring to referenceanchor_hint. - Result: Subsample 0.7154 → 0.6097 (−14.8%). CATASTROPHIC FAILURE. Reverted within same iteration.
- Observation: DSPy InputFields are invasive by design. Adding any new InputField to a DSPy Signature changes the LLM prompt structure for EVERY call through that module, not just calls where the field is non-empty. Even passing
anchor_hint=""changes the overall prompt (adds the field name and desc to the context, shifts the model's attention, changes token positions of other fields). This caused widespread count_pivot regressions across ALL questions, not just hobby/occupation anchor cases. The approach is not "structurally wrong" in concept — passing anchor entities as structured metadata is sound — but the DSPy InputField implementation is the wrong mechanism. Critical insight to record: never add a new InputField to an existing Signature in production use unless it is strictly required for all call sites. DSPy has no concept of "optional" input fields that are invisible when empty. - Remaining opportunity: The anchor entity injection concept remains valid. Alternative implementations: (1) expose
search_by_hobby_exact/search_by_occupation_exactas actual callable TOOLS in Phase 1's tool set — Phase 1 calls them itself when it detects a hobby/occupation anchor, preserving its autonomous search strategy; (2) create a separateEntityFinderWithHintSigsignature with the anchor field, and route to it only when anchor names are available (keepingEntityFinderSigclean for the base case); (3) prepend anchor names via a different mechanism that doesn't change the Signature (e.g., a system prompt addition, or pre-calling a Phase-0 module). Option (1) is the most architecturally clean and should be tried next.
Approach 13: Exact Hobby/Occupation Index Tools Exposed to Phase 1 (EntityFinderSig) (Iteration 16 — VALSET REGRESSION despite subsample gain)
- Approach: Built on iteration 15 (candidate 11). Added
self.search_by_hobbyandself.search_by_occupationtoentity_finder's tools list (Phase 1 only — single-phasereacttools unchanged). UpdatedEntityFinderSigdocstring's OCCUPATION/HOBBY ANCHORS section to instruct Phase 1 to "FIRST callsearch_by_occupation("X")/search_by_hobby("X")" before falling back to ColBERT, and to "pick a representative sample (up to 20)" to traverse the kinship chain. No DSPy InputField modifications. Analogy tosearch_by_date_exact(iteration 8). - Result: Subsample 0.6829 → 0.7137 (+4.51%); Valset 0.6343 → 0.6217 (−2.0% regression). ACCEPTED on subsample but valset REGRESSED. Best program remains iteration 12.
- Observation: (1) Specific wins are real: ex_id=13 (video editor complex chain: 0.22→0.77), ex_id=78 (sports therapist: 0.67→0.91), ex_id=31 (tea bag collecting: 0.33→0.57). The exact tool correctly fires first in Phase 1 for hobby/occupation anchor questions — the structural change works as intended at the tool-invocation level. (2) Corpus/Prolog mismatch is amplified by 100% anchor recall: The exact index returns ALL hobby/occupation persons in the corpus. Before, ColBERT only found 1-3 per hobby/occupation (small mismatch). Now Phase 1 gets all of them and samples 30+ for Phase 2, including corpus persons not in the Prolog's closed-world. This generates spurious Phase 2 counts, diluting F1. Ex 63 (video editor, 799 trace steps, 31 Phase 2 calls) and ex_id=13 (video editor, 5/8 gold values recovered but many extra '0' counts polluting the prediction set) demonstrate this. (3) New failure mode confirmed — Phase 1 budget exhaustion on deep chains: ex_id=102 ("niece of great-granddaughter of gongoozling person") — Phase 1 correctly called
search_by_hobby("gongoozling"), but then tried to traverse a 3-hop kinship chain (anchor→great-granddaughter→niece) from potentially hundreds of anchor persons. Exhausted max_iters=40 without completing the traversal (ColBERT can't do compound kinship queries). Returned emptytarget_entities→ fell back to single-phase → also failed → 0.0 score. Before the exact tool, Phase 1 would have found 1-3 gongoozling anchors and traversed them only; now with 30+ anchors it tries too many and exhausts the budget. (4) Subsample/valset divergence: The subsample happened to contain specific hobby/occupation examples where the improvement clearly outweighed mismatch noise (ex_id=13, 78, 31 are well-targeted wins). The valset has a broader distribution with more cases where the mismatch and budget exhaustion hurt. (5) The DOB index analogy is imperfect:search_by_date_exactin iteration 8 was clean because (a) DOB is the direct pivot in DOB-anchor questions (no further kinship hop needed in Phase 1), and (b) the Prolog and corpus align well for DOBs. Hobby/occupation anchors require 1+ additional kinship hops to find pivots, and the corpus has far more hobby/occupation persons than the Prolog's closed-world scope. - Remaining opportunity: The core structural idea (exact anchor recall via pre-built index) is correct. The failure modes are addressable: (a) Python-level pre-sampling in
forward(): before calling Phase 1, look up anchor persons via the exact index in Python and pass only a random sample of N=10-15 to Phase 1 (instead of letting Phase 1 call the tool and get potentially hundreds). This would reduce corpus/Prolog mismatch while preserving Phase 1's kinship traversal. (b) Increase Phase 1 max_iters: from 40 to 60-80 to give more budget for deep kinship chain traversal from multiple anchor persons. (c) Limit tool output size: capsearch_by_hobby/search_by_occupationreturn to 20 entries max within the tool itself, and add explicit guidance "traverse the kinship chain for each anchor ONE HOP AT A TIME — do not attempt compound queries." (d) Extend simple anchor bypass to 2-hop patterns: The simple anchor bypass in Python already handles "does the person whose hobby/occupation is Y have?" (direct pivot). Extending to "does the [1-hop kinship] of person whose hobby/occupation is Y have?" would handle a large sub-class of complex chains in Python, freeing Phase 1 for harder cases. This approach was fundamentally unpromising in its iteration 16 implementation but is NOT fundamentally wrong — the implementation needs major refinement.
Approach 10: Python-Level Hobby/Occupation Index Routing — Simple Anchor Bypass + ANCHOR HINT (Iteration 13 — VALSET REGRESSION)
- Approach: Built on iteration 12 (candidate 9, best valset 0.6417). Extended the hybrid two-phase
forward()with Python-level hobby/occupation routing: (a) Simple anchor bypass — if count_pivot question matches"does the person whose hobby/occupation is Y have?"pattern (attribute holder IS the direct pivot), bypass Phase 1 entirely and use the pre-built attribute index to get up to 30 pivot entities for Phase 2 directly; (b) ANCHOR HINT injection — for complex chain count_pivot questions where the hobby/occupation anchor is NOT the direct pivot, inject an[ANCHOR HINT: The following people have hobby/occupation 'X': name1, name2, ...]prefix with up to 25 names into Phase 1's question input. Phase 2 entity cap increased from 20 to 30. Round 1 (exposing hobby/occupation as ReAct LLM tools) was tried first and rejected (−4.4% subsample) because LLMs used the tools on inappropriate question types. - Result: Subsample 0.6933 → 0.7047 (+1.6%); Valset 0.6417 → 0.6153 (−4.1% regression from best). ACCEPTED on subsample but valset REGRESSED. Best program remains iteration 12.
- Observation: (1) Simple anchor bypass is architecturally sound and should be kept: The "does the person whose hobby/occupation is Y have?" regex correctly identifies questions where the attribute holder is the direct pivot. This deterministic Python bypass is analogous to the DOB exact-match index — completely bypasses Phase 1's ColBERT limitation for this pattern. Subsample simple anchor examples (Ex 10, 33) maintained or improved. This component contributes a genuine structural improvement. (2) ANCHOR HINT injection is net negative on the valset: While it helped specific subsample examples (Ex 31: tea bag collecting complex chain: 0.0→0.75), the valset regressed −4.1% overall. The failure mechanism: Phase 1 receives a long freetext prefix of 25 anchor names and sometimes exhausts its iteration budget traversing from those names instead of using its own efficient ColBERT broad search. Ex 85 (farm manager: 0.727→0.25) is the canonical failure — Phase 1 reads 25 farm manager names and follows them regardless of query structure. On the full valset distribution, this disruption pattern outweighs gains from the few Ex-31-like cases. (3) LLM tool misuse is a confirmed architectural risk (Round 1 evidence): Exposing hobby/occupation lookup as ReAct tools caused −4.4% because the LLM invoked them on non-attribute-anchor questions. The general principle: LLMs cannot be reliably constrained to "only use tool X when pattern Y appears" — Python-level routing is safer. (4) Subsample vs valset divergence: +1.6% subsample vs −4.1% valset. The subsample's specific 50 examples happened to include Ex 31 (ANCHOR HINT winner) but not as many Ex-85-like cases (ANCHOR HINT losers). Do not trust small subsample gains when the mechanism is known to have a failure mode.
- Remaining opportunity: (1) Remove ANCHOR HINT injection for complex chains (HIGH PRIORITY, LOW RISK) — the simple anchor bypass is worth keeping; removing ANCHOR HINT should recover most of the −4.1% valset regression. After this fix, the program should score near or above 0.6417. (2) The Phase 1 under-recall problem for complex chain hobby/occupation questions (e.g., "how many X does the female cousin of the person whose hobby is Y have?") remains structurally unsolved. Alternative to ANCHOR HINT: pass anchor names as structured metadata rather than freetext prefix, or investigate whether a light "seed entity hint" mechanism can avoid confusing Phase 1's search trajectory. (3) Phase 2 entity cap increase to 30 is retained and low-risk; keep it.
Approach 15: Entity-Question Routing Through Phase 1 (EntityFinderSig) (Iteration 18 — NEW BEST valset 0.6526; Iteration 19 — Prompt Incremental, Valset REGRESSED)
- Approach: Built on candidate 9 (iteration 12, best valset 0.6417). Added
elif question_type == 'entity':branch inforward()that callsentity_finder(question=question, question_type='entity')and returnstarget_entitiesdirectly, with fallback to single-phase if Phase 1 returns empty. StrengthenedEntityFinderSigdocstring with explicit one-hop-at-a-time guidance for 3+ hop chains: "resolve EACH HOP SEPARATELY, enumerate ALL entities at EACH level, NEVER declare 'cannot be determined' — try ALL branches first, ENUMERATE ALL BRANCHES." No changes to count_pivot path, PhantomWikiQA, or count_answer routing. - Result (iteration 18): Subsample 0.6764 → 0.7204 (+6.5%); Valset 0.6417 → 0.6526 (NEW BEST, +1.7%). ACCEPTED, candidate 13.
- Observation (iteration 18): (1) Phase 1's focused entity-finding objective reduces premature termination for multi-hop entity chains: ex_id=12 (male cousin of great-grandchild of Adelaida Brice: 0.0→1.0) — single-phase had kinship level confusion, Phase 1's focused traversal resolved it. ex_id=35 (second uncle of Rosina Robey: 0.0→0.667) — Phase 1 found both gold uncles but also included gold second aunts (Mona Bickel, Pearl Keith) as false positives due to no gender filtering. (2) Phase 1 over-inclusion for gender-qualified questions: When a question asks for "uncle" or "male X", Phase 1 finds entities of the correct kinship level but doesn't filter by gender, producing F1=0.667 where 1.0 is achievable with post-processing. (3) Phase 1 under-enumeration for deep fan-out persists: ex_id=80 (great-grandchild of great-grandfather of Deon Gall) still returns same 3/12 entities as single-phase — the ColBERT recall ceiling is unchanged. ex_id=89 (female cousin of grandchild of great-grandchild of Forest Benner) returned entirely wrong entities. (4) Phase 1 budget ceiling (max_iters=40 < single-phase 50): ex_id=23 (great-grandmother of father-in-law of friend of Kermit Clapp) returned empty from Phase 1 and fell back to single-phase (same 0.0). The lower budget may be the bottleneck for very complex entity chains requiring many retrieval steps. (5) Non-regressive fallback mechanism works: all previously-passing entity questions maintained their scores via the fallback (if Phase 1 returns empty, single-phase is used). (6) Subsample entity avg improved to ~0.695 (14 examples), up from ~0.529 in iteration 14. Entity questions are no longer the weakest question type. (7) Stochastic regression on count_answer path: ex_id=14 (Carlotta Freeland great-grandson count — was 1.0 in iteration 15, now 0.0) on the unchanged code path. This is seed-driven noise, not a regression from the change.
- Iteration 19 extension (VALSET REGRESSION, −7.7%): Added SINGULAR FORM ≠ UNIQUE note and definitional GENDER QUALIFIER section to EntityFinderSig docstring (three rounds; round 3 final: +15.5% subsample over parent). Subsample 0.6123 → 0.7073. Valset 0.6526 → 0.6021 (−7.7%). ACCEPTED on subsample but valset REGRESSED. Key wins on subsample: ex_id=54 (grandfather of Douglass Libby's brother: returns only 2 male grandparents instead of all 4 → 1.0), ex_id=58 (sister-in-law of friend of friend: 0.182→0.889). Key regression: ex_id=83 (female first cousin once removed of Sara Leyva: 1.0→0.0 — stochastic, unchanged code path but Phase 1 now only returned 'Jesse Dorman'). The two instructions (SINGULAR FORM, GENDER QUALIFIER) target systematic failure patterns and are directionally correct, but adding new instructions to the EntityFinderSig docstring changes behavior for ALL calls through Phase 1 (entity + count_pivot), amplifying both wins and losses. Best program remains iteration 18, candidate 13. Current live program (candidate 14) is a regression — next iterations must branch from candidate 13.
- Iteration 20 extension (REJECTED, −3.9% subsample): Attempted Python-level gender post-processing via ad-hoc
self.retrieve()calls inforward(). Round 1 (entity_finder max_iters 40→50 + 10-passage gender filter, threshold 1.2): −3.6% subsample. Round 2 (gender filter only, first-passage, threshold 1.5): −3.9% subsample. Both rejected. Critical new finding: callingself.retrieve()insideforward()outside of a DSPy ReAct module context causes systematic (non-stochastic) Phase 1 behavior changes — ex_id=35 and ex_id=55 failed identically in both rounds, confirming the interference is structural. This rules out ALL implementations of post-Phase-1 gender filtering that require additional retrieval calls inforward(). - Iteration 21 extension (ACCEPTED, +3.9% subsample, NEW BEST valset 0.6867): Built on candidate 13. Four additive docstring changes: (1) RECIPROCAL COUSINHOOD in EntityFinderSig entity block — "multiple grandchildren of X are mutual first cousins; 'cousin of grandchild of X' = return ALL grandchildren of X." Definitively fixed ex_id=81 (0.333→1.0). (2) DOB/ATTRIBUTE MULTI-ANCHOR EXPANSION in EntityFinderSig entity block — traverse kinship chain from EACH of N anchors when search_by_date_exact returns N persons. Partial improvement ex_id=104 (0.875) but budget-exhausts for N≥5 anchors + depth≥2 (ex_id=4, ex_id=93 still failing). (3) HOP-BY-HOP TRAVERSAL in EntityFinderSig count_pivot block — forbids compound-phrase ColBERT queries, requires step-by-step. Fixed ex_id=30, 26, 40 (0→1.0). Minor regression: ex_id=46 (0.86→0.50, Phase 1 uses more iters per anchor, finds fewer pivots). (4) FINDING ANCESTORS OF THE PIVOT in CountComputerSig RULES — search pivot's own article for parent names then hop upward. ex_id=88 improved from prior iterations but still only 0.250 (Phase 2 called for 20 spurious pivots, almost all return '0'). Branch:
codeevolver-20260615073543-c7abb8, candidate 15. Valset: 0.6867 (NEW BEST, +5.2% from 0.6526). - Remaining opportunity: (1)
Phase 1 budget exhaustion for DOB multi-anchor entity questions via separate— TRIED in iteration 22 (max_iters=60), FAILED (valset −11.0%). The 40-iteration limit is a beneficial constraint, not a bottleneck. Increasing Phase 1 budget for entity questions causes valset regression. Do NOT retry. (2) Phase 2 cap 20→30 ALONE from candidate 15 (LOW RISK) — was bundled with the failed max_iters change in iter 22; worth testing in isolation. (3) Phase 1 under-enumeration for deep entity fan-out (ex_id=80 Deon Gall ColBERT ceiling) remains structurally unsolved — not addressable by budget increases. (4) Any further EntityFinderSig docstring additions are MEDIUM RISK — iteration 21 confirms that well-targeted conditional additions generalize positively (+5.2% valset), unlike the broad GENDER QUALIFIER addition in iteration 19 (−7.7% valset). The key is that iteration 21's additions were strictly conditional (only fire when N anchors found / for count_pivot) and logically correct.entity_finder_entitymodule (max_iters=50-60)
Approach 16: Additive Reasoning Rules in EntityFinderSig + CountComputerSig (Iteration 21 — NEW BEST valset 0.6867)
- Approach: Built on candidate 13 (iteration 18, valset 0.6526). Four targeted, conditional, additive docstring rules added directly to
phantomwiki_module.py(no coding agent, direct Edit). No DSPy Signature structural changes (no new InputFields, no deletions). Changes are: RECIPROCAL COUSINHOOD (entity block of EntityFinderSig), DOB/ATTRIBUTE MULTI-ANCHOR EXPANSION (entity block of EntityFinderSig), HOP-BY-HOP TRAVERSAL (count_pivot block of EntityFinderSig), and FINDING ANCESTORS OF THE PIVOT (CountComputerSig RULES). - Result: Subsample 0.6883 → 0.7154 (+3.9%); Valset 0.6526 → 0.6867 (NEW BEST, +5.2%). Accepted, candidate 15. Branch:
codeevolver-20260615073543-c7abb8. - Observation: (1) Reciprocal cousinhood is a logical rule that was simply missing: "multiple grandchildren of X are mutual first cousins; 'cousin of grandchild of X' = return ALL grandchildren of X." This is universally correct in PhantomWiki's kinship model. Ex_id=81: 0.333→1.0 (previously Phase 1 searched compound ColBERT query "cousin of grandchild of Eldon Ridenour" → 1 result; after, Phase 1 identifies grandchildren of Eldon Ridenour as the answer set → 5/5 correct). High confidence this generalizes to all "cousin of grandchild of X" questions on the full valset. (2) Conditional docstring additions generalize positively: Unlike iterations 19 (GENDER QUALIFIER: −7.7% valset despite +15.5% subsample) and 3 (BFS: −1.5% valset), iteration 21's additions are strictly conditional and logically grounded — they only activate on matching patterns and implement correct reasoning steps. This confirms the key rule: add instructions that are logically necessary (e.g., "cousins are grandchildren") rather than heuristically useful (e.g., "always search both branches for ancestors"). (3) Hop-by-hop has a budget trade-off: Banning compound ColBERT queries forces Phase 1 to issue one search per hop, which is correct but uses more iterations. Phase 1's max_iters=40 becomes the binding constraint when anchor count is high (DOB: 7-9 persons, or occupation: 30+ persons) combined with 2-3 hop depth. (4) Over-enumeration ceiling persists: 20 Phase 2 calls are capped by the entity cap but the corpus/Prolog mismatch means ~15-18 of those calls return '0' for spurious pivots. The F1 ceiling for count_pivot questions with large hobby/occupation populations is ~0.5-0.7 on such examples even when Phase 2 logic is correct, because the prediction set is dominated by '0' values that dilute the non-zero gold values.
- Remaining opportunity: (1)
Phase 1 max_iters increase for entity questions via separate module— TRIED in iteration 22 (max_iters=60), FAILED (valset −11.0%). The 40-iteration limit is a beneficial constraint; increasing it causes regression. Do NOT retry. (2) Phase 2 cap 20→30 ALONE from candidate 15 — was bundled with the bad max_iters change in iteration 22; worth testing in isolation. (3) One-line conditional gender rule in EntityFinderSig entity block — MEDIUM RISK. (4) Persistent contamination failures (ex_id=65, ex_id=96, ex_id=106) remain on the single-phase attribute path with no fix in sight. A dedicated two-phase for attribute questions with a better Phase 1 traversal mechanism is the only structural fix, but the Phase 1 ColBERT ceiling must first be addressed.
Iteration 24: Incremental — Phase 1 Deduplication + Phase 2 Random Sampling (MAJOR VALSET REGRESSION)
- Approach: Built on candidate 15 (iteration 21, valset 0.6867). Two changes: (1) Phase 1 output deduplication (same zero-cost improvement from iteration 23); (2) Phase 2 random sampling — replaced
entities[:20]withrandom.sample(entities, 20)using a deterministic per-question seed (random.Random(hash(question))). Rationale: sequential top-N selection confirmed biased in iteration 23 — Prolog entities rank beyond position 20 for large hobby/occupation populations. Random sampling gives every entity proportional selection probability. Direct edit tophantomwiki_module.py, branched from candidate 15. - Result: Subsample 0.6463 → 0.6994 (+8.2%); Valset 0.6118 (−11.0% regression from best 0.6867). ACCEPTED on subsample. Candidate 18. Branch:
codeevolver-20260615073543-62729b. - Observation: (1) Subsample gain dominated by stochastic LLM variance on unchanged code paths: ex_id=11, 67, 74 improved on entity/attribute paths with NO code changes — pure run-to-run LLM variance that won't replicate on the full valset. Structural count_pivot wins from random sampling: only 2 (ex_id=36, 41). Structural count_pivot losses from random sampling: 6 (ex_id=10, 18, 20, 29, 31, 63). The structural effect is net-negative even on the subsample. (2) Per-question probability analysis confirms the approach is weak for moderate-to-large entity sets: For N=59 entities (ex_id=31, tea bag collecting), random-20 has P(selecting a specific Prolog entity)≈34%. For N=130 (ex_id=91, axe throwing), P≈15%. The wins require choosing the right 20 from potentially 130; the variance is enormous. The ColBERT rank bias is real, but random sampling doesn't reliably overcome it — it just changes WHICH entities are wrong rather than ensuring CORRECT entities are included. (3) Deduplication is confirmed zero-cost and retained: No regression attributed to deduplication. (4) Pattern matches prior regressions: Same profile as iteration 22 (max_iters=60 entity Phase 1, valset −11.0%) and iteration 19 (GENDER QUALIFIER docstring, valset −7.7%) — large subsample gain with net-negative structural effect masked by stochastic variance.
- Remaining opportunity: Phase 2 entity selection is now exhausted as a tuning target — sequential cap increase (iter 23) and random sampling (iter 24) both failed. The next approach for count_pivot corpus/Prolog mismatch is output filtering rather than input selection: confidence threshold post-processing — after all 20 Phase 2 calls complete, only retain count values appearing in ≥2 distinct calls. This reduces spurious one-off values from corpus entities while preserving recurring correct values. Python-level post-processing, no LM calls, NOT YET TRIED.
- NOTE: This is NOT a new macro approach — it is an incremental tuning of Phase 2 entity selection (same family as iteration 23). Recorded here for completeness.
Iteration 23: Incremental — Phase 1 Deduplication + Phase 2 cap 20→50 (VALSET REGRESSION)
- Approach: Built on candidate 15 (iteration 21, valset 0.6867). Two changes: (1) added Phase 1 output deduplication (order-preserving seen-set) before the Phase 2 loop to prevent redundant calls for duplicate entity names; (2) increased Phase 2 entity cap from
entities[:20]toentities[:50]for count_pivot questions. Direct edit tophantomwiki_module.py. Rationale: parent trace showed 5/13 count_pivot examples hitting the 20-entity cap, with Phase 1 returning 31–130 entities; cap=50 would give 53–100% coverage for moderate sets. - Result: Subsample 0.6906 → 0.7392 (+7.0%); Valset 0.6625 (−3.5% regression from best 0.6867). ACCEPTED on subsample. Candidate 17. Branch:
codeevolver-20260615073543-8feff1. - Observation: (1) Cap=50 genuinely helps moderate-sized entity sets: ex_id=68 (microbiology, 79 Phase 1 entities): 0.74→0.86 — 50 Phase 2 calls vs 20, found value '10' that cap=20 missed. ex_id=75 (DOB cousins, 15 entities): 0.50→0.80 — all 4 gold values found. ex_id=62 (DOB grandsons, 12 entities): 0.75→0.89 — 3 additional correct values. (2) Cap=50 hurts via corpus/Prolog mismatch for large populations: ex_id=91 (axe throwing, 130 Phase 1 entities): spurious '4' and '8' count values introduced by entities 21-50 that exist in corpus but not in Prolog's closed world → 0.800→0.667. (3) Sequential top-N Phase 2 selection is systematically biased: For very large occupation/hobby populations, the Prolog entities with distinctive non-zero counts are NOT necessarily in the top 50 ColBERT results. ex_id=101 (clinical research associate, 50+ entities): 48 of 50 Phase 2 calls return '0'; gold values {1,3,4,5,7} completely absent from prediction — those Prolog entities are ranked >50th by ColBERT. ex_id=33 (financial controller, 95 entities): cap=50 still misses gold entities with counts {5,6,7,8} — they are not in ColBERT's top 50 results. (4) Deduplication is a clean low-risk improvement: No regression attributed to it; avoids wasting Phase 2 budget on duplicate entity names from Phase 1's output. (5) Subsample/valset divergence (+7.0% subsample vs −3.5% valset): The subsample contained DOB-anchor and moderate-population examples where cap=50 cleanly helps. The valset has more large-population hobby/occupation questions where the corpus/Prolog mismatch dominates. (6) Score by type in trace: entity (avg
0.733), count_pivot (avg0.757 for large-cap examples, worse for corpus-mismatched), attribute (avg0.500), count_answer (avg1.000). Large count_pivot questions with pred_total=50 show wide variance: ex_id=68 (0.857), ex_id=108 (0.842), ex_id=10 (0.889) — wins; ex_id=101 (0.444), ex_id=91 (0.667) — losses. - Remaining opportunity: (1) Random sampling instead of sequential top-N — for Phase 2 entity selection when Phase 1 returns N>cap entities, take a RANDOM sample of cap entities instead of the first cap. This would give a better chance of including Prolog entities that ColBERT ranks lower than corpus-only entities. Python-level change in forward(). (2) Confidence threshold post-processing — only include Phase 2 count values that appear in ≥2 distinct Phase 2 calls. This collapses spurious one-off values from corpus/Prolog mismatch (like '8' in ex_id=91) while keeping truly recurring correct values. Python-level post-processing with no LM calls. (3) Revert to cap=20 from candidate 15 is the safe base — the deduplication alone is a free win worth keeping if re-testing. (4) All next experiments must branch from candidate 15 (not candidate 17).
- NOTE: This is NOT a new macro approach — it is an incremental tuning of Phase 2 entity cap (and deduplication). Recorded here for completeness.
Iteration 22: Incremental — entity_finder_entity (max_iters=60) + Phase 2 cap 20→30 (VALSET REGRESSION)
- Approach: Built on candidate 15 (iteration 21, valset 0.6867). Two changes: (1) created a separate
entity_finder_entitydspy.ReAct module (same EntityFinderSig, max_iters=60) specifically for entity questions, replacing the sharedentity_finder(max_iters=40); (2) increased Phase 2 cap from 20→30 for count_pivot questions. Commit:9e0f76a. - Result: Subsample 0.6208 → 0.6382 (+2.8%); Valset 0.6112 (−11.0% regression from best 0.6867). ACCEPTED on subsample. Candidate 16. Branch:
codeevolver-20260615073543-dfc4b7. - Observation: (1) Increasing Phase 1 budget (40→60) for entity questions caused valset regression: Higher budget did NOT help the known hard cases (ex_id=93 DOB multi-anchor only marginally improved 0.143→0.167; ex_id=58 and ex_id=90 still 0.0). The likely cause of valset regression: at max_iters=60, Phase 1 explores wrong branches more deeply on questions that previously terminated naturally at 40 iterations with a correct result — more compute → more wrong-path search → worse entity quality on some previously-passing questions. (2) Phase 2 cap 20→30 was bundled with the max_iters change: Cannot isolate its individual effect from the regression. Some individual count_pivot examples improved (ex_id=88: 0.250→0.500 from prior iteration, ex_id=37: 0.800 with correct values {3,4} found). But the cap increase also means more spurious pivot calls producing extra '0' values in the prediction set. (3) Subsample / valset divergence: +2.8% subsample with a new seed did not generalize; the seed happened to contain entity examples where longer search helped, while the valset has more cases where it hurts. (4) Subsample parent baseline was lower (0.6208 vs iteration 21's subsample score of ~0.71 on its seed) — indicating seed variance, making the delta less reliable.
- Remaining opportunity: (1) Phase 2 cap 20→30 alone (without max_iters change) should be tested from candidate 15 — the individual Phase 2 cap improvement for count_pivot may be net positive when not bundled with the entity Phase 1 regression; (2) entity_finder_entity at max_iters=60 is LIKELY HARMFUL and should not be retried — the 40-iteration limit for entity Phase 1 appears to be a beneficial constraint preventing over-exploration of wrong paths. (3) Branch from candidate 15 for ALL next experiments — candidate 16 is a regression and must not be used as base.
- NOTE: This is NOT a new macro approach — it is an incremental tuning of the entity Phase 1 routing (Approach 15/16). Recorded here for completeness.
Approach 14: Attribute_Deep Two-Phase Extension — Phase 1 (EntityFinderSig) + Phase 2 (AttributeAnswerSig) (Iteration 17 — REJECTED)
- Approach: Built on iteration 12 (candidate 9, all-time best valset 0.6417). Added a new
attribute_deepquestion sub-type in_classify_question(): attribute questions ("what is/are/was/were") with ≥2 "of the" occurrences and no "person whose" anchor pattern. For this type, dispatched Phase 1 (entity_finderviaEntityFinderSig, question_type='attribute') to find all terminal entities in the multi-hop chain, then Phase 2 (newAttributeAnswerSigReAct, max_iters=20) to look up the requested attribute for each entity — eliminating intermediate-entity contamination by design. Single-phase fallback retained if Phase 1 returns empty. Round 2 added a SIBLING CROSS-REFERENCE instruction block toEntityFinderSig's COMPLETENESS section. - Result: Subsample 0.7630 → 0.7270 (Round 1, −4.7%) → 0.7176 (Round 2, −6.0%). REJECTED. Valset: N/A.
- Observation: (1) Phase 1 under-enumerates for attribute questions at the same rate as single-phase: The motivation question ("What is the occupation of the great-grandchild of the great-grandfather of Deon Gall?", gold=12) scored 0.0 in both rounds — Phase 1 returned the same 3 wrong entities as single-phase (it does not find more of the 12 great-grandchildren; ColBERT cannot enumerate all children of a given person). (2) SIBLING CROSS-REFERENCE in Phase 1 is harmful: The instruction "siblings listed in an entity's article are also children of the same parent" caused Phase 1 to over-expand into arbitrary sibling chains unrelated to the correct traversal path, producing 8 entirely wrong entities and 0.0 F1 on the primary test question. In single-phase context, this instruction might help (the model has the full question context to constrain expansion); in Phase 1 it causes undirected over-expansion. (3) 3 attribute_deep questions in subsample (avg=0.500): 1.0 (simple 2-hop entity chain), 0.5 (3-hop DOB query, found 1 of 3), 0.0 (Deon Gall 2-hop occupation fan-out). The routing didn't improve any of these vs what single-phase would have done. (4) Architecture is correct in principle: Two-phase IS the right fix for contamination — Phase 2 (AttributeAnswerSig) receiving explicit final entity names would eliminate contamination. The blocker is Phase 1 completeness. (5) Many "wins" and "losses" were stochastic noise on single-phase paths (examples on the entity/attribute/count paths that aren't affected by the attribute_deep change) — not attributable to the change.
- Remaining opportunity: Do NOT retry attribute_deep with EntityFinderSig as Phase 1 without a fundamentally better traversal mechanism. Promising alternatives: (a) Add concrete worked example to single-phase
PhantomWikiQAdocstring: "When traversing a multi-hop chain, at each hop look up any siblings mentioned in the entity's article — they are also children of the same parent and may also qualify"; (b) Build a dedicated Phase 1 agent for attribute questions with explicit step-by-step hop-by-hop instructions (separate Signature from EntityFinderSig, which was designed for count_pivot); (c) Entity question two-phase may be a better starting point since entity-question Phase 1 has less ambiguity than attribute-question Phase 1.
Approach 5: Dual Retrieval Tools (search_wiki_broad k=30) + HOW MANY Format Fix + Minimal Targeted Additions on Clean Iteration 1 Base (Iterations 5–6 — CURRENT BEST)
- Approach: Built on iteration 1 (best clean base, NOT iterations 3/4 which had heavy baggage). Added
search_wiki_broad(query)as a second retrieval tool backed bydspy.Retrieve(k=30)alongside existingsearch_wiki(k=10). Added minimal targeted prompt additions: (1) HOW MANY FORMAT RULE with WRONG/RIGHT examples ("return the numeric count as a string, not entity names"); (2) IMPLICIT RELATIONSHIPS section (cousin/nephew/niece must be derived via traversal, never queried directly); (3) NON-STANDARD KINSHIP TERMS — second aunt/uncle = great-grandparent's sibling (confirmed-correct from iteration 4 traces); (4) DATE-OF-BIRTH guidance to usesearch_wiki_broad; (5) Step 4 in HOW TO SEARCH: singular-form questions may have MULTIPLE entities at each hop. Deliberately excluded BFS heavy example, mandatory enumeration rules, generation tracking — all additions that caused regressions in iterations 3/4. - Result: Subsample 0.4207 → 0.4800 (+14.2%); Valset 0.5152 → 0.5425 (+5.3%). NEW BEST valset score. First genuine valset improvement since iteration 1.
- Observation: (1) HOW MANY FORMAT FIX was the highest-impact single change. The model was computing the correct count internally but outputting entity names instead of the count string. Entries 0 ("2"), 22 ("2"), 28 ("2"), 44 ("2") all flipped 0.0→1.0. This is a purely structural output bug that silently failed across many "how many" questions. The fix generalizes to any question where the model correctly enumerates but mislabels the output. (2) Going back to iteration 1's clean base was critical. Iterations 3/4 accumulated BFS guidance, generation tracking, multi-count prescriptions, and NEVER ABANDON sections that collectively destabilized simpler questions. Starting fresh from iteration 1 and adding only targeted minimal additions let each addition work without interference. (3) search_wiki_broad provided marginal but real improvement for DOB lookups (entry 11: 1→2 correct occupations for DOB 1050-09-16). However, ColBERT's k=30 ceiling still misses 5/7+ people sharing a DOB — not a structural fix, just a partial improvement. For entries 2, 10, 36, 42, 49 (DOB-anchored), the model still returned 0-1 correct answers out of 7-15. (4) Entries 38, 43 remain low (0.40, 0.00) for the Deon Gall great-grandchild fan-out — the model only finds 3 of 12 great-grandchildren. This is a fan-out depth issue, not a format issue. (5) Entries 30, 34 (intermediate entity contamination for deep kinship chains) persist at 0.0 — same question failures as iterations 3/4.
- Remaining opportunity: (1) "How many" multi-path fan-out (entries 5, 6, 15, 17, 29, 33, 36, 40, 45, 46, 47) still fails — model returns 1 count when 3-9 distinct counts needed. The format fix helped simple 1-count questions; it does NOT fix cases requiring N separate counts for N intermediate entities. This remains the biggest unsolved cluster. (2) DOB structural lookup: ColBERT cannot enumerate all people sharing a birth year. A code-level tool is needed. (3) Intermediate entity contamination (entries 30, 34, 43): deep kinship traversal causes model to return attributes of intermediate entities. DO NOT bullets are consistently ineffective. A structural architecture change (traversal phase separate from attribute-lookup phase) may be needed. (4) Second uncle chain traversal bugs: entries 16 (Rosina Robey second uncle — completely wrong entities returned despite correct definition in prompt) and 41 (mother of cousin of second uncle — wrong entity). Even with the correct definition, traversal execution fails for multi-hop second-uncle chains.
Iteration 6 extension (built on iteration 5, ACCEPTED, valset 0.5425→0.5530, +1.9%): Added MULTI-ENTITY ENUMERATION prompt section (9 lines) instructing model to search BOTH maternal/paternal branches for ancestor anchors, issue 2+ follow-up searches for DOB/hobby anchors, enumerate all friends/siblings before counting. Also increased retrieve_broad from k=30 to k=50. Key wins: second uncle of Rosina Robey (iteration 5 entry 16/iteration 6 entry 17) finally fixed at 1.0 — model searched both ancestor branches and found both Alvaro/Joesph Sharma. Female first cousin once removed of Sara Leyva (iteration 5 entry 39/iteration 6 entry 38) fixed at 1.0 — all 5 correct entities found. Friend-of-great-grandparent count (entry 4): 7 of 9 counts correct (0.875). Key regressions introduced: (a) Tautological DOB question (entry 27): "What is the DOB of person whose DOB is 0954-03-04?" → model now searches for all people with that DOB instead of returning the value directly; returned [] vs gold '0954-03-04'. (b) Over-counting when multiple grandfathers found (entry 42): model reports counts for EACH grandfather independently (['2','1'] vs gold ['2']), a new multi-entity enumeration failure mode where the model over-applies counting instructions to every resolved intermediate. k=50 for broad search showed no improvement for DOB fan-out failures (entries 12, 22, 35, 40) — ColBERT ceiling confirmed at k=30 already.
Iteration 7 extension (built on iteration 6, ACCEPTED on subsample, valset 0.5530→0.5464, −1.2% regression from best): Three code changes and three prompt changes: (1) Added search_by_date(date_str) tool that decomposes date into year, year-month, and full-date components and issues 5 query formats ("born YYYY", "date of birth YYYY", "YYYY-MM", "born YYYY-MM-DD", "YYYY-MM-DD") against retrieve_broad (k=30), deduplicating all results; (2) Reverted k=50→k=30 for search_wiki_broad (iteration 6 confirmed no benefit at k=50); (3) New ATTRIBUTE FAN-OUT section requiring 5+ varied query phrasings for attribute-anchored questions before computing any count; (4) Second cousin clarification (goes UP to grandparent level, NOT great-grandparent — avoid confusion with second uncle); (5) Tautological DOB short-circuit rule ("if question asks for DOB of person whose DOB is X, return X directly"). Subsample: +2.8% (0.5363→0.5611). Key subsample wins: example 64 (hobby fan-out: 0.22→1.0 — ATTRIBUTE FAN-OUT guidance worked, model issued multiple hobby queries and found all 4 hobbies); example 26 (0.0→1.0 — correct count computed). Key subsample regressions: example 58 (stochastic failure: 0.57→0.0 — model retrieved correct intermediate entities but drilled into irrelevant branch), example 20 (0.2→0.0 — deep kinship chain returned empty). Trace confirmed: search_by_date is called correctly (first tool call in DOB-anchored questions), but even with 5 varied query formats at k=30, ColBERT returns year-neighborhood documents ranked by semantic proximity — exact-date matches beyond top 2-3 are outranked by near-miss dates (e.g., "0918-01-16" crowding out "0918-01-17"). Example 27 still finds 2/7 people; example 79 still finds 1/9 — identical recall to k=30 without the tool. The valset regression despite subsample gain is consistent with either noise (subsample is 50 rows, seed changed between iterations 6→7) or mild overfitting to the specific subsample's DOB/hobby examples. The k=30 revert is a clean no-cost improvement (k=50 was confirmed worse, not just equal).
Observations
What Works Well
- The enriched
PhantomWikiQA(dspy.Signature)docstring effectively guides multi-answer exhaustive search (established in iteration 1, still foundational) - BFS enumeration guidance in iteration 3 significantly improved multi-hop multi-branch traversal on the training subsample (+9.9%): Deon Gall great-grandchild (0.29→0.92), sibling of cousin chains (0.00→0.89), aunt of cousin questions (0.67→1.00)
- k=12 provides marginally better passage coverage than k=10 (no regression attributed to this change)
- max_iters=50 is sufficient; model typically uses 8–15 searches on complex questions
- Explicit anti-contamination instruction in the answer field description largely prevents "attribute (person name)" format leakage — though trace entry [44] showed one regression where 7 parenthetical formats crept through
- The ReAct agent branches out well when the BFS signature instructs it — correctly finding Hilton Gall's other children (Bettye Dix, Chloe Hinman, Shaina Schenck, Xiao Gall) in entry [44], even if it applied those branches at the wrong generation level
- Kinship term definitions for "first cousin once removed" worked correctly in trace entry [3] (1.0 F1) and entry [17] (1.0 F1)
- Second aunt/uncle definition (great-grandparent's sibling) is confirmed correct (iteration 4 and 5 traces): multiple second-aunt/uncle questions now pass. The previous definition ("parent's first cousin") was causing systematic wrong-generation traversal.
- HOW MANY FORMAT FIX (iteration 5): A critical structural output bug fix. The model was computing the correct numeric count internally but outputting entity names (e.g., ["Alice", "Bob"] instead of ["2"]). Iteration 5 entries 0, 22, 28, 44 all moved from 0.0→1.0 from this single fix. This generalizes to the entire valset for any "how many" question where the model's reasoning produces the right count.
- Dual retrieval (search_wiki_broad k=30): Iteration 5. Improved DOB recall from 1→2 correct entities for DOB 1050-09-16 (entry 11). Also useful for attribute-anchor lookups (hobby/occupation as anchor for broader fan-out).
- Clean minimal base (iteration 1) outperforms accumulated-additions bases (iterations 3/4) for valset generalization: Iteration 5 showed that branching from iteration 1 (clean signature) rather than iteration 3/4 (heavy BFS/multi-count additions) produced better valset results. The heavy prompt additions from iterations 3/4 were net-negative on the broader valset distribution.
- Entry [21] (iteration 5): "Who is the great-grandson of Carlotta Freeland?" → 1.0 ✓ (was 0.0 in iterations 3 and 4). This persistent failure resolved when using iteration 1's cleaner base + the format/traversal approach without conflicting GENERATION LEVEL TRACKING text.
- Entry [45] (iteration 5): "How many sisters does person with hobby table football have?" → 0.75 (got 3 of 5 counts). The search_wiki_broad tool enabled finding more hobby-attribute matches across multiple entities.
- MULTI-ENTITY ENUMERATION guidance (iteration 6): Explicitly instructing the model to search BOTH maternal and paternal ancestor branches fixed the Rosina Robey second-uncle case (iteration 6 entry 17: 0.0→1.0 across 4 iterations). Also fixed female first cousin once removed of Sara Leyva (entry 38: 0.0→1.0). The guidance that "ancestor chains may have multiple qualifying intermediates; search all branches" causes genuine improvement on ancestor-fan-out questions and generalizes positively (+1.9% valset).
- k=50 for broad search provides no additional benefit over k=30 for DOB recall — ColBERT's semantic ceiling is already hit at k=30. Increasing k further wastes token budget without improving recall for DOB anchor failures.
- Hybrid two-phase architecture (iteration 12): Per-entity Phase 2 calling for count_pivot definitively solves multi-count fan-out collapse. Ex 9→0.714, Ex 13→0.545, Ex 39→0.857, Ex 63→0.571, Ex 78→0.800. The +9.9% valset gain is the largest structural improvement in the run. The key design decisions: (a) Python-level
_classify_question()instead of LLM classification, (b) two-phase ONLY for count_pivot, not all types, (c) fallback to single-phase when Phase 1 returns empty. - Python-level simple anchor bypass (iteration 13): For "does the person whose hobby/occupation is Y have?" questions, bypassing Phase 1 and using the pre-built index directly as pivot entities is a clean structural improvement. Phase 2 cap increased to 30. This component should be retained regardless of other changes.
- Python
_classify_question()routing is reliable: The lexical rules (how many + does/did/do + "the" → count_pivot; how many → count_answer; what is/are → attribute; else → entity) correctly categorize ~96% of questions based on trace inspection. No misclassification observed in iteration 12 subsample (50 examples). This is a significant improvement over LLM-based classification which had systematic misclassification rates of 10-20%. - EntityFinderSig (Phase 1) KINSHIP DEPTH and BILATERAL BRANCH SEARCH instructions work well for kinship-chain pivot finding: Ex 37 (female first cousin once removed of Sara Leyva = 1.0), Ex 31 (female first cousin once removed of grandparent of Sam Highsmith = 1.0), Ex 36 (cousin of grandchild of Eldon Ridenour = 1.0). The bilateral ancestor search instructions have been maintained and are still effective.
Generation-Level Confusion — Partially Resolved in Iteration 5
A systematic "off-by-one generation" error was identified in iteration 3 and persisted through iteration 4. Iteration 5 shows partial resolution:
- Iteration 3, Trace entry [4]: "How many great-grandsons does Carlotta Freeland have?" — returned 0, model searched for Frederic's children (one level too deep).
- Iteration 4, Trace entry [6]: SAME question, SAME failure at 0.0. GENERATION LEVEL TRACKING section did NOT fix it.
- Iteration 5, Trace entry [21]: "Who is the great-grandson of Carlotta Freeland?" → 1.0 ✓ (Frederic Koons). A related but slightly different phrasing (entity lookup vs count) now works correctly with the clean iteration-1 base and without conflicting GENERATION LEVEL TRACKING text. The format fix + cleaner prompt together resolved the entity-identification version of this question.
- Iteration 5, Trace entry [4]: "How many cousins does the cousin of the female second cousin of the female second cousin of Tashina Noe have?" → predicted '0', gold '3'. Still a deep-chain generation confusion, though this question also requires multi-path traversal.
- Iteration 5, Trace entry [13]: "How many cousins does the cousin of the great-grandchild of the great-grandfather of Deon Gall have?" → predicted '6', gold ['1', '3']. Model found a wrong intermediate entity and computed the count for that entity instead — this is both a traversal error and a multi-count failure.
- The removal of GENERATION LEVEL TRACKING section (by going back to iteration 1's clean base) may have helped some cases (entry 21 now 1.0) without introducing new regressions. Adding explicit worked counter-examples of the failing pattern may be more effective than generic "count at the exact level" instructions.
Carlotta Freeland "How Many Great-Grandsons" — FIXED in Iteration 15
"How many great-grandsons does Carlotta Freeland have?" → gold=['1']. FIXED in iteration 15 (Row 7/ex_id=14: pred=['1'], 1.0). This was 0.0 in iterations 3–14 for the count form — the model found Frederic Koons as the great-grandson but then went one generation too deep looking for Frederic's children. The fix came naturally with the ANCHOR HINT removal and seed change; no targeted prompt change was needed. The question now routes through count_answer (single-phase), and the model correctly returns the count of 1. Note: "Who is the great-grandson of Carlotta Freeland?" (entity form) was also already working (1.0 since iteration 5). Both forms are now solved.
Iteration 9 Key Finding: "Enumerate-then-Collapse" Confirmed at Reasoning Level
Iteration 9 trace inspection on the iteration 8 parent program revealed: the model correctly lists all intermediate entities in its Chain-of-Thought (e.g., all 15 people born on a given date, all 4 friends of a person, all financial controllers) but then picks only one entity to process and calls finish(). This is the "enumerate-then-collapse" failure — the knowledge of the full entity set exists in the model's reasoning, but iteration over the full set does not happen. This confirms that the failure is NOT a retrieval problem (the model has the entities) but a control flow problem (the model doesn't loop over them all in the action phase).
Both MULTI-COUNT ITERATION section (−5.8%) and ATTRIBUTE FAN-OUT alone (−6.8%) caused regressions on the iteration 8 parent because they induced over-searching on simple single-count questions — the instructions cannot discriminate "implicit multi-entity anchor requiring N separate counts" from "simple single-entity anchor requiring 1 count." Every round of prompt instructions to iterate has either over-applied (false positives on simple questions) or under-applied (model ignores instruction for some cases).
"How Many" Questions — Two Distinct Sub-Problems (Updated Through Iteration 12)
Iteration 5 revealed a critical distinction between two "how many" failure modes:
Sub-problem A: FORMAT BUG (FIXED in iteration 5) — Model computes correct count but outputs entity names instead of the count string. HOW MANY FORMAT RULE fixed this. Entries 0, 22, 28, 44 all moved from 0.0→1.0. This is now resolved.
Sub-problem B: MULTI-PATH FAN-OUT (LARGELY UNRESOLVED through iteration 8) — Questions where there are N distinct intermediate entities, each requiring a separate count. The model computes 1 count for 1 entity and stops. This pattern persists through all iterations:
- Iteration 3 entries 8, 11, 13, 46: 9, 5, 9, 7 counts needed, model got only 1.
- Iteration 4 entries 3, 5, 9, 15, 24, 29, 32, 34: multiple values needed, got 1.
- Iteration 5 entries 5 (gold ['0','2','3'], got ['0']), 6 (gold 9 values, got ['6']), 15 (gold ['0','2','4','6','8'], got ['0']), 17 (gold ['0','2'], got ['2']), 29 (gold ['0','1','3','4','6'], got ['1']), 33 (gold ['0','1','2'], got ['2']), 36 (gold ['0','1','10','4'], got ['0']), 40 (gold ['0'..'6'], got ['0']), 45 (got 3 of 5), 46 (gold ['0'..'8'], got ['0']), 47 (gold ['0'..'4'], got ['0']).
- Iteration 6 entries 7 (gold ['0'..'7'], got ['0']), 9 (gold ['0','2'], got ['2']), 15 (gold ['0','2','4','6','8'], got ['4']), 16 (gold ['0'..'8'], got ['0']), 19 (gold ['3','4'], got ['0']), 31 (gold ['0','1','3','4','6'], got ['1']), 34 (gold ['0','1','2'], got ['0']), 43 (gold ['0'..'7'], got ['0']), 44 (gold ['0'..'4'], got ['0']). Multi-entity enumeration guidance helped entry 4 (friend-of-great-grandparent: 7 of 9 counts, 0.875) but did not fix 1-entity-collapse for occupation/hobby anchors or deep kinship chains.
- New failure mode from iteration 6 (multi-entity enumeration over-application): Entry 42 "How many children does the grandfather of Dwain Decker have?" → predicted ['2','1'] vs gold ['2']. The model found 2 grandfathers and returned a count for each, when only one count was needed.
- Iteration 8 — multi-count persists across 9 failing examples (47% of all failures): Ex 4 (female cousins of grandchild of great-grandchild of Forest Benner, gold=['0','2','3'], pred=['1']), Ex 5 (friend-of-friend of great-grandparent of Dwight Lazarus, gold=['1'..'9'], pred=['6']), Ex 8 (male first cousins once removed of great-grandchild of video editor person, gold=['0'..'7'], pred=['4']), Ex 13 (nephews of great-uncle of great-uncle of stone-collecting person, gold=['0'..'8'], pred=[]), Ex 16 (great-grandparents of female cousin of tea-bag-collecting person, gold=['0','2','4','6','8'], pred=[]), Ex 18 (granddaughters of financial controller person, gold=['0'..'8'], pred=['0']), Ex 37 (children of child of grandmother of sports-therapist person, gold=['0'..'5'], pred=[]), Ex 42 (great-grandsons of great-grandchild of farm-manager person, gold=['0'..'6'], pred=['0']), Ex 44 (female first cousins once removed of grandfather of company-secretary person, gold=['0'..'6'], pred=['0']). Subsample avg on multi-count questions: 0.407 (across 17 examples).
- Iteration 10 — PARTIAL improvement: With ATTRIBUTE FAN-OUT 5+ queries restored, multi-count now WORKS for common-attribute anchors: Ex 26 (microbiology hobby → 0.909 — model iterates over ~20 people and computes their friend counts) and Ex 47 (biochemist occupation → 0.842 — similar pattern). But it STILL FAILS for rare-attribute anchors: Ex 14 (financial controller → pred=['2'], gold 9 values), Ex 42 (crystals hobby → pred=['0'], gold 9 values), Ex 43 (clinical research associate → pred=['1'], gold 7 values). The ATTRIBUTE FAN-OUT instruction is running but ColBERT cannot find all instances of rare attributes regardless of query phrasing. — Also NEW: Ex 30 (cousins of male second cousin of Reinaldo Pettus): model correctly found all 4 second cousins (bilateral traversal) and iterated over each to compute cousin counts, but returned '0' for all 4 instead of ['10','7','8']. This is a retrieval failure at the FINAL hop — the model correctly loops but ColBERT cannot enumerate all cousins of a given named person.
- Root cause confirmed: these questions require finding all N intermediate entities, then counting independently for EACH. The model finds 1 intermediate entity, computes 1 count, and calls
finish. Eight iterations of prompt guidance have not fully fixed this. Partial improvement for common-attribute anchors is now achieved; rare-attribute anchors remain structurally unsolved. - Prompt guidance alone is insufficient for rare-attribute anchors. A code-level pre-built attribute index (attribute_type → attribute_value → [person_list]) analogous to the DOB exact index would fix this structurally.
- The multi-entity enumeration approach works for ENTITY-FINDING tasks (second uncle, first cousin once removed) but causes regression for COUNT tasks where over-counting is penalized. The guidance needs to be scoped specifically to entity-finding contexts, not counting contexts.
- New failure mode confirmed in iteration 10: Over-enumeration false positives — when the model over-searches, it finds false-positive entities and computes spurious counts: Ex 8 (pred=['1','2'], gold=['1'] — found extra false second aunt); Ex 46 (pred=['Mayra Battle','Sherrie Fite','Judith Philips','Patti Fuchs'], gold=['Judith Philips','Patti Fuchs'] — over-searched and added wrong cousins). The MULTI-ENTITY ENUMERATION "always search both branches" guidance causes the model to explore extra family lines that happen to return unrelated entities matching the query terms.
- Iteration 12 — hybrid two-phase PARTIALLY solves multi-count fan-out for count_pivot: The per-entity Phase 2 eliminates the collapse failure for count_pivot questions. Ex 4 (0.714), Ex 16 (0.857), Ex 42 (0.889), Ex 49 (1.0) all show meaningful improvement. But Phase 1 under-enumeration (Ex 8, 9, 15 — finds 1 of 4-9 pivots) and over-enumeration from corpus/Prolog mismatch (Ex 14, 27, 43 — finds too many wrong pivots) are the new bottlenecks. The F1 ceiling for count_pivot on the subsample is now ~0.668 avg — up significantly from ~0.4 avg in iterations 8-10, but further gains require Phase 1 quality improvements (attribute index).
- count_answer questions (3 examples in subsample, avg=0.333): These use single-phase. Both failures (Ex 0, Ex 6) are corpus dead-ends — the model can't traverse to the relevant ancestor articles. The two-phase architecture doesn't help here because Phase 1 would have the same dead-end. This cluster is low-hanging fruit that is NOT actually addressable with the current tools.
Intermediate Entity Answer Contamination (Persists Through Iteration 10)
When traversing multi-level kinship chains, the model sometimes returns attributes of INTERMEDIATE entities instead of the final target. This has been confirmed across iterations 3, 4, 5, and 6:
- Iteration 3, Entry [28]: hobby of great-uncle of great-uncle of Geraldine Ruch — returned 4 hobbies of intermediate entities.
- Iteration 3, Entry [34]: hobby of great-uncle of niece of second uncle of Juan Arevalo — returned 4 hobbies of intermediates.
- Iteration 4, Entry [30]: SAME question as [34] — returned ['Noodling', 'Railway journeys', 'Microbiology']; gold ['antiquities']. DO NOT bullets did NOT fix this.
- Iteration 5, Entry [30]: "What is the hobby of the great-uncle of the great-uncle of Geraldine Ruch?" → predicted ['sand art', 'crystals', 'slot car racing'], gold ['botany']. 0.0 again. Same pattern.
- Iteration 5, Entry [34]: "hobby of great-uncle of niece of second uncle of Juan Arevalo" → predicted ['disc golf'], gold ['antiquities']. 0.0 again. SAME question as iterations 3/4, same failure.
- Iteration 5, Entry [43]: "occupation of cousin of great-grandchild of great-grandfather of Deon Gall" → predicted 7 completely wrong occupations (from wrong intermediate entities); gold is 8 correct ones. 0.0.
- Iteration 6, Entry [41]: "occupation of cousin of great-grandchild of great-grandfather of Deon Gall" → 5 wrong occupations returned. 0.0. SAME question as iteration 5 entry [43], SAME failure pattern.
- Iteration 8, Entry [35]: "hobby of great-uncle of niece of second uncle of Juan Arevalo" → predicted ['railway journeys', 'microbiology'], gold ['antiquities']. 0.0. SIXTH consecutive iteration of SAME failure. Same question appears in iterations 3, 4, 5, 6, 7, and now 8 — always wrong. DO NOT bullets, GENERATION LEVEL TRACKING, removing guidance, multi-entity enumeration, ATTRIBUTE FAN-OUT, and exact-match DOB index have all failed to fix this single question. The model finds intermediate entities (great-uncle of second uncle: e.g., Werner Corrigan) and returns THEIR hobbies instead of the final target entity's hobbies. Critically, the DOB exact-match tool was not relevant here — this is a pure kinship traversal contamination.
- Pattern: After multi-hop BFS traversal the model accumulates entities at different levels and reports their attributes together (or picks the wrong level's attributes). FIVE distinct iterations with five different prompt strategies have all failed to fix this. DO NOT bullets, GENERATION LEVEL TRACKING, removing all extra guidance, multi-entity enumeration, and exact-match DOB — none resolves it. This is a fundamental ReAct architecture limitation.
- Iteration 10, Ex 25: "hobby of great-uncle of great-uncle of Geraldine Ruch" → pred=['shortwave listening', 'sand art', 'crystals', 'slot car racing'], gold=['botany']. SEVENTH consecutive iteration of SAME failure. Two-phase architecture was specifically designed to fix this — but it failed for a different reason (Phase 1 ambiguity for counting questions; the contamination fix was never tested because it couldn't survive the counting regression).
- Iteration 10, Ex 27: "hobby of great-uncle of niece of second uncle of Juan Arevalo" → pred=['noodling', 'railway journeys', 'microbiology'], gold=['antiquities']. EIGHTH consecutive failure of this exact question.
- Iteration 10, Ex 45: "hobby of grandparent of great-aunt of grandson of Dortha Mcnulty" → pred=['flag football', 'amateur astronomy'], gold=['archery', 'eating']. New instance of same contamination pattern.
- Iteration 15, Row 29 (ex_id=72): "hobby of great-uncle of niece of second uncle of Juan Arevalo" → pred=['mineral collecting', 'trainspotting'], gold=['antiquities']. FIFTEENTH consecutive failure of this exact question. Never correct in any iteration, across every prompt/architecture variant tried.
- Iteration 15, Row 47 (ex_id=106): "hobby of grandparent of great-aunt of grandson of Dortha Mcnulty" → pred=['gongoozling'], gold=['archery', 'eating']. Same contamination pattern.
- Iteration 15, Row 39 (ex_id=96): "occupation of cousin of great-grandchild of great-grandfather of Deon Gall" → pred=[8 wrong occupations], gold=['building control surveyor','dancer','marine scientist','public relations officer','risk analyst','social researcher','sports physiotherapist','surveyor']. TWELFTH consecutive failure (attribute contamination, different question pattern from Juan Arevalo but same root cause).
- Iteration 16, ex_id=72: Juan Arevalo hobby chain → 0.0. SIXTEENTH consecutive failure.
- Iteration 16, ex_id=96: Deon Gall occupation chain → 0.0. THIRTEENTH consecutive failure. Same intermediate contamination, still on single-phase path.
- Iteration 17 — Deon Gall 2-hop form (gold=12) added to attribute_deep path: "What is the occupation of the great-grandchild of the great-grandfather of Deon Gall?" was dispatched through the new attribute_deep two-phase routing. Round 1: Phase 1 returned the SAME 3 wrong entities as single-phase (Deon Gall, Von Gall, Nikki Gall) — not the great-grandchildren. Phase 2 looked up their occupations → 8 wrong occupations predicted → 0.0. Round 2 (SIBLING CROSS-REFERENCE): Phase 1 over-expanded into entirely wrong entity branches → 0.0. The Juan Arevalo (ex_id=72) and ex_id=96 questions were not in this subsample.
- Iteration 18 — ex_id=80 (entity form: "Who is the great-grandchild of the great-grandfather of Deon Gall?", gold=12): Now routed through entity Phase 1. pred=['Deon Gall', 'Von Gall', 'Nikki Gall'], score=0.400. Phase 1 returned the SAME 3 entities as single-phase — entity routing does NOT fix the ColBERT fan-out ceiling. This confirms the limitation is structural (ColBERT cannot enumerate all N children of a named entity), not merely a routing/instruction problem.
- Iteration 18 — ex_id=106 (Dortha McNulty attribute chain): "What is the hobby of the grandparent of the great-aunt of the grandson of Dortha Mcnulty?" → pred=['finance','research'], gold=['archery','eating']. SEVENTEENTH consecutive failure of this contamination pattern (first appeared in iteration 10 as Ex 45). Attribute, single-phase path, unchanged code.
- Iteration 19 — ex_id=72 (Juan Arevalo hobby): pred=['mineral collecting','trainspotting'], gold=['antiquities']. NINETEENTH consecutive failure. Unchanged code path (attribute, single-phase). No prompt or architectural change has ever fixed this.
- Iteration 21 — ex_id=65 (Geraldine Ruch hobby, same contamination pattern): pred=['shortwave listening','sand art','crystals','slot car racing'], gold=['botany']. 21st+ consecutive failure of this contamination pattern. Iteration 21's docstring additions did not affect the single-phase attribute path. The Juan Arevalo (ex_id=72) hobby question was not in the iteration 21 subsample but ex_id=65 shows the identical contamination pattern persists.
- Iteration 19 — ex_id=80 (Deon Gall entity form, gold=12): pred=['Deon Gall','Von Gall'], score=0.286. Phase 1 still returns only 2/12 great-grandchildren — ColBERT fan-out ceiling unchanged regardless of Phase 1 prompt tuning.
- Iteration 19 — ex_id=28 (Deon Gall attribute form, gold=12): "What is the occupation of the great-grandchild of the great-grandfather of Deon Gall?" pred=['advertising copywriter','sales executive'], score=0.286 — only 2/12 occupations found. Attribute, single-phase path. Same ColBERT fan-out ceiling blocking Phase 1 entity enumeration and single-phase traversal alike.
- Root cause update (iterations 17/18): Two-phase routing IS the correct architectural fix for contamination. The blocker is Phase 1 (EntityFinderSig) under-enumeration for attribute question chains — it uses the same ColBERT retrieval as single-phase and finds the same incomplete set of final entities. For Deon Gall: the model sees Sylvester Gall's article listing his sisters (Bettye Dix, Chloe Hinman, etc.) but concludes "Hilton had only one child," returning only 3 of 12 great-grandchildren. A fundamentally better Phase 1 for attribute questions is needed before two-phase can work. Options: (1) dedicated traversal agent with explicit per-hop instructions; (2) sibling cross-reference logic within single-phase via concrete worked examples in PhantomWikiQA docstring (not in Phase 1, where it causes over-expansion). SIBLING CROSS-REFERENCE in Phase 1 is confirmed harmful — caused 0.0 vs 0.4 on ex_id=28.
Date-of-Birth Lookup — STRUCTURALLY SOLVED by Exact-Match Index (Updated Through Iteration 8)
ColBERT semantic search cannot match exact date strings like "0946-07-14". After four failed semantic interventions (k=30, k=50, 5-format search_by_date, iteration 7), iteration 8 added search_by_date_exact(date_str) backed by a pre-built 494MB JSON exact-match index. This is now solved for direct DOB→attribute lookups.
Prior semantic failure history (iterations 5–7):
- All k variants (k=10, k=30, k=50) and 5-format semantic queries hit the same ceiling: 1–2 people per DOB out of 7–17 who share it. ColBERT ranks by embedding similarity, not substring match; year-neighborhood documents outrank exact-date matches beyond position 2–3.
Iteration 8 — exact-match index results:
- Ex 11: "hobby of person whose DOB is 0946-07-14" → 1.0 (17/17 hobbies found; was 1/17 in iteration 7)
- Ex 15: "occupation of person whose DOB is 1050-09-16" → 1.0 (7/7 occupations; was 2/7)
- Ex 38: "occupation of person whose DOB is 0918-01-17" → 1.0 (9/9 occupations; was 1/9)
- Ex 29: "grandsons of persons whose DOB is 0918-01-17" → 0.889 (4/5 counts; each person's grandson count now computed)
- Ex 19: "DOB of sibling of person whose DOB is 0905-03-17" → 0.815 (all siblings found via exact index, most DOBs extracted)
- DOB-anchor questions (11 examples in subsample): avg score 0.772 on subsample (up from ~0.15–0.20 in prior iterations)
Remaining DOB challenges (post-exact-index):
- Ex 36: "cousins of persons born 0945-06-12" → 0.400 (gold=['0','1','10','4'], pred=['10']). The index found all people, but then the model only computed one person's cousin count. This is a multi-count fan-out failure at the downstream hop, not a DOB recall failure.
- Ex 46: "father-in-law of friend of person whose DOB is 0881-04-27" → 0.0 (gold=7, pred=1). The exact index provides all 7 people, but then finding ALL their friends and ALL their friends' fathers-in-law is still an incomplete cascade fan-out. The DOB step is now solved; the multi-hop fan-out from DOB is not.
- Ex 24: "sisters of sibling of person whose DOB is 0905-03-17" → 0.800 (gold=['0','1','2'], pred=['1','2']). Missing one count — the model resolved most siblings but missed the case of a sibling with 0 sisters.
Pattern summary: The exact-match index completely fixes DOB recall (the core structural failure). What remains is that DOB-anchored questions requiring 2+ downstream hops (DOB → friends → their attribute) still suffer from the same multi-count fan-out problem that affects all multi-hop questions.
Non-Standard Kinship Terms — Partially Fixed, Partially Still Failing (Updated Through Iteration 6)
Iteration 3 added kinship definitions. Iteration 4 fixed second aunt/uncle. Iteration 5 kept the second aunt/uncle definition and added IMPLICIT RELATIONSHIPS guidance. Iteration 6 added multi-entity enumeration with bilateral ancestor search. Results:
- Fixed: "first cousin once removed" — works in standard cases (iterations 3, 5, 6)
- Fixed: Second aunt/uncle definition (great-grandparent's sibling) — entry 0 (iteration 5): HOW MANY second aunts of Alan Denney → 1.0 ✓. Definition is confirmed correct and stable.
- NEWLY FIXED in iteration 6: "second uncle of Rosina Robey" (iteration 6, entry 17): predicted ['Alvaro Sharma', 'Joesph Sharma'], gold ['Alvaro Sharma', 'Joesph Sharma']. 1.0 ✓. This was 0.0 in iterations 3, 4, AND 5 (entry 16 in iteration 5: wrong entities Mona Bickel / Pearl Keith). The multi-entity enumeration guidance with "search BOTH maternal and paternal branches" fixed this — the model now searches both great-grandparent lines and finds the correct siblings.
- NEWLY FIXED in iteration 6: "female first cousin once removed of Sara Leyva" (iteration 6, entry 38): predicted all 5 correct entities (Lucille Blum, Rowena Harless, Kirsten Blum, Paige Blum, Liane Lange), gold same. 1.0 ✓. Was 0.0 in iteration 5. Multi-entity enumeration caused the model to search all parent's cousins' children systematically.
- Still failing: Deep kinship chains with attribute lookups (intermediate contamination) — see Intermediate Entity Answer Contamination section.
- Pattern: Multi-entity enumeration guidance has been the key unlock for kinship term traversal failures. When the model previously failed on second-uncle/first-cousin-once-removed, the root cause was SINGLE-BRANCH traversal (finding one great-grandparent instead of both lineages). The bilateral-search instruction directly addresses this.
- Kinship term definitions help the model understand WHAT to do; multi-entity enumeration helps it EXECUTE comprehensively by searching multiple ancestor branches. The combination is now working for standard kinship term cases.
Phase 1 Budget Exhaustion on Deep Kinship Chains (New Failure Mode — Iteration 16)
When Phase 1 (entity_finder) has access to exact hobby/occupation tools, it gets many anchor persons (up to 30+ from the index). If the kinship chain from anchor to pivot is 3+ hops, Phase 1 exhausts its max_iters=40 budget attempting multi-hop traversal from too many anchors and returns empty target_entities. The system then falls back to single-phase, which also typically fails for these questions. This is a new failure mode introduced in iteration 16 that did not exist before (previously, Phase 1 found only 1-3 anchors via ColBERT, so traversal budget was not the bottleneck).
Confirmed in ex_id=102 (iteration 16 trace): "How many sisters does the niece of the great-granddaughter of the person whose hobby is gongoozling have?" Phase 1 correctly called search_by_hobby("gongoozling"), then issued 8+ compound ColBERT queries attempting to resolve the 3-hop chain (anchor→great-granddaughter→niece), exhausted its budget, called finish() with no arguments → empty target_entities → single-phase fallback → also returned [] → score=0.0.
The compound query problem: Phase 1 tries ColBERT queries like "niece of the great-granddaughter of gongoozling person" — which ColBERT cannot resolve as a multi-hop kinship query. The correct approach is one-hop-at-a-time: (1) get all gongoozling persons, (2) for each, find their great-granddaughters, (3) for each great-granddaughter, find her nieces. But 30+ anchors × 2 hops = up to 60+ individual lookups, far exceeding max_iters=40.
Implication: The max_iters=40 cap for Phase 1 is now too tight when the anchor population is large AND the chain is deep. Either increase max_iters or reduce the anchor population before Phase 1 traversal.
Entity Questions — No Longer Weakest Type After Iteration 18 Routing Fix
In the iteration 14 subsample (50 examples), entity questions scored dramatically lower than other types:
- Entity (17 examples): avg=0.529 — 6 full failures, 5 partials, only 6 passes
- Count_pivot (14 examples): avg=0.853 — 0 full failures, 10 partials, 4 passes
- Attribute (18 examples): avg=0.757 — 3 full failures, 5 partials, 10 passes
- Count_answer (1 example): avg=1.000 — trivially small sample
Entity question failures:
- Deep multi-hop entity chains (Ex 6, 21, 22, 38): single-phase agent gets lost or returns wrong entities for 3+ hop friend/in-law traversals. Ex 6 returned "cannot be determined" for great-grandmother of father-in-law of friend. Ex 22 returned 2 wrong sister-in-laws for friend-of-friend chain (gold: 5). Ex 38 returned 4 wrong + 1 correct father-in-law for DOB-anchor friend cascade (gold: 7).
- Stochastic second uncle failures (Ex 12, 37 in iter 14; Ex 37 in iter 15): Rosina Robey second uncle (which was stable in iterations 6–12) flipped back to wrong entities ['Mona Bickel','Pearl Keith'] in iter 14 and returned 'Tiffany Robey' (instead of gold 'Latasha Galbreath' for the mother-of-cousin-of-second-uncle variant) in iter 15. This is an LLM stochastic failure — the bilateral-search instruction was working in prior seeds but can degrade on different seeds.
- Carlotta Freeland off-by-one generation (Ex 18 iter 14): the model correctly traced Carlotta→Delinda→Cornelius→Frederic (the great-grandson), but then mistakenly searched for Frederic's SONS (one level too deep) and returned [] when no sons were found. This specific failure was FIXED in iteration 15 (Ex 14/row 7 in iter 15 trace: "How many great-grandsons does Carlotta Freeland have?" → 1.0). The count version is now working.
- This subsample result is important: count_pivot (hybrid two-phase path) is now OUTPERFORMING entity questions (single-phase path). The remaining single-phase entity/attribute failures are the new primary bottleneck.
Iteration 15 trace (50 examples) — question type breakdown:
- The subsample changed seed; cannot directly compare type-level averages. But notable patterns:
- Row 37 (ex_id=90, entity): "mother of cousin of second uncle of Rosina Robey" → pred=['Tiffany Robey'], gold=['Latasha Galbreath']. 0.0 — deep non-standard kinship chain still fails.
- Row 29 (ex_id=72, attribute): Juan Arevalo hobby contamination — 0.0 (FIFTEENTH consecutive failure).
- Row 39 (ex_id=96, attribute): Deon Gall occupation contamination — 0.0 (TWELFTH consecutive failure).
- Row 32 (ex_id=77, attribute): Mother-in-law of DOB 1050-09-16 person — pred=4 (over-enumeration), gold=1. 0.40. Corpus/Prolog mismatch: DOB index found 7 people, Prolog gold used 1.
- Row 7 (ex_id=14): Carlotta Freeland great-grandsons = 1.0. FIXED. This question failed in iterations 3-14 (count form) and is now working.
Iteration 16 trace (50 examples) — question type breakdown (seed changed again):
- entity (20 examples): avg=0.670. Failures: ex_id=23 (great-grandmother of father-in-law of friend of Kermit Clapp — 3-hop entity chain, 0.0), ex_id=35 (Rosina Robey second uncle — 0.0 stochastic), ex_id=55 (male first cousin once removed of cousin of daughter-in-law — 0.0), ex_id=58 (sister-in-law of friend of friend of Demetria Woodland — 0.0, deep friend chain), ex_id=90 (mother of cousin of second uncle of Rosina Robey — 0.0, 16th consecutive failure).
- attribute (9 examples): avg=0.741. Failures: ex_id=72 (Juan Arevalo hobby contamination — 0.0, 16th consecutive failure), ex_id=96 (Deon Gall occupation contamination — 0.0, 13th consecutive failure).
- count_pivot (18 examples): avg=0.701. Failure: ex_id=102 (gongoozling niece sisters — 0.0, new Phase 1 budget exhaustion failure). Partial: ex_id=8 (Forest Benner female cousins — 0.40), ex_id=31 (tea bag collecting — 0.571), ex_id=63 (video editor grandchild great-grandparents — 0.571), ex_id=75 (DOB cousins — 0.60), ex_id=84 (great-grandparent granddaughter parents — 0.667), ex_id=46 (DOB cousin chain — 0.50), ex_id=53 (Deon Gall great-grandfather great-grandchildren — 0.50).
- count_answer (3 examples): avg=1.000 (trivially small, likely stochastic).
- Count_pivot avg (0.701) is now competitive with attribute (0.741) — the exact tools helped several count_pivot questions. Entity remains weakest (0.670).
- Corpus/Prolog mismatch persists: ex_id=13 (video editor, 0.769 — pred found '0','0','3','2','5' but gold is '0','1','2','3','4','5','6','7' — Phase 2 produces many '0' counts for spurious pivot entities), ex_id=63 (video editor, 0.571 — same pattern), ex_id=68 (microbiology, 0.800 — Phase 2 found counts 3,1,6,8,5 of gold 0-11 but missing 10,11,7,9).
Iteration 18 trace (50 examples) — entity questions through Phase 1 (NEW):
- entity (14 examples): avg≈0.695. Phase 1 routing significantly improved entity question performance vs iteration 16 (avg 0.670). Key wins: ex_id=12 (male cousin of great-grandchild of Adelaida Brice: 0.0→1.0 — Phase 1's focused traversal resolved the kinship level confusion that trapped single-phase), ex_id=35 (second uncle of Rosina Robey: 0.0→0.667 — Phase 1 found both gold uncles but also the two gold aunts Mona Bickel/Pearl Keith as over-inclusion; gender filtering not applied). Remaining failures: ex_id=23 (Phase 1 returned empty → fallback single-phase → 0.0; Phase 1 max_iters=40 budget likely exhausted on deep friend chain), ex_id=80 (same 3/12 great-grandchildren of Deon Gall great-grandfather — Phase 1 has same ColBERT ceiling as single-phase for fan-out), ex_id=89 (wrong entities for Forest Benner great-grandchild chain — wrong traversal path in Phase 1), ex_id=90 (wrong entity for Rosina Robey complex second-uncle chain — 18th consecutive failure of this question).
- attribute (10 examples): avg≈0.789. ex_id=103 (occupation of grandfather of great-grandchild of wife of Armando G: 0.0 — wrong entity found at end of chain), ex_id=106 (hobby of grandparent of great-aunt of grandson of Dortha Mcnulty: pred=['finance','research'], gold=['archery','eating'] — intermediate contamination, 17th consecutive failure type).
- count_pivot (22 examples): avg≈0.655. ex_id=29 (cousins of cousin of great-grandchild of great-grandfather of Deon Gall: 0.0 — same wrong entity traversal), ex_id=37 (female second cousins of female second cousin of great-grandson of Carlotta: 0.0 — wrong counts), ex_id=76 (cousins of male second cousin of Reinaldo Pettus: 0.0 — found only 2 pivot entities, both got count=2, gold is ['7','8','10']).
- count_answer (4 examples): avg=0.75. ex_id=14 (Carlotta Freeland great-grandsons: 0.0 — stochastic regression from the 1.0 achieved in iteration 15; unchanged code path).
- Entity questions improved significantly (avg ~0.695 in iter 18 vs 0.670 in iter 16, 0.529 in iter 14 single-phase). Entity is no longer the weakest type. Attribute and count_pivot remain the harder categories at current architecture state.
Iteration 19 trace (50 examples) — GENDER QUALIFIER + SINGULAR FORM additions to EntityFinderSig:
- entity (13 examples): avg=0.716. Key win: ex_id=54 (grandfather of brother of Douglass Libby: Phase 1 now returns only 2 male grandparents instead of all 4 grandparents → 1.0 — the definitional clarification works for direct gender-kinship terms). ex_id=12 (male cousin of great-grandchild of Adelaida Brice: 1.0 — maintained from iteration 18). ex_id=58 (sister-in-law of friend of friend of Demetria Woodland: 0.889 — 4/5 correct). Key regression: ex_id=83 (female first cousin once removed of Sara Leyva: 1.0→0.0 — Phase 1 returned only 'Jesse Dorman', stochastic failure). ex_id=80 (great-grandchild of Deon Gall's great-grandfather: 0.286 — same 2/12 ColBERT ceiling, unchanged). ex_id=93 (father-in-law of friend of DOB person: 0.133 — mostly wrong entities from Phase 1 over-committing to wrong friend set early).
- attribute (10 examples): avg=0.729. ex_id=72 (Juan Arevalo hobby: 0.0 — NINETEENTH consecutive failure). ex_id=96 (Deon Gall occupation: 0.0 — FOURTEENTH consecutive failure). ex_id=28 (occupation of great-grandchild of great-grandfather of Deon Gall: 0.286 — only 2/12 occupations found, ColBERT fan-out ceiling). ex_id=27 (occupation of DOB 1050-09-16: 1.0 — unchanged, exact index works).
- count_pivot (23 examples): avg=0.686. ex_id=37 (female second cousins of female second cousin of great-grandson of Carlotta Freeland: 0.0 — all 4 pivot entities got count=0, Phase 1 likely found wrong pivots). ex_id=29 (cousins of cousin of great-grandchild of great-grandfather of Deon Gall: 0.286 — over-enumerated pivots with wrong entities). ex_id=75 (cousins of DOB 0945-06-12 person: 0.462 — DOB index found all, Phase 2 got many wrong counts, over-enumeration from corpus/Prolog mismatch).
- count_answer (4 examples): avg=0.750. ex_id=15 (male second cousins of Reinaldo Pettus: 0.0 — predicted ['4'], gold=['7']; corpus dead-end). ex_id=0 (second aunts of Alan Denney: 1.0 — Phase 1 now works via entity routing).
- Overall subsample score 0.7073. Valset 0.6021 (−7.7% regression from best 0.6526). The large subsample gain did not generalize — the parent seed baseline was unusually low (0.6123), and the docstring additions to EntityFinderSig changed Phase 1 behavior across ALL entity/count_pivot calls. See Approach 15 for full analysis.
- Key insight from iteration 19: Prompt additions to EntityFinderSig that IMPROVE specific examples can simultaneously DEGRADE others across the broad valset distribution. This is the same risk pattern as DSPy InputFields — any change to Phase 1's docstring modifies its behavior for all calls. The "noun as surname" confusion (round 2: "cousin" as both a relationship and a surname → 48 wrong "Cousin"-surnamed entities for ex_id=4) is a concrete example of unintended side effects from broadly-phrased filter instructions.
DSPy Signature InputField Invasiveness — Critical Constraint (New Finding, Iteration 15)
Adding a new InputField to a DSPy Signature changes the LLM prompt structure for every call through that module, including calls where the field is empty. This caused −14.8% subsample regression in iteration 15 Round 1. Key lessons:
- Never add an optional InputField expecting it to be a no-op when empty — it is not a no-op. The field name, its desc, and its position in the prompt all change the model's behavior.
- Existing Signatures should be treated as frozen in production — modifications to them require evaluating impact across ALL call sites.
- Safe alternatives for passing structured data: (1) expose it as a callable TOOL so the module calls it autonomously; (2) create a new separate Signature (routing to it only when data is available); (3) use a pre-processing module that doesn't touch the existing Signature.
- This constraint directly rules out the "structured anchor field" approach described in iteration 14's memory as a future opportunity (Opportunity 2 in Major Opportunities). That opportunity should be reframed to use tools instead.
Output Format
- Correct: list of plain strings like
["journalist", "musician"] - Contamination: "attribute (person name)" format mostly prevented by current signature, but regressed in entry [44] (7 parenthetical occupations returned)
- Still occurs:
[]empty answer or "Cannot be determined" — ~8 entries in iteration 3 trace (entries 5, 6, 14, 15, 20, 24, 25, 28, 34, 41, 44, 47) score 0.0, mostly due to DOB anchor failures + intermediate contamination + over-exploration without finding targets
Major Opportunities
-
DONE: ANCHOR HINT freetext injection removed (iteration 15, candidate 11, valset 0.6343). The change is now in the live program. Partial recovery from 0.6153→0.6343. Gap to best: 0.6417−0.6343=0.0074. The current program (iteration 15) starts from iteration 13 candidate 10 with ANCHOR HINT removed. This is now the base for next iterations.
-
TRIED (iteration 16) — VALSET REGRESSION: Exact hobby/occupation tools as Phase 1 tools (see Approach 13): Adding
search_by_hobby/search_by_occupationto Phase 1's tool list caused valset regression (0.6343→0.6217, −2.0%) despite strong subsample gain (+4.51%). Root causes: (a) corpus/Prolog mismatch amplified by 100% anchor recall — exact index returns ALL hobby/occupation persons including those outside Prolog's closed-world, generating spurious Phase 2 counts; (b) Phase 1 budget exhaustion for deep chains — with 30+ anchor persons, Phase 1 exhausts max_iters=40 attempting multi-hop kinship traversal and returns empty target_entities. The structural idea remains sound; the implementation needs refinement. Priority next steps: (i) Python-level anchor pre-sampling inforward()— look up anchor persons via the exact index in Python BEFORE Phase 1 (not inside Phase 1), take a random sample of N=10-15, and pass only those to Phase 1 as a simple Python-controlled input (e.g., injecting a subset list into Phase 1's context without DSPy InputFields); (ii) increase Phase 1 max_iters (40→60 or 40→80) to give more budget for deep chain traversal; (iii) cap the tool's return size (return only first 20 matches) to prevent Phase 1 from being overwhelmed. Critical: do NOT implement as a DSPy InputField (iteration 15 catastrophic failure). Critical: do NOT expose these tools to the single-phase react (iteration 13 Round 1 failure). The current program (iteration 16) has these tools in Phase 1 — they may need to be REMOVED if the refinements cannot fix the regression. -
Corpus/Prolog Over-Enumeration in Phase 1 (count_pivot): Phase 1 sometimes finds MORE pivot entities than the Prolog used to generate the gold answer. E.g., Ex 20: found 4 great-grandfathers, gold has 2 — the other 2 exist in the text corpus but weren't in the Prolog query's closed-world scope. Ex 43: found ~20 clinical research associates from the corpus but only a subset appear in the Prolog query result. This produces spurious counts that dilute F1. Mitigation options: (a) deduplicate Phase 1 entity list (already done via set, not helpful here), (b) cap Phase 1 to entities that appear in ≥2 independent search queries (confidence filter), (c) note that this is a fundamental tension between the open-world text corpus and the closed-world Prolog ground truth — may not be fully fixable with the current approach. DON'T OVER-INVEST in fixing this specific sub-problem unless Opportunities 1–2 are already in place and this is the next main failure cluster.
-
Attribute Question Fan-Out — Two-Phase Extension to Attribute Type (TRIED in iteration 17, FAILED — Phase 1 bottleneck confirmed): Iteration 17 added
attribute_deeprouting (attribute questions with ≥2 "of the" + no "person whose" anchor) dispatched to Phase 1 (EntityFinderSig) → Phase 2 (new AttributeAnswerSig). The architecture is correct but Phase 1 is the bottleneck: EntityFinderSig returned the same 3 wrong entities as single-phase for the Deon Gall question (gold=12). SIBLING CROSS-REFERENCE instruction in Phase 1 made it worse (0.0). The approach needs a fundamentally better Phase 1 entity traversal mechanism for attribute question chains, not just the same EntityFinderSig with new instructions. Next attempt options: (a) Add a concrete SIBLING CROSS-REFERENCE worked example to single-phase PhantomWikiQA docstring instead of Phase 1 — so the full-context single-phase can use it without the over-expansion risk; (b) Build a dedicated Phase 1 agent specifically for attribute questions with explicit step-by-step hop-by-hop traversal instructions (separate from EntityFinderSig which was designed for count_pivot); (c) Accept that attribute fan-out is ColBERT-limited (cannot enumerate all N children of a person) and focus gains elsewhere. -
count_answer Single-Phase Under-Counting (Low Priority, Hard Fix): Ex 0 ("How many second aunts does Alan Denney have?" → pred=['0'], gold=['2']) and Ex 6 ("How many male second cousins does Reinaldo Pettus have?" → pred=['4'], gold=['7']) are single-phase failures for simple named-person counting questions. Root cause: corpus dead-ends (some ancestor pages not in the wiki) cause the model to find fewer entities than exist in the Prolog. These are 2/3 count_answer examples failing (0.333 avg). No structural fix exists without a full-corpus traversal index. Not worth investing in — these are inherent corpus coverage gaps.
-
Intermediate Entity Contamination — STILL UNSOLVED but lower impact now: The two-phase approach for count_pivot doesn't help attribute questions (single-phase path). Ex 41 ("What is the occupation of the cousin of the great-grandchild of the great-grandfather of Deon Gall?" → completely wrong occupations) continues to fail in iteration 13. This question has failed in EVERY iteration (8+ consecutive). The hybrid was architecturally designed to fix this for attribute questions too, but Round 1 of iteration 12 showed attribute Phase 1 causes regressions. The only way to fix contamination for attribute questions is a working two-phase for attributes — which requires Opportunity 2 (reliable attribute anchor mechanism) first to ensure Phase 1 entity quality. Record this as a known persistent failure; do not attempt without the attribute anchor mechanism in place.
-
Entity Question Phase 1 Routing — DONE in iteration 18 (valset 0.6526, NEW BEST): Entity questions now route through Phase 1 (EntityFinderSig, question_type='entity'). Subsample +6.5%, valset +1.7% (0.6417→0.6526). ex_id=12 confirmed structural win. Entity avg improved from ~0.529 (iter 14, single-phase) to ~0.695 (iter 18, Phase 1). Entity questions are no longer the weakest type. Remaining entity sub-opportunities: (a) Gender-filter post-processing: ex_id=35 found both uncles and aunts (0.667); regex-detect gender qualifier in question + filter Phase 1 output would recover to 1.0; (b) Phase 1 max_iters increase for entity questions: ex_id=23 returned empty at max_iters=40; a separate entity_finder_entity module with max_iters=50 would help; (c) Phase 1 fan-out under-enumeration: ex_id=80 (Deon Gall great-grandchild chain) still returns 3/12 — same ColBERT ceiling, same as single-phase. No fix known.
-
Always Branch from Current Best (Process Note — CONFIRMED THROUGH ITERATION 24): The best program is now iteration 21, candidate 15 (
codeevolver-20260615073543-c7abb8, valset 0.6867). The current live program is candidate 18 (iteration 24, valset 0.6118 — major regression). The pattern of building on the best valset program (not the latest) has been confirmed correct: iterations 5, 8, 12, 18, and 21 all achieved new bests by branching from the prior best. CRITICAL: iterations 22, 23, and 24 were all accepted on subsample but regressed on valset (−11%, −3.5%, −11% respectively). Always branch from candidate 15 for all next experiments — NOT candidate 16, 17, or 18. Candidates 16, 17, and 18 must all be abandoned as bases. -
Gender-Filter Post-Processing for Phase 1 Entity Output — IMPLEMENTATION APPROACH FAILED (iterations 19-20), RISK ASSESSMENT REVISED by iteration 21: Phase 1 (EntityFinderSig) does not filter returned entities by gender even when the question specifies "uncle" (male), "aunt" (female), "male cousin", etc. In iteration 18, ex_id=35 ("Who is the second uncle of Rosina Robey?") — Phase 1 returned both gold uncles AND gold aunts, F1=0.667. Iteration 19 (GENDER QUALIFIER docstring: −7.7% valset) and iteration 20 (Python
self.retrieve()gender filter: −3.9% subsample, systematic interference) both failed. CRITICAL CONSTRAINT (iteration 20): Any implementation that callsself.retrieve()insideforward()outside a DSPy ReAct module context causes systematic Phase 1 behavior changes — FORBIDDEN. NEW from iteration 21: Iteration 21 confirmed that strictly conditional, logically correct one-line additions to EntityFinderSig generalize positively (+5.2% valset). This revises the risk classification: a ONE-LINE conditional gender instruction in EntityFinderSig's entity block is now MEDIUM RISK (not HIGH RISK). Viable approaches: (1) Add one-line conditional gender rule to EntityFinderSig entity block ("For 'uncle/grandfather/male X' questions, include ONLY male entities; for 'aunt/grandmother/female X' questions, include ONLY female entities") — MEDIUM RISK, test from candidate 15; (2) Create a separateentity_finder_gender_awaremodule instance with a modified Signature for gender-specified entity questions only; (3) Accept current ~0.667 gender performance. Estimated valset impact if solved cleanly: +1-2%. Must branch from candidate 15. -
Phase 2 entity selection for count_pivot — Sequential cap increase FAILED (iter 23, −3.5%), Random sampling also FAILED (iter 24, −11.0%): All Phase 2 entity selection variants have now been tried from candidate 15:
- Sequential top-20 (candidate 15 baseline): valset 0.6867
- Sequential cap=50 (iteration 23): valset 0.6625 (−3.5%)
- Random sample=20 (iteration 24): valset 0.6118 (−11.0%) The root cause of both failures: no entity selection strategy can reliably distinguish Prolog ground-truth pivots from corpus-only spurious pivots. Sequential top-N is biased toward corpus entities; random sampling introduces variance that hurts more than it helps. The Phase 2 entity selection mechanism is exhausted as a tuning target — do not retry further variants of cap/sampling from Phase 1's raw entity list. The next correct approach for count_pivot improvement is confidence threshold post-processing: after ALL Phase 2 calls complete (using the existing cap=20 sequential from candidate 15), only retain count values that appear in ≥2 distinct Phase 2 calls. This collapses spurious one-off corpus/Prolog mismatch values while preserving values that genuinely recur across multiple correct pivots. Python-level, no LM calls, LOW RISK, NOT YET TRIED.
-
TRIED AND FAILED: Phase 1 max_iters=60 for entity questions (iteration 22): Increasing entity Phase 1 budget from 40→60 caused valset regression of −11.0% (0.6867→0.6112). The 40-iteration limit appears to be a BENEFICIAL constraint for entity questions — it prevents the model from exploring wrong paths too deeply. At 60 iterations, the model follows wrong branches more thoroughly, producing worse entity quality on questions that previously resolved correctly at the lower limit. Do NOT retry max_iters=60 for entity Phase 1. The hard entity failures (ex_id=93, ex_id=58, ex_id=90) are NOT solved by giving more budget — they are structural failures (ColBERT ceiling for deep chains, wrong traversal path choices) that require a different mechanism.
-
Tautological Question Short-Circuit (STABLE): The tautological DOB short-circuit rule is stable. No action needed.
Other Important Notes
-
The metric is set-based token-level F1: precision/recall/F1 over normalized answer lists. Partial matches give partial credit. Missing 3 out of 5 answers gives ~0.4 F1, not 0.0. IMPORTANT: The set-based metric means duplicate values in the prediction list are collapsed. E.g., pred=['0','0','2','0'], gold=['0','2'] → F1=1.0 because pred_set={0,2}=gold_set. This means Phase 2 over-computing counts for spurious pivots doesn't always hurt as much as it appears — if the counts happen to match the gold distinct values, F1 is still 1.0.
-
RLMs were tried in a prior unrelated trial and underperformed — not recommended.
-
The model is
gpt-5.4-nanowithreasoning_effort="low"— relatively cheap but capable of multi-step reasoning when well-guided. -
Retrieval uses a remote ColBERTv2 endpoint with 60s timeout and 2 retries. Timeout errors are rare but do occur for very long ReAct chains.
-
PhantomWiki is entirely fictional — no real-world knowledge leakage. The only knowledge source is the ColBERT corpus + the pre-built exact-match DOB index.
-
The subsample seed changes between iterations, introducing variance. Do not over-rotate on individual subsample deltas; trust the direction when multiple examples flip positively and the changes target structural failure modes.
-
Iteration 3 regressed on valset (0.5152 → 0.5074, −1.5%) despite +9.9% subsample gain. BFS guidance caused net regressions on simpler valset questions.
-
Iteration 4 was REJECTED (subsample 0.5666 vs parent baseline 0.5921 on new seed). Regressions on simple questions from prescriptive counting/generation-tracking guidance.
-
Iteration 5 achieved NEW BEST valset: 0.5425 (+5.3% from previous best 0.5152). Branch:
codeevolver-20260615073543-475dd6. Built on iteration 1's clean minimal base. Key wins: HOW MANY FORMAT FIX (structural output bug) + search_wiki_broad (k=30) + minimal targeted additions. -
Iteration 6 achieved valset: 0.5530 (+1.9% from previous best 0.5425). Branch:
codeevolver-20260615073543-7ea7e9. Built on iteration 5. Key wins: MULTI-ENTITY ENUMERATION guidance (bilateral ancestor search fixed second-uncle and female first-cousin-once-removed cases). Key regressions introduced: tautological DOB questions return [] (entry 27), over-counting when multiple grandfathers found (entry 42). -
Iteration 7 valset score 0.5464 is a regression from best (0.5530). Despite subsample gain (+2.8%), the valset went backwards. search_by_date was the main new addition but confirmed ColBERT's hard ceiling — provided no improvement over k=30. Branch:
codeevolver-20260615073543-9293b4. -
Iteration 8 achieved valset: 0.5839 (+5.6% from previous best 0.5530). Branch:
codeevolver-20260615073543-781dad. Built on iteration 6 (candidate 5). Key wins:search_by_date_exactexact-match index (DOB questions went from avg ~0.15→0.772). Side effect: coding agent weakened ATTRIBUTE FAN-OUT and MULTI-ENTITY ENUMERATION guidance. -
Iteration 11 (SKIPPED): Coding agent never ran. Outcome reflection confirmed: (a) Python-determined question_type (never LLM-classified) is the correct approach for two-phase routing; (b) attribute questions showed Phase 1 misclassification was fatal for accuracy; (c) build on candidate 7. Follow-up experiments correctly identified: Python classifier + hybrid (count_pivot only) + attribute index as the roadmap.
-
Iteration 12 achieved NEW BEST valset: 0.6417 (+9.9% from previous best 0.5839). Branch:
codeevolver-20260615073543-4b676c. Built on iteration 8 (candidate 7). Architecture: hybrid two-phase — Python-routed count_pivot questions use Phase 1 (EntityFinderSig) + per-entity Phase 2 (CountComputerSig); all other types use single-phase PhantomWikiQA. -
Current active branch:
codeevolver-20260615073543-62729b(iteration 24, candidate 18). Live program valset score: 0.6118 — major regression from best (−11.0%). NEXT EXPERIMENTS MUST BRANCH FROM CANDIDATE 15 (codeevolver-20260615073543-c7abb8), not candidate 17 or 18. -
Best valset branch:
codeevolver-20260615073543-c7abb8(iteration 21, candidate 15). Best valset score: 0.6867. Previous best:codeevolver-20260615073543-c10f8d(iteration 18, candidate 13, 0.6526). -
Current architecture (iteration 24, candidate 18 — live program, MAJOR REGRESSION): Same as candidate 15 (iteration 21, best) but with two changes: (1) Phase 1 output deduplication (order-preserving seen-set before Phase 2 loop); (2) count_pivot Phase 2 random sampling —
random.sample(entities, 20)with per-question deterministic seed (random.Random(hash(question))), instead of sequentialentities[:20]. Entity questions still useentity_finder(max_iters=40), Phase 2 cap remains 20 (cap was reverted to 20 from the cap=50 change in iteration 23). Everything else is unchanged from candidate 15. -
Best architecture (iteration 21, candidate 15):
PhantomWikiReActwith Python-level_classify_question()routing. entity → Phase 1 EntityFinderSig (max_iters=40) with RECIPROCAL COUSINHOOD and DOB/ATTRIBUTE MULTI-ANCHOR EXPANSION rules, returning target_entities, fallback to single-phase if empty. count_pivot → simple anchor bypass (for direct patterns) OR Phase 1 EntityFinderSig (max_iters=40) with HOP-BY-HOP TRAVERSAL rule + CountComputerSig per entity (max_iters=15, cap=20) with FINDING ANCESTORS OF THE PIVOT rule. attribute/count_answer → single-phasePhantomWikiQA(max_iters=50, unchanged). Three retrieval tools:search_wiki(k=10),search_wiki_broad(k=50),search_by_date_exact. NO hobby/occupation tools. EntityFinderSig docstring does NOT have iteration 19 GENDER QUALIFIER or SINGULAR FORM additions. Candidate 15 branches from candidate 13 (the same clean base used for all best programs). NOTE: Phase 2 cap in candidate 15 is 20 (NOT 30 — the memory previously stated 30, which was a documentation error; the diff confirms 20→30 was a change made in iteration 22). -
Subsample score by question type (iteration 12 trace, 50 examples): entity (18 examples) avg=0.817, attribute (13 examples) avg=0.714, count_pivot (16 examples) avg=0.668, count_answer (3 examples) avg=0.333. Overall: 0.7134.
-
count_pivot two-phase is structurally working — per-entity Phase 2 calling eliminates enumerate-then-collapse for count_pivot. The remaining count_pivot failures are Phase 1 quality issues (under/over enumeration of pivots), not Phase 2 issues.
-
Corpus/Prolog mismatch confirmed: The PhantomWiki text corpus has more entities with certain attributes than the Prolog query closure used to generate gold answers. E.g., a DOB date in the corpus may have 7 people, but the Prolog question was generated from a world with only 1 person at that DOB. This causes over-enumeration: finding too many pivots → spurious counts in Phase 2 output. This is a fundamental limitation of comparing against a closed-world Prolog ground truth using an open-world text corpus.
-
search_by_date_exact is a structural breakthrough (iteration 8): The exact-match DOB index bypasses ColBERT's semantic limitation entirely. The design principle — when a retrieval limitation is structural, a code-level pre-built index outperforms any prompt workarounds — applies equally to hobby/occupation indices.
-
Key validated insight: Branching from the BEST VALSET program (not the latest) has been correct in every iteration that achieved a new best (5, 8, 12). Always branch from the best-performing program, not the most recent.
-
HOW MANY FORMAT BUG is confirmed fixed (since iteration 5): Stable.
-
MULTI-ENTITY ENUMERATION is confirmed to fix bilateral ancestor traversal (since iteration 6): Stable in iteration 12 traces (Ex 37: female first cousin once removed of Sara Leyva = 1.0; Ex 31: female first cousin once removed of grandparent of Sam Highsmith = 1.0).
-
k=50 for broad search in iteration 12: Note the current architecture uses k=50 for search_wiki_broad (not k=30 as in iterations 6-10). This change was made in iteration 12's Round 1. No confirmed benefit/harm yet vs k=30.
-
Workspace tools (
note_finding,recall_findings) are NOT in the current codebase and have not been tested on this new base. Not recommended without a code-level redesign. -
Overfitting note: The subsample (50 rows) is noisy and varies by seed. The track record (iterations 1–12) shows the most reliable valset improvements come from structural code-level changes (new tools, architectural changes), not prompt additions. Iteration 12's +9.9% valset gain came from the architectural hybrid — the largest structural change since the DOB exact index. Treat subsample deltas < +5% as inconclusive; require a clear structural mechanism before trusting.
-
Incomplete fan-out + corpus/Prolog mismatch are the twin dominant failure patterns for count_pivot: (1) Phase 1 under-enumeration (finds too few pivots → missing counts) — partially improved by iteration 16 exact tools but not fully solved due to budget exhaustion on deep chains. (2) Corpus/Prolog mismatch (finds too many pivots from corpus vs Prolog's closed-world → spurious counts). These two failure modes are in tension: better anchor recall (via exact tools) amplifies over-enumeration. Python-level anchor pre-sampling (take a random N=10-15 from the exact index, not all) is the next structural attempt to balance the two.
-
Two-phase cost note: count_pivot questions now consume up to 40 + 20×15 = 340 LM iterations in the worst case, vs 50 for single-phase. In practice (from reflection), Phase 2 uses ~5 iters per entity and Phase 1 finds ~10 entities, so practical cost is ~40 + 10×5 = 90 LM iterations per count_pivot question. At 30% of distribution, total cost increase is ~(90-50)*0.3 = 12 extra iterations per question on average. Acceptable given the valset improvement.
-
Ex 41 (occupation of cousin of great-grandchild of great-grandfather of Deon Gall) — TENTH consecutive failure: pred=['financial planner', 'physiotherapist', ...] (all wrong), gold=['building control surveyor', 'dancer', ...]. This specific question has failed in every single iteration (3 through 13). It is now on the single-phase path (attribute type). The model finds wrong entities (gets off the right traversal chain at the great-grandchild or cousin hop). This is the clearest evidence of the remaining intermediate contamination problem for attribute questions.
-
Iteration 9 (SKIPPED) — key insight still valid: Adding ANY further prompt instructions to the single-phase beyond what's in iteration 8 caused regressions. The hybrid architecture (iteration 12) succeeded precisely by NOT adding prompt instructions to the single-phase, but by routing count_pivot to a structurally different path.
-
Iteration 13 (ACCEPTED but valset regression): Python-level simple anchor bypass for "does the person whose hobby/occupation is Y have?" is structurally sound and should be kept. ANCHOR HINT injection for complex chains caused the valset regression (0.6417→0.6153, −4.1%). Branch:
codeevolver-20260615073543-785aac, candidate 10. -
LLM tool misuse is a proven risk: Iteration 13 Round 1 confirmed that exposing new tools to ReAct agents causes them to use those tools on inappropriate question types (−4.4% subsample). Python-level dispatch is safer than LLM-level tool access for structured index lookups tied to specific question patterns. Exception: exposing attribute tools specifically to Phase 1 only (not to the single-phase react) would be safe because Phase 1 is only invoked for count_pivot questions with attribute anchors.
-
Phase 2 entity cap = 30 (iteration 13, retained through iteration 15): low-risk improvement, maintained in all future iterations.
-
Simple anchor bypass mechanism (iteration 13, retained through iteration 15): The
is_simple_anchorregex correctly identifies direct attribute-anchor count_pivot questions and bypasses Phase 1 entirely. Retained and working. -
Iteration 14 (REJECTED — stochastic noise): Removed ANCHOR HINT injection block. −0.25% (within noise). Branch:
codeevolver-20260615073543-74b3a9. Architecturally correct but rejected. Retried successfully in iteration 15. -
Iteration 15 (ACCEPTED, valset 0.6343): Two rounds: Round 1 (DSPy InputField anchor_hint) −14.8% subsample FAILED → reverted. Round 2 (clean ANCHOR HINT removal only) +2.93% subsample ACCEPTED. Valset partial recovery: 0.6153→0.6343. Branch:
codeevolver-20260615073543-f280a2, candidate 11. The ANCHOR HINT freetext injection is now removed from the live program. -
DSPy InputField invasiveness — CRITICAL constraint confirmed in iteration 15: Adding any new InputField to a DSPy Signature changes the LLM prompt structure for EVERY call, even when the field is empty. Round 1 proved this with −14.8% regression from adding
anchor_hint: str = dspy.InputField(...). Do NOT add new InputFields to existing Signatures. Safe alternatives: (1) expose functionality as callable tools; (2) create a separate Signature and route to it only when needed; (3) pre-processing module that doesn't touch the Signature. -
Carlotta Freeland great-grandson count — FIXED in iteration 15 (Row 7/ex_id=14: 1.0). After 12 consecutive failures (iterations 3–14), the count form "how many great-grandsons does Carlotta Freeland have?" now returns the correct answer of ['1'].
-
Juan Arevalo hobby chain (ex_id=72) — 16+ consecutive failures: "hobby of great-uncle of niece of second uncle of Juan Arevalo" → always wrong (pred includes wrong hobbies of intermediate entities). Not in iteration 17 subsample. No prompt or architecture change has fixed this. Structural dead-end with current single-phase and with Phase 1 (EntityFinderSig) approach.
-
Deon Gall occupation chain (ex_id=96) — 13th consecutive failure: "occupation of cousin of great-grandchild of great-grandfather of Deon Gall" → wrong occupations. Not in iteration 17 subsample. Same contamination pattern as Juan Arevalo.
-
Corpus/Prolog mismatch for DOB-anchor attribute questions (confirmed iter 15, Row 32/ex_id=77): "mother-in-law of person whose DOB is 1050-09-16" → gold=['Jada Paez'] (1 person), pred=['Jada Paez','Pauletta Green','Sofia Corwin','Goldie Scherer'] (4 people). The DOB exact-match index found all people born on that date in the corpus (multiple), but the Prolog ground truth only counted 1. This is a known corpus/Prolog mismatch. The single-phase react has no way to know which person to pick; it computes mother-in-law for all of them. The only mitigation would be to cap the DOB index results or a better Prolog alignment.
-
Phase 1 under-enumeration confirmed in iteration 15 trace (Rows 6, 11, 17, 20, 41, 43): For hobby/occupation-anchor complex chain count_pivot questions, Phase 1 still finds only 1–3 pivot entities when the gold set has 5–9. Iteration 16 attempted to fix this by adding
search_by_hobby/search_by_occupationas Phase 1 tools — it caused valset regression (see Approach 13, Opportunity 2). The structural fix needs refinement: Python-level pre-sampling or Phase 1 max_iters increase before re-trying. -
Iteration 16 (ACCEPTED, valset 0.6217 — regression): Added
search_by_hobbyandsearch_by_occupationto Phase 1's tool list + updatedEntityFinderSigdocstring. Subsample: +4.51% (0.6829→0.7137). Valset: 0.6343→0.6217 (−2.0%). Branch:codeevolver-20260615073543-1b655b. Candidate 12. The valset regression was caused by: (a) corpus/Prolog mismatch amplified by 100% anchor recall; (b) Phase 1 budget exhaustion for 3+ hop kinship chains from many anchor persons. Best program remains iteration 12 candidate 9 (0.6417). The current live program (iteration 16) is a regression from the best program — architect should consider branching from iteration 12 candidate 9 or iteration 15 candidate 11 for next experiments. -
Corpus/Prolog mismatch is now confirmed as the dominant count_pivot ceiling: The exact hobby/occupation index amplified this problem (100% anchor recall → many spurious Phase 2 pivots). The DOB index has the same issue but less severely because DOB-anchor questions are typically simpler (direct lookup rather than chained). For hobby/occupation questions with large populations (microbiology: 3,273; video editor: 813+), even with the correct tool-call strategy, over-enumeration from the corpus dominates.
-
Phase 1 max_iters=40 is too tight for deep chains with many anchors: With 30 anchor persons and a 3-hop chain (anchor→hop1→hop2=pivot), Phase 1 needs 30 × 2 = 60+ individual kinship lookups. At max_iters=40 it cannot complete the traversal. Either increase Phase 1 max_iters or reduce the anchor count before Phase 1.
-
Juan Arevalo hobby chain (ex_id=72) — 21+ consecutive failures: No change through iteration 21. pred=['mineral collecting','trainspotting','shortwave listening','sand art','crystals'] in various iterations (attribute, single-phase path). No prompt or architectural change has ever fixed this.
-
Deon Gall occupation chain (ex_id=96) — 15+ consecutive failures: No change through iteration 21. pred in iteration 21 = ['clothing technologist','tour manager','sales professional','presenter','physiotherapist','retail buyer'], gold=['building control surveyor','dancer','marine scientist','public relations officer','risk analyst','social worker','tax inspector','town planner']. All wrong. Attribute single-phase path — intermediate contamination. No prompt or architectural change has ever fixed this.
-
Deon Gall 2-hop occupation (ex_id=28 in iter 17, gold=12): Dispatched to attribute_deep path in iteration 17 — Phase 1 returned same 3 entities as single-phase → 0.0. Phase 1 cannot enumerate all 12 great-grandchildren. This is the same ColBERT fan-out limitation that prevents ex_id=96 from working.
-
Iteration 17 (REJECTED, valset N/A): Added
attribute_deeprouting with Phase 1 (EntityFinderSig) + Phase 2 (AttributeAnswerSig). Both rounds regressed: Round 1 (−4.7%): Phase 1 under-enumerates attribute chains exactly like single-phase. Round 2 (−6.0%): SIBLING CROSS-REFERENCE in Phase 1 caused over-expansion into wrong branches. The attribute_deep routing concept is architecturally correct but Phase 1 is the bottleneck. Branch:codeevolver-20260615073543-d912ab. Built on candidate 9 (the correct base per memory guidance). Reversion to parent (candidate 9) means current live program reverted to iteration 12 candidate 9 (valset 0.6417). -
SIBLING CROSS-REFERENCE instruction is harmful in Phase 1: Tested in iteration 17 Round 2 in EntityFinderSig COMPLETENESS section. Caused Phase 1 to follow arbitrary sibling chains into wrong branches. If this concept is tried in the future, apply it only to the single-phase
PhantomWikiQAwhere the full question context constrains expansion, NOT to Phase 1 where there is no full-answer context. -
Attribute_deep classification (≥2 "of the" + no "person whose"): This classifier correctly identifies 3 questions in the iteration 17 subsample. The classification rule itself is sound. The two-phase architecture for this type is also sound. The bottleneck is Phase 1 entity enumeration quality.
-
Iteration 18 (ACCEPTED, valset 0.6526 — NEW BEST): Added entity question routing through Phase 1 (EntityFinderSig, question_type='entity') with fallback to single-phase when Phase 1 returns empty. EntityFinderSig docstring strengthened with one-hop-at-a-time guidance. Subsample: +6.5% (0.6764→0.7204). Valset: 0.6417→0.6526 (+1.7%). Branch:
codeevolver-20260615073543-c10f8d. Candidate 13. Key wins: ex_id=12 (0.0→1.0, male cousin of great-grandchild), ex_id=35 (0.0→0.667, second uncle — over-includes aunts). Still failing: ex_id=23 (Phase 1 empty→0.0), ex_id=80 (3/12 Deon Gall great-grandchildren — same ColBERT ceiling), ex_id=89 (wrong entity traversal), ex_id=90 (18th consecutive failure of Rosina Robey mother-of-cousin-of-second-uncle). -
Phase 1 over-inclusion for gender-qualified entity questions (found in iteration 18): When the question asks for "uncle" (male), Phase 1 returns both male uncles AND female aunts (siblings at the same kinship level), giving F1=0.667 instead of 1.0.
-
Carlotta Freeland great-grandson count (ex_id=14) — stochastic regression in iteration 18: Was 1.0 in iterations 15-17. In iteration 18, pred=['0'], gold=['1'] → 0.0. Seed-driven noise. Resolved again in iteration 19 (pred=['1'], 1.0).
-
Iteration 19 (ACCEPTED on subsample, valset REGRESSION −7.7%): Added SINGULAR FORM ≠ UNIQUE note and GENDER QUALIFIER definitional section to EntityFinderSig docstring (built on candidate 13, iteration 18). Subsample: +15.5% (0.6123→0.7073). Valset: 0.6526→0.6021 (−7.7%). Branch:
codeevolver-20260615073543-ebe82e. Candidate 14. Key wins on subsample: ex_id=54 (grandfather of Douglass Libby's brother → 1.0, definitional gender clarification works), ex_id=58 (sister-in-law of friend of friend → 0.889). Key failure: ex_id=83 (female first cousin once removed of Sara Leyva → 0.0 in round 3 from ~0.6 in rounds 1/2 — stochastic regression from narrow single-entity return 'Jesse Dorman'). The +15.5% subsample gain is spuriously large: (1) parent seed produced an unusually low baseline 0.6123 (compare to iteration 18's subsample 0.7204 on a different seed), making the delta artificially inflated; (2) the definitional instructions changed Phase 1's behavior across ALL entity/count_pivot calls, producing wins on the specific subsample examples but losses on the broader valset distribution. Best program remains iteration 18, candidate 13. Current live program (candidate 14) must not be used as base for next experiments — branch from candidate 13. -
Cautionary finding from iteration 19: A +15.5% subsample gain can coexist with a −7.7% valset regression when (a) the parent baseline is unusually low due to seed variance, and (b) the change modifies shared module behavior (EntityFinderSig docstring) in ways that have mixed effects across the full distribution. The subsample is not a reliable signal when the parent baseline is more than 10% below the known best program's subsample score on the same seed. Trust structural mechanism changes; distrust large prompt-tuning gains.
-
SIBLING CROSS-REFERENCE instruction is confirmed harmful in Phase 1 and has NOT been tested in single-phase: Still a viable (untested) approach for single-phase PhantomWikiQA — a concrete worked example in the single-phase docstring showing how to find siblings of intermediate entities could help attribute fan-out without the over-expansion risk (the full question context in single-phase constrains expansion naturally).
-
CRITICAL ARCHITECTURAL CONSTRAINT (iteration 20, confirmed both rounds): Calling
self.retrieve(),self.search_wiki(), or any ColBERT/DSPy retrieval method insideforward()OUTSIDE of a DSPy ReAct module context causes systematic (non-stochastic) Phase 1 behavior changes. The exact mechanism is unknown (ColBERT server state pollution, DSPy tracing side effects, or similar), but the consequence is identical: specific entity questions (ex_id=35, ex_id=55) that previously scored 1.0 consistently drop to 0.0. No ad-hoc retrieval calls may be placed inforward()for gender checking, entity validation, or any other post-processing purpose. This constraint rules out the "pronoun-based gender filter via ColBERT lookup" approach documented in iteration 19's follow-ups and the current memory. -
Iteration 20 (REJECTED, −3.9% subsample): Two rounds of gender post-processing for entity questions, both rejected. Round 1: entity_finder max_iters 40→50 + gender filter using 10 passages from search_wiki, threshold 1.2. Round 2: gender filter only using first passage from self.retrieve(), threshold 1.5. Both caused identical failures on ex_id=35 and ex_id=55 — confirmed the DSPy pipeline state interference. Current live program reverted to candidate 13. Best valset remains 0.6526 (candidate 13, iteration 18).
-
Iteration 20 trace key observations (50 examples, child avg=0.6802 vs parent 0.7190):
- ex_id=35 (second uncle of Rosina Robey): 1.0 (parent) → 0.0 (child), pred=['Marcus Robey'] — systematic gender-filter interference
- ex_id=55 (male first cousin once removed): 1.0 (parent) → 0.0 (child), pred=['Hunter Nicholas','Bryan Fernandez'] — same interference
- ex_id=72 (Juan Arevalo hobby): 0.0 — 20th consecutive failure (pred=['mineral collecting','trainspotting'], gold=['antiquities'])
- ex_id=80 (Deon Gall great-grandchild entity): 0.400 (5/12 via Phase 1) — ColBERT fan-out ceiling unchanged
- ex_id=7 (cousins of cousin of female second cousin): 0.000 — over-enumeration, 10 wrong counts predicted for gold=['3']
- ex_id=77 (mother-in-law of DOB 1050-09-16 person): 0.286, pred=6 entities, gold=1 — corpus/Prolog mismatch
- ex_id=107 (female cousin of Jona Markowitz): 1.0 — entity gender question working correctly on parent (candidate 13)
-
Next structural improvement candidates (all should branch from candidate 15,
codeevolver-20260615073543-c7abb8): (i)Increase Phase 1 max_iters from 40→50-60 for entity questions via— TRIED in iteration 22, FAILED (valset −11%). Do NOT retry; (ii)entity_finder_entityPhase 2 cap increase (20→50)— TRIED in iteration 23, FAILED (valset −3.5%). Sequential top-N biased against Prolog entities. Do NOT retry; (iii) Python-level Phase 2 RANDOM sampling (LOW RISK) —random.sample(entities, min(20, len(entities)))instead ofentities[:20]; (iv) Confidence threshold post-processing — only include Phase 2 count values appearing in ≥2 Phase 2 calls; (v) One-line conditional gender rule in EntityFinderSig entity block (MEDIUM RISK); (vi) Sibling cross-reference worked example in single-phase PhantomWikiQA docstring only (NOT Phase 1). -
Iteration 21 (ACCEPTED, NEW BEST valset 0.6867, +5.2%): Four additive docstring rules to EntityFinderSig and CountComputerSig. Built on candidate 13. Branch:
codeevolver-20260615073543-c7abb8, candidate 15. Subsample: +3.9% (0.6883→0.7154). Valset: 0.6867 (NEW BEST). Key win: ex_id=81 (1.0, RECIPROCAL COUSINHOOD). Key partial wins: ex_id=30, 26, 40 (all 0→1.0, HOP-BY-HOP TRAVERSAL). Key regressions: ex_id=46 (0.86→0.50, Phase 1 budget consumed by hop-by-hop), ex_id=42 (1.0→0.67, stochastic noise). Current live program IS candidate 15. -
Iteration 21 trace key observations (50 examples, child avg=0.7154 vs parent 0.6883):
- ex_id=81 (cousin of grandchild of Eldon Ridenour): 0.333→1.0 — RECIPROCAL COUSINHOOD definitively fixed. Phase 1 returned all 5 grandchildren correctly.
- ex_id=65 (Geraldine Ruch hobby): 0.000 — 21st+ consecutive failure (pred=['shortwave listening','sand art','crystals','slot car racing'], gold=['botany']). Contamination unchanged, single-phase attribute path.
- ex_id=96 (Deon Gall occupation of cousin of great-grandchild): 0.000 — 15th+ consecutive failure (pred 6 wrong occupations). Single-phase attribute contamination.
- ex_id=106 (Dortha Mcnulty hobby of grandparent of great-aunt of grandson): 0.000 — 18th+ consecutive failure (pred=['research','finance'], gold=['archery','eating']). Single-phase attribute contamination.
- ex_id=4 (DOB multi-anchor entity, male cousin of nephew of grandson): 0.000 — Phase 1 still budget-exhausted with 7+ DOB anchors (pred 4 wrong entities, gold 8). Multi-anchor expansion helps but max_iters=40 insufficient.
- ex_id=93 (DOB father-in-law of friend): 0.143 (1/7) — Phase 1 found only 1 correct father-in-law despite multi-anchor expansion instruction. 7 DOB anchors + 2-hop chain exhausts budget.
- ex_id=88 (company secretary grandfather female first cousins once removed): 0.250 — Phase 2 called 20 times, almost all return '0'. Phase 1 over-enumerates from large company-secretary corpus population.
- ex_id=13 (video editor count_pivot): 0.222 — Phase 2 called 5 times, all return '0'. Phase 1 found pivots via hop-by-hop but Phase 2 can't find cousins of each great-grandchild. Distinct failure: Phase 2 traversal failure, not Phase 1.
- ex_id=24 (DOB occupation, 15 occupations): 1.0 — DOB exact-match working perfectly with multi-anchor expansion.
- ex_id=79 (DOB occupation, 9 occupations): 1.0 — Same.
- ex_id=34 (DOB sibling DOBs, 11 DOBs): 1.0 — Perfect.
- ex_id=58 (Demetria Woodland sister-in-law of friend of friend): 0.000 — Phase 1 returned only 1 wrong entity. Deep 3-hop friend chain.
- ex_id=20 (stone collecting nephew, 9 gold values): 0.615 — Phase 2 called 20 times, got {0,1,2,3} of {0,1,2,3,4,5,6,7,8}. Corpus/Prolog mismatch: many spurious '0' pivots.
- ex_id=85 (farm manager great-grandchild great-grandsons, 7 gold values): 0.600 — Phase 2 called 20 times, got {0,2,5} of {0,1,2,3,4,5,6}.
- ex_id=99 (crystals hobby great-grandsons, 9 gold values): 0.615 — Phase 2 called 20 times, got {0,1,2,3} of {0,1,2,3,4,5,6,7,8}.
-
Over-enumeration + corpus/Prolog mismatch is now the dominant count_pivot ceiling: With HOP-BY-HOP traversal, Phase 1 finds correct pivots more reliably, but ALSO finds more spurious corpus pivots. Phase 2 is called ~15-20 times per count_pivot question (capped at 30). Most spurious pivot calls return '0', and the prediction set {0, few non-zeros} is compared to gold set {0,1,2,...,8}. The model achieves good F1 for the '0' values (many spurious pivots return '0' which happens to match some gold '0' values) but misses the non-zero gold values (3,4,5,6,7,8) entirely if no real pivot produces that count. This explains the 0.6 F1 ceiling on large-population hobby/occupation count_pivot questions. The fix: Python-level cap on Phase 2 calls (e.g., random sample N=8-12 unique pivots from Phase 1 output) would reduce spurious '0' calls while keeping the real pivot calls.
-
CRITICAL ARCHITECTURAL CONSTRAINT (iteration 21 confirms relaxation): Previous iterations treated all EntityFinderSig docstring additions as HIGH RISK after iteration 19's −7.7% valset regression. Iteration 21 revises this: conditional and logically correct additions generalize positively. The key distinguisher: (a) iteration 19's GENDER QUALIFIER was a broad behavioral filter that changed entity selection semantics for ALL entity/count_pivot calls; (b) iteration 21's additions are conditional ("when N anchors found", "for count_pivot questions") and implement logically necessary reasoning (reciprocal cousinhood is always true; hop-by-hop is how kinship traversal works). New rule: Additions that are logically correct (not just heuristically useful) and strictly conditional (only activate on matching patterns) are LOW-TO-MEDIUM RISK. Additions that broadly change selection semantics remain HIGH RISK.
-
Next structural improvement candidates (all should branch from candidate 15,
codeevolver-20260615073543-c7abb8): (i)Separate— TRIED in iteration 22, FAILED (valset −11.0%). Do NOT retry; (ii)entity_finder_entitymodule with max_iters=50-60Phase 2 cap 20→50— TRIED in iteration 23, FAILED (valset −3.5%). Sequential top-N biased against Prolog entities for large populations. Do NOT retry sequential cap increase; (iii) Python-level Phase 2 RANDOM sampling (LOW RISK) —random.sample(entities, min(20, len(entities)))instead ofentities[:20]. Gives Prolog entities proportional selection chance regardless of ColBERT rank. Most promising next step; (iv) Confidence threshold post-processing — only include Phase 2 count values appearing in ≥2 distinct Phase 2 calls. Python-level, no LM calls; (v) One-line conditional gender rule in EntityFinderSig entity block — MEDIUM RISK, would fix ex_id=35 (~+1-2% valset); (vi) Sibling cross-reference worked example in single-phase PhantomWikiQA docstring only (NOT Phase 1). -
Iteration 22 (ACCEPTED on subsample, MAJOR VALSET REGRESSION −11.0%): Two changes from candidate 15: (1)
entity_finder_entity(max_iters=60) for entity questions; (2) Phase 2 cap 20→30 for count_pivot. Subsample: 0.6208→0.6382 (+2.8%). Valset: 0.6867→0.6112 (−11.0%). Branch:codeevolver-20260615073543-dfc4b7, candidate 16. The valset regression is driven by the max_iters=60 change for entity Phase 1 — increasing budget makes Phase 1 explore wrong branches more deeply on questions that previously worked correctly at max_iters=40. The Phase 2 cap change cannot be isolated. Current live program is candidate 16 (regression). Best program remains candidate 15 (0.6867). All next iterations MUST branch from candidate 15. -
Iteration 22 trace key observations (50 examples, child avg=0.6382 vs parent 0.6208):
- ex_id=65 (Geraldine Ruch hobby): 0.000 — 22nd+ consecutive failure. pred=['shortwave listening','sand art','crystals','slot car racing'], gold=['botany']. Single-phase attribute contamination.
- ex_id=90 (Rosina Robey mother of cousin of second uncle): 0.000 — 19th+ consecutive failure. pred=['Babara Ramage'], gold=['Latasha Galbreath']. Entity Phase 1 still cannot traverse this complex chain.
- ex_id=93 (DOB father-in-law of friend): 0.167 — marginal improvement from 0.143 (iter 21). max_iters=60 found 1/7 correct father-in-laws. 7 DOB anchors + 2-hop still exhausts budget even at 60 iterations.
- ex_id=35 (Rosina Robey second uncle): 0.000 — pred=['Mona Bickel','Pearl Keith'] (gold aunts), gender over-inclusion persists.
- ex_id=14 (Carlotta Freeland great-grandsons): 0.000 — stochastic regression from iter 21's 1.0. Unchanged code path, seed variance.
- ex_id=37 (female second cousins of female second cousin of great-grandson of Carlotta): 0.800 — pred=['4','0','0','3'], gold=['3','4']. Phase 2 cap=30 helped find both non-zero values.
- ex_id=88 (company secretary grandfather female first cousins once removed): 0.500 — pred=['0','0','0','0','0','1'], gold=['0','1','2','3','4','6']. Improved from 0.250 (iter 21) — Phase 2 cap=30 found more pivot entities, but still only {0,1} of gold {0,1,2,3,4,6}.
- ex_id=53 (Deon Gall great-grandfather great-grandchildren count): 0.500 — pred=['3','3','3','4'], gold=['12','3']. Only value '3' matches; '4' is wrong, '12' is missed. Phase 2 cap=30 didn't help the 12-grandchild ColBERT ceiling.
- ex_id=58 (sister-in-law of friend of friend of Demetria Woodland): 0.000 — pred=['Melina Hayden','Alyssa Truong'], gold=['Alana Courtney','Daniele Frantz','Genevieve Avalos','Hope Libby','Natacha Pepin']. Deep 3-hop friend chain still fails despite max_iters=60.
- ex_id=109 (daughter-in-law of DOB 0946-07-14 person): 0.846 — pred found 5/8 correct. DOB exact-match working well for entity questions.
-
Iteration 23 (ACCEPTED on subsample, VALSET REGRESSION −3.5%): Two changes from candidate 15: (1) Phase 1 output deduplication (order-preserving seen-set); (2) Phase 2 cap 20→50 for count_pivot. Subsample: 0.6906→0.7392 (+7.0%). Valset: 0.6867→0.6625 (−3.5%). Branch:
codeevolver-20260615073543-8feff1, candidate 17. The cap increase from 20→50 adds more Phase 2 calls for large entity sets but introduces more spurious count values from the corpus/Prolog mismatch. Critical finding: for large occupation/hobby populations (95-130+ Phase 1 entities), sequential top-N Phase 2 selection is systematically biased — ColBERT ranks corpus entities highest, but Prolog ground-truth entities with distinctive non-zero counts may be ranked 50th+ and missed entirely (ex_id=101: 48/50 Phase 2 calls return '0'). Current live program is candidate 17 (regression). Best program remains candidate 15 (0.6867). All next iterations MUST branch from candidate 15. -
Iteration 23 trace key observations (50 examples, child avg=0.7392 vs parent 0.6906):
- ex_id=68 (microbiology hobby, 79 Phase 1 entities): 0.74→0.86 — structural win. cap=50 found value '10' (friends) that cap=20 missed. pred_unique: {0,1,2,3,4,5,6,7,10} vs gold {0,1,2,3,4,5,6,7,8,9,10,11}.
- ex_id=75 (DOB cousins, 15 Phase 1 entities): 0.50→0.80 — structural win. cap=50 processed all 15 entities, found all 4 gold values (0,1,10,4). Extra values {5,6} are over-prediction.
- ex_id=91 (axe throwing hobby, 130 Phase 1 entities): 0.800→0.667 — structural regression. cap=50 entities 21-50 introduced spurious count values '4' and '8' (corpus entities not in Prolog's scope). pred_unique: {0,2,4,8} vs gold {0,2}.
- ex_id=101 (clinical research associate occupation, 50+ Phase 1 entities): 0.444 — persistent failure. 48 of 50 Phase 2 calls return '0'. Only values {0,2} found vs gold {0,1,2,3,4,5,7}. The Prolog entities with counts 1,3,4,5,7 are NOT in the top-50 ColBERT results — sequential selection fails systematically for large populations.
- ex_id=33 (financial controller occupation, 95 Phase 1 entities): 0.714 — partial but capped. Even at cap=50, gold entities with counts {5,6,7,8} are not in top-50. pred_unique: {0,1,2,3,4} vs gold {0,1,2,3,4,5,6,7,8}.
- ex_id=29 (cousins of cousin of great-grandchild of great-grandfather of Deon Gall): 0.000 — Phase 1 still returns wrong entities for this deep chain. pred: {4,5,7,8} vs gold {1,3}. Persistent Phase 1 traversal failure, unrelated to cap change.
- ex_id=49 (occupation of grandparent of mother-in-law — attribute): 0.000 — completely wrong occupations predicted (planning/design/library fields vs camera/clothing/financial adviser etc.). Persistent attribute single-phase contamination.
- ex_id=89 (female cousin of grandchild of great-grandchild of Forest Benner): 0.000 — wrong entities. Phase 1 traversal still fails for this complex chain. Entity Phase 1 persistent failure.
- ex_id=90 (mother of cousin of second uncle of Rosina Robey): 0.000 — pred=['Mona Bickel'] vs gold=['Latasha Galbreath']. 20th+ consecutive failure. Entity Phase 1 persistent failure.
- ex_id=106 (hobby of grandparent of great-aunt of grandson of Dortha Mcnulty): 0.000 — pred=['finance','research'] vs gold=['archery','eating']. 23rd+ consecutive failure. Attribute single-phase contamination.
- ex_id=65 (Geraldine Ruch hobby contamination): NOT in subsample (seed variance). Persistent failure assumed based on prior iterations.
- ex_id=96 (Deon Gall occupation contamination): NOT in subsample (seed variance). Persistent failure assumed based on prior iterations.
- ex_id=12 (male cousin of great-grandchild of Adelaida Brice): 1.0 — entity Phase 1 working correctly. Stable.
- ex_id=4 (DOB multi-anchor entity, 7+ anchors): 0.545 — Phase 1 still budget-exhausted with many DOB anchors. Not fixed.
- ex_id=93 (DOB father-in-law of friend chain): 0.154 — 1/7 correct. Phase 1 still fails on deep DOB multi-anchor chains. Not fixed.
-
Sequential top-N Phase 2 selection bias — CONFIRMED in iteration 23: For large hobby/occupation populations (N>50), ColBERT retrieval does NOT rank Prolog ground-truth entities highest. The top-50 results are dominated by corpus entities (which may exist in the wiki but were not included in the Prolog reasoning that generated the gold answers). This means cap increases beyond 50 do NOT reliably help — they add more spurious entities that return wrong count values. The correct fix is RANDOM sampling of N entities from Phase 1's full output (not sequential top-N), so that Prolog entities have a proportional chance of being sampled regardless of their ColBERT rank.
-
Phase 2 deduplication is a zero-cost improvement (iteration 23): No regression attributed to deduplication of Phase 1 output. This prevents wasting Phase 2 budget on duplicate entity names. Should be RETAINED in all future iterations regardless of cap setting.
-
Iteration 24 (ACCEPTED on subsample, MAJOR VALSET REGRESSION −11.0%): Two changes from candidate 15: (1) Phase 1 output deduplication (same zero-cost win as iteration 23); (2) Phase 2 random sampling —
random.sample(entities, 20)with deterministic per-question seed. Subsample: 0.6463→0.6994 (+8.2%). Valset: 0.6867→0.6118 (−11.0%). Branch:codeevolver-20260615073543-62729b, candidate 18. The large subsample gain was dominated by stochastic wins on entity/attribute code paths (ex_id=11, 67, 74) that were NOT changed — pure LLM run-to-run variance that doesn't generalize. Structural count_pivot effect from random sampling: 2 wins (ex_id=36, 41) vs 6 losses (ex_id=10, 18, 20, 29, 31, 63). Root cause: for any individual count_pivot question with N Phase 1 entities, random-20 gives P(hitting a specific Prolog entity) ≈ 20/N. For N=59 (ex_id=31, tea bag collecting), P≈34% — meaning 66% chance that entity is excluded AND a spurious corpus entity is included instead. The wins and losses cancel out or net-negative on the full valset distribution. Both Phase 2 entity selection variants (sequential cap increase and random sampling) have now failed — the Phase 2 entity selection mechanism is exhausted as a tuning target. Current live program is candidate 18 (regression). Best program remains candidate 15 (0.6867). All next iterations MUST branch from candidate 15. -
Iteration 24 trace key observations (50 examples, child avg=0.6994 vs parent 0.6463):
- ex_id=36 (grandfather of great-granddaughter of Lee Patino great-grandchildren): 0.0→1.0 — structural count_pivot win from random sampling found the correct pivot that sequential top-20 missed.
- ex_id=41 (mother of parent of brother-in-law of Taneka Seely great-grandchildren): 0.67→1.0 — structural count_pivot win. Random selection found the correct single-count value '6'.
- ex_id=63 (grandchild of child of video editor occupation grandparents): 0.571→0.0 — structural count_pivot loss. Random sampling selected entities that all returned '0', while sequential would have included entities returning '2','4','6','8'. pred=['0','0'], gold=['2','4','6','8']. Confirms variance cuts both ways.
- ex_id=29 (cousins of cousin of great-grandchild of Deon Gall): 0.0 — persistent Phase 1 traversal failure (unrelated to sampling change). pred={0,4,5,7} vs gold={1,3}.
- ex_id=55 (male first cousin once removed of cousin of daughter-in-law of Oleta Miller): 0.0 — pred=['Vicente Cousin','Julio Cousin','Milo Cousin'] — classic "Cousin" surname confusion, Phase 1 returned entities with the surname "Cousin" instead of the kinship relation. Persistent entity Phase 1 failure.
- ex_id=72 (Juan Arevalo hobby contamination): 0.0 — pred=['railway journeys','mineral collecting','trainspotting'], gold=['antiquities']. 20th+ consecutive failure. Unchanged.
- ex_id=90 (Rosina Robey mother of cousin of second uncle): 0.0 — pred=['Mona Bickel'] vs gold=['Latasha Galbreath']. 21st+ consecutive failure. Unchanged.
- ex_id=77 (mother-in-law of DOB 1050-09-16 person): 0.40 — pred=['Jada Paez','Pauletta Green','Crysta Hernandez','Beulah Hong'], gold=['Jada Paez']. Persistent corpus/Prolog mismatch for DOB questions with multiple corpus matches.
- ex_id=91 (axe throwing hobby parents): 1.0 — random sampling helped here by avoiding spurious entities. gold=['0','2'], pred_set={0,2}. Good example where random sampling resolved the spurious-value problem.
- ex_id=88 (company secretary grandfather female first cousins once removed): 0.286 — pred=['0'], gold=['0','1','2','3','4','6']. Only 1 value found despite 20 Phase 2 calls — 19 spurious pivots returning '0'. Phase 2 cap=20 insufficient for this question regardless of selection strategy.
- ex_id=12 (male cousin of great-grandchild of Adelaida Brice): 1.0 — entity Phase 1 stable and correct. Maintained across all iterations since 18.
- ex_id=81 (cousin of grandchild of Eldon Ridenour): 1.0 — RECIPROCAL COUSINHOOD still working. Maintained from iteration 21.
-
Random sampling for Phase 2 — CONFIRMED FAILED (iteration 24, valset −11.0%): The theoretical motivation was correct (ColBERT rank bias confirmed in iteration 23), but the practice shows random sampling introduces high per-question variance that is net-negative on the valset distribution. The confidence threshold approach (only keep count values appearing in ≥2 Phase 2 calls) is the next lowest-risk attempt at reducing corpus/Prolog mismatch noise. It operates AFTER all Phase 2 calls complete (no selection change), filtering the output instead of changing which pivots are called. Worth testing from candidate 15 with Phase 2 cap=20 sequential (candidate 15 baseline).
-
Next structural improvement candidates (all should branch from candidate 15,
codeevolver-20260615073543-c7abb8): (i)Separate— TRIED in iteration 22, FAILED (valset −11.0%). Do NOT retry; (ii)entity_finder_entitymodule with max_iters=50-60Phase 2 cap 20→50— TRIED in iteration 23, valset REGRESSION (−3.5%). Do NOT retry sequential cap increase; (iii)Python-level Phase 2 RANDOM sampling— TRIED in iteration 24, FAILED (valset −11.0%). Random sampling is theoretically sound but empirically introduces too much per-question variance. Do NOT retry; (iv) Confidence threshold post-processing — only include Phase 2 count values appearing in ≥2 distinct Phase 2 calls; collapses spurious one-off corpus/Prolog mismatch values. Python-level, no LM calls, NOT YET TRIED, worth testing from candidate 15; (v) One-line conditional gender rule in EntityFinderSig entity block — MEDIUM RISK (~+1-2% valset if it works); (vi) Sibling cross-reference worked example in single-phase PhantomWikiQA docstring only (NOT Phase 1); (vii) Hybrid Phase 2 sampling: sequential top-10 + random-10 from remainder — captures guaranteed top ColBERT results AND gives Prolog entities some chance. NOT YET TRIED; lower-variance than pure random sampling. Could be tested from candidate 15 if confidence threshold also fails.