Skip to content

Commit 52b36e2

Browse files
JihaoXinclaude
andcommitted
Page enforcement: loop until success, relax tolerance every 4 attempts
- No max attempt limit — loops until page count is in range - Every 4 failed attempts, relax tolerance by ±0.1 pages (e.g., attempt 1-4: 5.95-6.1, attempt 5-8: 5.85-6.2, etc.) - Quota exhaustion: accepts if within hard ceiling (≤ N+0.5 pages) - No human intervention needed — always converges Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent df7f8fe commit 52b36e2

File tree

1 file changed

+41
-30
lines changed

1 file changed

+41
-30
lines changed

ark/execution.py

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -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
666691
Reduce 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}.
674699
Ensure `\\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
685709
Expand 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}.
693717
Ensure `\\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

Comments
 (0)