fix: audit improvements — grace window, DRY errors, broader injection escape, new options
- noProgressTurnsBeforePause (default 2): no-progress counter now accumulates
across consecutive low-output idle cycles before stopping; counter resets when
a high-output turn is seen; managed entirely in the idle handler rather than
split across message.updated
- maxRecentMessages (default 12): messages query limit promoted from hardcoded
literal to a configurable normalizeOptions option
- applyPromptFailure: extracted shared helper used by both the response.error
branch and the catch block, eliminating duplicated failure-tracking logic
- escapeGoalText: broadened from escaping only </goal_objective> to escaping
all XML closing tags (replaceAll("</" → "<\/")) so user goal text cannot
break any structural tag in buildContinueMessage or the system transform
- testInternals: added applyPromptFailure and logPluginError exports
- tests: 14 new cases covering buildLimitWarning, outputTokensForMessage,
budgetWrapupNeeded, getSessionID, escapeGoalText (all structural tags),
stopReason, logPluginError console fallback, applyPromptFailure,
extractBlockedReason first-line edge case, normalizeOptions boundary inputs
(0/negative/NaN/null/undefined, budgetWrapupRatio at 0 and 1), grace window
integration (N-1 stalls allowed, counter reset on high-output turn)
- three existing no-progress tests updated with noProgressTurnsBeforePause: 1
to preserve their one-strike semantics under the new default
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> W
Willy committed
fdfcb2135f1cec518ffe6b716502fd2e75df0e0b
Parent: 6401483