Skip to content

SDK session poison-loop: generator emits prose "empty observation" instead of <skip_summary/>, triggering repeated kill/respawn #2955

Description

@budriamanda

Version: 13.6.1 (Windows 11)

Summary

When the observation generator decides there's nothing worth recording, it returns a natural-language string such as (Empty observation - routine search result extraction and JSON parsing with no substantive technical change, decision, or discovery) instead of the <skip_summary reason="..."/> tag the parser expects. The parser classifies this prose as invalid output; after 3 consecutive invalid responses the SDK session is "poisoned" and killed/respawned. In one session this fired 28 times in a few minutes — pure log spam plus wasted SDK round-trips. No data loss (pending messages preserved, valid observations still written).

Root cause (scripts/worker-service.cjs)

  • p9(text) (XML validator) accepts only <skip_summary .../> or <observation>/<summary> with at least 1 parsed entry. Everything else returns {valid:false}.
  • m9(text) (classifier) returns "idle" for empty, "poisoned" for known session-death phrases (rEe), "xml" if a tag is present, else "prose".
  • Poison gate ($9 = 3):
if(!d.valid){
  C = m9(t);
  e.consecutiveInvalidOutputs = (e.consecutiveInvalidOutputs ?? 0) + 1;
  warn("returned non-XML " + C);
  if(C === "poisoned" || e.consecutiveInvalidOutputs >= $9){ /* kill + respawn */ }
}

A "nothing to record" decision expressed as prose therefore counts as a malformed output and accumulates toward the poison threshold, even though it is an intentional, correct skip.

Sample logs

[PARSER] SDK returned non-XML prose response — ignoring queued batch
  {outputClass=prose, preview=(Empty observation - routine search result extraction... no substantive technical change), consecutiveInvalidOutputs=1}
[SESSION] SDK session poisoned — killing and respawning, pending messages preserved
  {outputClass=idle, consecutiveInvalidOutputs=3, threshold=3}

Proposed fixes (either or both)

  1. Generator prompt — instruct the model to emit <skip_summary reason="..."/> (never free prose) when there is nothing to record. Eliminates the invalid-output path entirely.
  2. Parser tolerance — in m9/p9, treat an empty ("idle") or clear skip-intent prose response (e.g. matches /empty observation|no substantive|nothing to record|routine/i) as a valid skip: do not increment consecutiveInvalidOutputs, do not count toward poison. Reserve poison for genuine rEe session-death phrases.

Impact

Cosmetic — log noise and wasted SDK calls, no data loss. Low severity but easy to remove a repeated false poison.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions