@@ -647,21 +647,46 @@ def _enforce_page_count(self, context: str = "post-writing") -> bool:
647647 self .log (f"[{ context } ] Page check: { page_count :.1f} body pages "
648648 f"(target: { min_pages :.2f} –{ max_pages :.1f} , { columns } -col)" , "INFO" )
649649
650- # Loop until page count is in range (safety limit to avoid infinite loop)
651- MAX_ATTEMPTS = 5
652- for attempt in range (MAX_ATTEMPTS ):
653- in_range = min_pages <= page_count <= max_pages
650+ # Loop until page count is in range.
651+ # Every 4 failed attempts, relax tolerance by 0.1 pages (both sides).
652+ attempt = 0
653+ tolerance_relaxations = 0
654+ cur_min = min_pages
655+ cur_max = max_pages
656+
657+ while True :
658+ in_range = cur_min <= page_count <= cur_max
654659 if in_range :
655- self .log (f"[{ context } ] Page count OK: { page_count :.1f} /{ venue_pages } (attempt { attempt + 1 } )" , "INFO" )
660+ if tolerance_relaxations > 0 :
661+ self .log (f"[{ context } ] Page count OK: { page_count :.1f} /{ venue_pages } "
662+ f"(accepted with relaxed tolerance after { attempt } attempts)" , "INFO" )
663+ else :
664+ self .log (f"[{ context } ] Page count OK: { page_count :.1f} /{ venue_pages } " , "INFO" )
656665 return True
657666
658- if page_count > max_pages :
667+ attempt += 1
668+
669+ # Every 4 attempts, relax tolerance
670+ if attempt > 0 and attempt % 4 == 0 :
671+ tolerance_relaxations += 1
672+ cur_min = min_pages - tolerance_relaxations * 0.1
673+ cur_max = max_pages + tolerance_relaxations * 0.1
674+ self .log (f"[{ context } ] Relaxing tolerance (round { tolerance_relaxations } ): "
675+ f"new range { cur_min :.2f} –{ cur_max :.1f} " , "WARN" )
676+ # Re-check with relaxed tolerance before another agent call
677+ continue
678+
679+ if self ._quota_exhausted :
680+ self .log (f"[{ context } ] Quota exhausted, accepting { page_count :.1f} pages" , "WARN" )
681+ return page_count <= venue_pages + 0.5 # Hard ceiling: never more than half page over
682+
683+ if page_count > cur_max :
659684 action = "compress"
660- self .log (f"[{ context } ] Over limit ({ page_count :.1f} > { max_pages :.1f} ), compressing (attempt { attempt + 1 } / { MAX_ATTEMPTS } )..." , "WARN" )
661- self .run_agent ("writer" , f"""## PAGE COMPRESSION — venue limit is { venue_pages } body pages (attempt { attempt + 1 } )
685+ self .log (f"[{ context } ] Over limit ({ page_count :.1f} > { cur_max :.1f} ), compressing (attempt { attempt } )..." , "WARN" )
686+ self .run_agent ("writer" , f"""## PAGE COMPRESSION (attempt { attempt } )
662687
663- The paper body is currently { page_count :.1f} pages, exceeding the { venue_pages } -page limit.
664- Target: between { min_pages :.2f} and { venue_pages :.0f} body pages. Do NOT over-compress.
688+ The paper body is currently { page_count :.1f} pages, exceeding the limit.
689+ Target: between { cur_min :.2f} and { venue_pages :.0f} body pages. Do NOT over-compress.
665690
666691Reduce carefully — aim for exactly { venue_pages } pages, NOT much less. Strategies:
667692- Condense verbose paragraphs by ~10-15% (not more)
@@ -670,17 +695,16 @@ def _enforce_page_count(self, context: str = "post-writing") -> bool:
670695- Reduce whitespace around figures/tables (use \\ vspace{{-4pt}})
671696- Do NOT remove key technical content, results, or entire sections
672697
673- After changes, compile and verify body pages are between { min_pages :.2f} and { venue_pages :.0f} .
698+ After changes, compile and verify body pages are between { cur_min :.2f} and { venue_pages :.0f} .
674699Ensure `\\ clearpage` before `\\ bibliography`.
675700""" , timeout = 1800 )
676701
677- elif page_count < min_pages :
702+ elif page_count < cur_min :
678703 action = "expand"
679- self .log (f"[{ context } ] Under target ({ page_count :.1f} < { min_pages :.2f} ), expanding (attempt { attempt + 1 } / { MAX_ATTEMPTS } )..." , "WARN" )
680- self .run_agent ("writer" , f"""## PAGE EXPANSION — paper is too short (attempt { attempt + 1 } )
704+ self .log (f"[{ context } ] Under target ({ page_count :.1f} < { cur_min :.2f} ), expanding (attempt { attempt } )..." , "WARN" )
705+ self .run_agent ("writer" , f"""## PAGE EXPANSION (attempt { attempt } )
681706
682- The paper body is currently { page_count :.1f} pages. Target: { min_pages :.2f} –{ venue_pages :.0f} body pages.
683- The last page must be at least 90% filled.
707+ The paper body is currently { page_count :.1f} pages. Target: { cur_min :.2f} –{ venue_pages :.0f} body pages.
684708
685709Expand by adding substantive content (NOT filler):
686710- Deepen the analysis/discussion section with more insights
@@ -689,7 +713,7 @@ def _enforce_page_count(self, context: str = "post-writing") -> bool:
689713- Add a limitations paragraph or future work discussion
690714- Do NOT add padding text or redundant restatements
691715
692- After changes, compile and verify body pages are between { min_pages :.2f} and { venue_pages :.0f} .
716+ After changes, compile and verify body pages are between { cur_min :.2f} and { venue_pages :.0f} .
693717Ensure `\\ clearpage` before `\\ bibliography`.
694718""" , timeout = 1800 )
695719
@@ -700,19 +724,6 @@ def _enforce_page_count(self, context: str = "post-writing") -> bool:
700724 self .log (f"[{ context } ] Could not determine page count after { action } " , "WARN" )
701725 return True
702726
703- # After all attempts — notify user if still out of range
704- in_range = page_count and min_pages <= page_count <= max_pages
705- if not in_range :
706- msg = (f"⚠️ Page count still out of range after { MAX_ATTEMPTS } attempts: "
707- f"{ page_count :.1f} pages (target: { min_pages :.2f} –{ max_pages :.1f} ). "
708- f"Manual adjustment may be needed." )
709- self .log (f"[{ context } ] { msg } " , "ERROR" )
710- if self .telegram .is_configured :
711- self .telegram .send (msg )
712- else :
713- self .log (f"[{ context } ] Final page count: { page_count :.1f} /{ venue_pages } body pages OK" , "INFO" )
714- return in_range
715-
716727 def _ensure_clearpage_before_bibliography (self ):
717728 """Programmatically ensure \\ clearpage appears before \\ bibliography in main.tex."""
718729 main_tex = self .latex_dir / "main.tex"
0 commit comments