fix: treat daily-memory no-op as success instead of hard failure#2784
Open
chubes4 wants to merge 1 commit into
Open
fix: treat daily-memory no-op as success instead of hard failure#2784chubes4 wants to merge 1 commit into
chubes4 wants to merge 1 commit into
Conversation
DailyMemoryTask logged a legitimate 'MEMORY.md unchanged' outcome as an ERROR-level job failure, flooding error-rate metrics and the wake briefing. The conversation loop sets completed=false both for genuine faults (provider error, runtime exception, malformed result, interruption) and for the common case where a small, already-healthy MEMORY.md produced no acceptable PERSISTENT/ARCHIVED split because there was nothing memory-worthy to fold in. The file is untouched at this point, so the latter is a successful no-op, not a failure. Distinguish the two by explicit error signal (non-empty error string, error_code, or error/failed/interrupted status). Genuine faults still failJob and log at error; a no-op completes the job and logs at info. Closes #2783
Contributor
Homeboy Results —
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2783
Problem
DailyMemoryTasklogged a legitimate "MEMORY.md unchanged" outcome as an ERROR-level hard job failure, generating recurring false-positive noise that polluted error-rate metrics and the wake briefing.Real log evidence from
extrachill.com(andwire.extrachill.com), repeating ~3×/day across multiple agents and every day:{"job_id":5151,"task_type":"daily_memory_generation","error":"Daily memory completion policy was not satisfied. MEMORY.md unchanged."}Root cause (investigated, not assumed)
Inspecting live failing jobs confirmed the mechanism:
token_usageand the error is the exact fallback string — meaning$response['error']was empty.completed=falsewith no genuine error — i.e. the completion policy never returnedcomplete()within the turn budget.MEMORY.mdis 144 bytes (MAX is 8192), so the file is small and already healthy. The task didn't skip at the size-threshold guard only because there was some activity context that day. The model reviewed the day, found nothing memory-worthy, and never emitted an acceptable===PERSISTENT===/===ARCHIVED===partition. Nothing is written to disk on this path, soMEMORY.mdis genuinely unchanged — a successful no-op, not a fault.The conversation loop (
datamachine_run_conversation) setscompleted=falsefor both genuine faults (provider error, runtime exception, malformed result,budget_exceeded/interrupted/failedstatus) and this benign "ran out of turns without an acceptable changed split" case. The old code blindlyfailJob'd both.Fix
At the
completed=falsebranch inDailyMemoryTask::executeTask(), distinguish the two by explicit error signal:errorandfailJob.completeJobwithskipped/no_changemarkers and log atinfo. Safe becausereplace_all()happens later in the method, soMEMORY.mdis untouched at this point.How legitimate no-op is distinguished from genuine failure
error/error_codefailJob(error)status∈ {error, failed, interrupted}failJob(error)empty($ai_output)guardfailJob(error) — unchangedplanMemoryCompactionconservation checksfailJob(error) — unchangedcompleteJobno-op (info) ✅All genuine-failure paths downstream (empty response, parse failure, conservation/expansion failures in
planMemoryCompaction) are reached only whencompleted=trueand remain loud — they represent a model that produced bad output, which the issue explicitly says must still fail.Fork decisions / out of scope
complete()/incomplete()); the no-op semantics are a Data-Machine-task concern (the file being untouched at this call site), so the distinction belongs in the task, not the generic loop. This keeps layer purity intact.Verification
php -lclean.phpcs --standard=WordPressclean (exit 0, no warnings — covers the array-arrow/assignment-alignment gate).phpcbfmade no changes.