An assistant can always suggest another search. That is not a useful stopping rule. A bounded loop must distinguish gathering new evidence, repeating a request, requesting handover, failing a boundary check, and exhausting a resource. For this course, one step means one chooser invocation. A stop request consumes a step because producing it still required a decision. The default eight-step budget therefore permits at most eight proposals, not eight tools followed by an unlimited conversation.
At each turn the controller constructs a view of recorded evidence and unknowns, asks the chooser for exactly one action, validates that action, and either stops or dispatches one allowed tool. It then checks the deadline and result size before appending evidence. A tool result becomes available only on a later choice. This creates a clear boundary for replay: a reviewer can point to the precise observation that was available when each proposal was made.
The baseline chooser does not adapt to observations. It uses the evidence count to select three fixed requests and then stop. This demonstrates the controller interface but is a deterministic workflow, NOT a true LLM agent. A real agent would use a model's interpretation of returned evidence to choose among permitted actions. Whether that freedom is beneficial must be measured; the baseline remains a useful comparator because it has predictable coverage and no inference cost.
Choice | Proposal | Controller outcome |
|---|---|---|
1 | Search R42 for reset_smoke | Record E1 with both matching log lines |
2 | Read reset_release from spec revision 3 | Record E2 with the requirement excerpt |
3 | Read three reset_smoke history records | Record E3 with R40, R41, R42 |
4 | Stop | Return handoff_requested, preserving unknowns |
This trace is a specified example, not output captured from an execution. The terminal status is handoff_requested, not root_cause_found or design_verified. The controller can verify that a valid stop request arrived. It cannot infer that the evidence is sufficient for engineering closure. An evaluator separately checks whether the packet contains the required observations. If a chooser stops immediately, the program still returns a handover status, but that run should fail the evidence-completeness rubric.
Repeated actions are detected by serializing the complete action with sorted keys. Different dictionary insertion order cannot disguise the same request. Changing a query can produce a distinct request, so repeat detection alone does not bound all loops. The step budget still caps the run. Because the lab data is immutable, immediately repeating an identical read cannot produce fresh evidence. A future live data source would need explicit snapshot and freshness semantics before deciding which repeated reads are meaningful.
Manually trace the baseline with max_steps=2. Record the status, evidence references, and missing source. Then trace a chooser that always requests the same first search. Do not assume an error is a successful search with zero results: an invalid request should create an error event and stop. Finally explain what a model should do if the available evidence does not resolve whether the failing cycle matches the specification's first rising edge.
The two-step baseline returns step_budget with E1 and E2 but no history. An always-repeat chooser records E1, then stops with repeated_action on its second proposal. Unresolved timing alignment remains an unknown for handover.
A loop boundary is only as strong as its operations. A chooser that never returns prevents a synchronous loop from reaching its next check. The lab's clock checks therefore implement a cooperative deadline, not forced cancellation. Python 3.12 time.monotonic provides elapsed-time measurement unaffected by wall-clock adjustments; external I/O still needs independent timeout enforcement.