@@ -81,6 +81,9 @@ class Ceiling:
8181 unit : str
8282 #: The short tag reported as `RunResult.halted`.
8383 halted : str
84+ #: Nobody wrote this figure: it is PACT's own (`ir.DEFAULT_STEPS`, law 2), so
85+ #: the sentence must not tell a person it is "the limit you set".
86+ default : bool = False
8487
8588
8689@dataclass (frozen = True )
@@ -114,6 +117,20 @@ def sentence(self) -> str:
114117 happened — a message saying only "limit exceeded" leaves the reader with
115118 nowhere to go, which is the failure D13 rules out."""
116119 what = self .what
120+ if self .ceiling .default :
121+ whose = (
122+ f"PACT's default limit, { what } , which applies when no "
123+ f"`{ self .ceiling .field } :` is written (write one under `limits:` to set "
124+ f"your own)"
125+ )
126+ if self .action is Action .ASK :
127+ return f"Waiting for a person: this run reached { whose } ."
128+ if self .action is Action .ANSWER :
129+ return (
130+ f"This run reached { whose } , so it answered with what it had rather "
131+ f"than finishing the work."
132+ )
133+ return f"Stopped before finishing: this run reached { whose } ."
117134 if self .action is Action .ASK :
118135 return f"Waiting for a person: this run reached the limit you set with { what } ."
119136 if self .action is Action .ANSWER :
@@ -582,7 +599,9 @@ def across_runs(self) -> tuple[str, ...]:
582599 meter. Reported, never dropped (T7)."""
583600 return ("counted-per" ,) if self .counted_per not in ("" , "run" ) else ()
584601
585- def ceilings (self , steps_at_most : int | None = None ) -> tuple [Ceiling , ...]:
602+ def ceilings (
603+ self , steps_at_most : int | None = None , steps_default : bool = False
604+ ) -> tuple [Ceiling , ...]:
586605 """Every ceiling in force, in a FIXED order.
587606
588607 The order is the report's tie-break: when a step and a cost ceiling are
@@ -592,7 +611,7 @@ def ceilings(self, steps_at_most: int | None = None) -> tuple[Ceiling, ...]:
592611 """
593612 rows : list [Ceiling ] = []
594613 if steps_at_most is not None :
595- rows .append (step_ceiling (steps_at_most ))
614+ rows .append (step_ceiling (steps_at_most , default = steps_default ))
596615 if self .tool_calls_at_most is not None :
597616 rows .append (
598617 Ceiling (
@@ -619,10 +638,15 @@ def ceilings(self, steps_at_most: int | None = None) -> tuple[Ceiling, ...]:
619638 return tuple (rows )
620639
621640 def reached (
622- self , meter : Meter , now : float , steps_at_most : int | None = None
641+ self ,
642+ meter : Meter ,
643+ now : float ,
644+ steps_at_most : int | None = None ,
645+ steps_default : bool = False ,
623646 ) -> Reached | None :
624- """The first ceiling this run has reached, or `None`."""
625- for c in self .ceilings (steps_at_most ):
647+ """The first ceiling this run has reached, or `None`. `steps_default` says
648+ the step ceiling is PACT's default rather than the author's."""
649+ for c in self .ceilings (steps_at_most , steps_default ):
626650 at = meter .reading (c .reads , now )
627651 if at >= c .limit :
628652 return Reached (c , at , self .when_it_runs_out )
@@ -772,15 +796,15 @@ def _nothing_can_reach(cap: float) -> bool:
772796 return math .isnan (cap ) or cap == math .inf
773797
774798
775- def step_ceiling (limit : int ) -> Ceiling :
799+ def step_ceiling (limit : int , default : bool = False ) -> Ceiling :
776800 """The step ceiling as a row of the algebra.
777801
778802 It is enforced by the loop's own bound rather than by `reached`, but it ends
779803 a run through the same door as every other ceiling — otherwise `steps-at-most`
780804 and `cost-per-request-under` drift into behaving differently, which is what
781805 happens whenever each limit is given its own ending.
782806 """
783- return Ceiling ("steps-at-most" , "steps" , float (limit ), "steps" , "step-limit" )
807+ return Ceiling ("steps-at-most" , "steps" , float (limit ), "steps" , "step-limit" , default )
784808
785809
786810#: Every way `RunResult.halted` can say "a ceiling ended this". A caller that
0 commit comments