* fix: canonicalize topic session transcript fallback
When initSessionState has a topic-scoped SessionKey but no MessageThreadId, fallback transcript selection should still land on the topic-qualified JSONL path instead of the bare session file. Match the existing transcript resolver by parsing the thread id from the session key, and cover the regression with a session init test that loads the Telegram session-conversation grammar.
Regeneration-Prompt: |
Investigate why a Telegram topic session could alternate between <session-id>.jsonl and <session-id>-topic-<n>.jsonl for the same logical session. The fix should be in OpenClaw's session initialization path, not in lossless-claw. Keep behavior unchanged when MessageThreadId is present, but when the inbound turn only carries a topic-scoped SessionKey, derive the same topic-specific transcript path that the canonical transcript resolver would use. Add a regression test that proves initSessionState chooses the topic-qualified file even without MessageThreadId, and make the test load the session-conversation registry needed to parse Telegram :topic: grammar.
* fix: preserve topic session transcript history
- scope computeQaAgenticParityMetrics to QA_AGENTIC_PARITY_SCENARIO_TITLES
in buildQaAgenticParityComparison so extra non-parity lanes in a full
qa-suite-summary.json cannot influence completion / unintended-stop /
valid-tool / fake-success rates
- filter coverageMismatch by !parityTitleSet.has(name) so each required
parity scenario fails the gate exactly once (from requiredScenarioCoverage)
instead of being double-reported as a coverage mismatch too
- drop the bare /\\berror\\b/i rule from SUSPICIOUS_PASS_PATTERNS — it was
false-flagging legitimate passes that narrate "Error budget: 0" or
"no errors found" — and replace it with targeted /error occurred/i and
/an error was/i phrases that indicate a real mid-turn error
- add regressions: error-budget/no-errors-observed passes yield
fakeSuccessCount === 0, genuine error-occurred narration still flags,
each missing required scenario fires exactly one failure line, and
non-parity lanes do not perturb scoped metrics
- isolate the baseline suspicious-pass test by padding it to the full
first-wave scenario set so it asserts the isolated fake-success path
via toEqual([...]) rather than toContain