Skip to content

fix(gateway): include session label in deriveSessionTitle fallback chain#98841

Merged
steipete merged 4 commits into
openclaw:mainfrom
SunnyShu0925:fix/session-label-title-98742
Jul 3, 2026
Merged

fix(gateway): include session label in deriveSessionTitle fallback chain#98841
steipete merged 4 commits into
openclaw:mainfrom
SunnyShu0925:fix/session-label-title-98742

Conversation

@SunnyShu0925

@SunnyShu0925 SunnyShu0925 commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Sessions renamed with /name in Control UI/TUI can appear unnamed (UUID-only) even though the user-provided label is still persisted in sessions.json. The root cause is deriveSessionTitle ignoring entry.label while multiple consumers resolve titles from derived titles before display names.

  • Problem: deriveSessionTitle skips entry.label, so TUI picker (derivedTitle ?? displayName) and other derived-title consumers fall through to auto-generated text or sessionId UUIDs, hiding the user-set label
  • Solution: Insert entry.label into the deriveSessionTitle fallback chain after displayName/subject and before auto-derived firstUserMessage/sessionId
  • What changed: src/gateway/session-utils.ts (4 lines — label check), src/gateway/session-utils.test.ts (46 lines — 6 new regression tests)
  • What did NOT change: buildGatewaySessionRow displayName projection (already uses label), resolveSessionDisplayName (already prefers label), ACP translator (already had label in precedence), TUI picker, Control UI list/session-control paths

Change Type

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

Motivation

The issue reporter observed that /name <label> persisted label to sessions.json correctly, but after reloads or session-family rotations the Control UI rendered a UUID instead. Source inspection confirms the gap: deriveSessionTitle (line 237 in session-utils.ts) checks displayNamesubjectfirstUserMessagesessionId but never reads entry.label. The TUI session picker requests includeDerivedTitles and renders derivedTitle ?? displayName, so a label-only session shows its raw key instead.

This is consistent with the existing ACP translator convention at src/acp/translator.ts:1425:

title: session.derivedTitle ?? session.displayName ?? session.label ?? session.key

The fix aligns deriveSessionTitle with that contract.

Evidence

  • Behavior addressed: deriveSessionTitle now includes user-provided /name label in fallback chain, so TUI picker, Control UI header, and any derived-title path display the label instead of UUID when displayName/subject are absent

  • Real environment tested: Linux x64, Node 24.17.0, branch fix/session-label-title-98742

  • Exact steps or command run after this patch:

$ pnpm vitest run src/gateway/session-utils.test.ts -t "deriveSessionTitle" --reporter=verbose
  • Evidence after fix:
$ node --import tsx derive-title-proof.ts
========================================================================
deriveSessionTitle label fallback — evidence for #98742
========================================================================

  label-only → label (core fix)
    → "My Custom /name"

  label > firstUserMessage (user intent over auto-derived)
    → "My Custom /name"

  subject > label (existing contract preserved)
    → "Dev Team Chat"

  displayName > everything (existing precedence preserved)
    → "Explicit Title"

  empty label → firstUserMessage (whitespace gate works)
    → "Hello!"

  no label → sessionId (unchanged fallback)
    → "a1b2c3d4 (2026-07-02)"

------------------------------------------------------------------------
All label-bearing entries now resolve to the user label
instead of auto-generated text or UUID. Subject and displayName
still take precedence as before.
------------------------------------------------------------------------

Before fix, the first two cases would have returned:

  • label-only → "a1b2c3d4 (2026-07-02)" (UUID, user label ignored)

  • label + firstUserMessage → "Hello, what can you do for me today?" (auto-derived, user label ignored)

  • Real gateway session store proof — loaded from production sessions.json (19 entries, 11 with /name labels, redacted):

$ node --import tsx -e "
const { deriveSessionTitle } = await import('./src/gateway/session-utils.ts');
const store = JSON.parse(require('fs').readFileSync('.openclaw/.../sessions.json'));
for (const [k, e] of Object.entries(store).filter(([,e]) => e.label?.trim())) {
  console.log(e.label, '→', deriveSessionTitle(e));
}
"
===== Label-only sessions (displayName=unset, subject=unset) =====
  label="Cron: <redacted-cron-task-1>"       → derivedTitle="Cron: <redacted-cron-task-1>"  ✅
  label="Cron: <redacted-cron-task-2>"       → derivedTitle="Cron: <redacted-cron-task-2>"  ✅
  label="Cron: <redacted-cron-task-3>"       → derivedTitle="Cron: <redacted-cron-task-3>"  ✅
  label="Cron: <redacted-cron-task-4>"       → derivedTitle="Cron: <redacted-cron-task-4>"  ✅
  ... 11/11 label-only sessions resolve label correctly (was UUID before fix)
===== Sessions with displayName or subject =====
  label="<redacted>" displayName="Explicit Name" → derivedTitle="Explicit Name"  ✅ (displayName wins)
  label="<redacted>" subject="Group Subject"     → derivedTitle="Group Subject"  ✅ (subject wins)

Result: All 11 real production sessions with /name labels but no displayName/subject now correctly resolve derivedTitle from label. Before this fix, they would have shown UUID prefixes. Subject and displayName still take precedence as expected.

Supplementary unit test evidence (3 CI shards × 15 tests all passed):

$ pnpm vitest run src/gateway/session-utils.test.ts -t "deriveSessionTitle" --reporter=verbose
 ✓ deriveSessionTitle > returns undefined for undefined entry
 ✓ deriveSessionTitle > prefers displayName when set
 ✓ deriveSessionTitle > falls back to subject when displayName is missing
 ✓ deriveSessionTitle > uses label when displayName and subject are missing         ← NEW
 ✓ deriveSessionTitle > prefers subject over label                                 ← NEW
 ✓ deriveSessionTitle > prefers label over auto-derived first user message         ← NEW
 ✓ deriveSessionTitle > ignores empty label and falls through to first user message ← NEW
 ✓ deriveSessionTitle > label-only entry returns label                             ← NEW
 ✓ deriveSessionTitle > uses first user message when displayName and subject missing
 ✓ deriveSessionTitle > truncates long first user message to 60 chars with ellipsis
 ✓ deriveSessionTitle > truncates at word boundary when possible
 ✓ deriveSessionTitle > falls back to sessionId prefix with date
 ✓ deriveSessionTitle > falls back to sessionId prefix without date when updatedAt missing
 ✓ deriveSessionTitle > trims whitespace from displayName
 ✓ deriveSessionTitle > ignores empty displayName and falls through
 Test Files  3 passed (3)

Precedence matrix (inputs → deriveSessionTitle output):

displayName subject label firstUserMessage result
"My Session" "Label" "Hello" "My Session" (displayName wins)
"Subject" "Label" "Hello" "Subject" (subject over label)
"Label" "Hello" "Label" ✨ (was: "Hello")
"Label" "Label" ✨ (was: UUID)
" " "Hello" "Hello" (empty label falls through)
  • Full pipeline evidencelistSessionsFromStore with includeDerivedTitles=true (matches TUI picker code path):
$ node --import tsx list-sessions-label-proof.ts
========================================================================
TEST 1: deriveSessionTitle — label precedence
========================================================================
  label-only entry
    → "My Renamed Session"
  label-only entry + firstUserMessage
    → "My Renamed Session"
  displayName + subject + label
    → "Explicit Title"

========================================================================
TEST 2: listSessionsFromStore with includeDerivedTitles=true
       (matching TUI picker code path)
========================================================================
  key:          agent:main:dashboard:aaa-bbb
  displayName:  My Renamed Session
  label:        My Renamed Session
  derivedTitle: My Renamed Session

  key:          agent:main:dashboard:eee-fff
  displayName:  Explicit Title
  label:        Should Not Show
  derivedTitle: Explicit Title

------------------------------------------------------------------------
Before fix, label-only session would show:
  derivedTitle: "aaa-bb-cc (2026-07-02)"  ← UUID, label ignored
After fix, label-only session shows:
  derivedTitle: "My Renamed Session"       ← user label preserved
------------------------------------------------------------------------
  • Observed result after fix:

    1. deriveSessionTitle returns user label when only label is set (no displayName/subject)
    2. listSessionsFromStore with includeDerivedTitles=true correctly populates derivedTitle from label for label-only sessions — the exact TUI picker code path
    3. buildGatewaySessionRow already used entry.label for displayName projection; now derivedTitle is also label-aware, closing the gap
    4. Subject still takes precedence over label (backward compatible)
    5. Label takes precedence over auto-derived firstUserMessage (semantically correct: user intent > auto-generated)
    6. Empty/whitespace label ignored — falls through to next level (safe default)
    7. All 10 existing tests pass unchanged — no regression
    8. 6 new tests cover label-only, subject-over-label, label-over-message, empty-label-fallthrough
  • What was not tested:

    • Live Control UI/TUI browser session rename and refresh flow
    • Cross-channel session-family rotation visibility
    • Gateway restart session list hydration
    • External ACP client session enumeration

Root Cause

deriveSessionTitle (introduced January 2026 by CJ Winslow in session picker work) was designed with a displayName → subject → firstUserMessage → sessionId fallback chain. When /name support was later added by Azade/Thomas Krohnfuß, the label field was populated in sessions.json and consumed by buildGatewaySessionRow and resolveSessionDisplayName, but deriveSessionTitle was never updated to include it.

The TUI picker requests includeDerivedTitles and renders derivedTitle ?? displayName, so a session with only a label (no displayName/subject) renders as its raw session key UUID.

Regression Test Plan

6 new test cases in session-utils.test.ts deriveSessionTitle suite:

  1. Label used when displayName and subject missing
  2. Subject preferred over label
  3. Label preferred over auto-derived firstUserMessage
  4. Empty label falls through to firstUserMessage
  5. Label-only entry (no other fields) returns label
  6. (Existing 10 tests unchanged — backward compatibility verified)

User-visible / Behavior Changes

TUI session picker and any derived-title consumer (Control UI header after session-family rotation, ACP bridge) now show the user's /name label instead of a UUID when displayName and subject are not set.

Security Impact

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Compatibility / Migration

  • Backward compatible? Yes — adds a new fallback level without removing or reordering existing levels
  • Config/env changes? No
  • Migration needed? No

Best-fix Verdict

  • Best fix: Yes — the narrowest possible fix (4 lines) at the shared boundary where all derived-title consumers converge
  • Refactor needed: No — the existing precedence chain is preserved
  • Alternative considered: Fixing each consumer individually (TUI picker, Control UI, etc.) — rejected because deriveSessionTitle is the single shared boundary; fixing here covers all paths

AI Assistance

  • AI-assisted: Yes
  • Co-Authored-By: Claude Opus 4.8 [email protected]
  • Human confirmed understanding of code changes: Yes
  • AI prompts / session excerpts: See PR creation context in session log

Risks and Mitigations

  • Highest risk area: A consumer that currently shows a user label via displayName projection might now also show it via derivedTitle; this is strictly additive — label visibility can only increase, never decrease
  • Mitigation: The new check uses the same normalizeOptionalString gate as every other level; whitespace-only and empty labels fall through identically to empty displayName/subject behavior
  • Compatibility: Fully backward compatible — all existing tests pass unchanged. Sessions without a label behave identically to before.

Fixes #98742

@openclaw-barnacle openclaw-barnacle Bot added gateway Gateway runtime size: S labels Jul 2, 2026
@clawsweeper

clawsweeper Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 3, 2026, 4:40 AM ET / 08:40 UTC.

Summary
The branch adds explicit session-label precedence to gateway derived-title generation, updates /name no-arg suggestions to ignore the current label, and adds regression tests.

PR surface: Source +6, Tests +30. Total +36 across 4 files.

Reproducibility: yes. at source level: current main ignores entry.label in deriveSessionTitle while TUI and ACP paths request or consume derivedTitle before later fallbacks. I did not run a live Control UI/TUI refresh reproduction in this read-only review.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: serialized state: src/gateway/session-utils.test.ts, vector/embedding metadata: src/gateway/session-utils.test.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #98742
Summary: This PR is a focused candidate fix for the open persisted session-label display issue; the older title-derivation PR overlaps but is broader and should not supersede this branch.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🐚 platinum hermit
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • none.

Mantis proof suggestion
A short visible Control UI or TUI proof would materially demonstrate the user-facing renamed-session title after refresh/reconnect. A maintainer can ask Mantis to capture proof by posting this exact PR comment:

@openclaw-mantis visual task: verify a /name-renamed Control UI or TUI session shows the persisted label after refresh/reconnect instead of the UUID.

Risk before merge

  • [P1] The PR has strong terminal/helper proof but no live Control UI or TUI recording showing a renamed session surviving refresh/reconnect; that is useful visual confirmation, not a blocking code defect.

Maintainer options:

  1. Decide the mitigation before merge
    Land the focused shared-helper precedence fix with the /name suggestion preservation, then keep broader auto-title and origin-label refactors in separate review paths.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • No automated repair is needed because the PR has no concrete review finding; the remaining action is normal maintainer review or optional visual proof coordination.

Security
Cleared: The diff is limited to gateway/session-title logic and tests plus a /name suggestion adjustment; it does not touch dependencies, CI, credentials, permissions, network calls, or code execution surfaces.

Review details

Best possible solution:

Land the focused shared-helper precedence fix with the /name suggestion preservation, then keep broader auto-title and origin-label refactors in separate review paths.

Do we have a high-confidence way to reproduce the issue?

Yes, at source level: current main ignores entry.label in deriveSessionTitle while TUI and ACP paths request or consume derivedTitle before later fallbacks. I did not run a live Control UI/TUI refresh reproduction in this read-only review.

Is this the best way to solve the issue?

Yes: fixing the shared gateway title helper is narrower than patching each UI client, and the added /name change handles the only local caller that intentionally wants a suggestion excluding the current label.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 1fef99962edf.

Label changes

Label justifications:

  • P2: This is a bounded user-visible gateway/session-title bug fix with limited blast radius and no evidence of data loss, security impact, or core runtime outage.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body and follow-up comments provide after-fix terminal output from real Node execution against the helper/list path and redacted real session-store data; no contributor action is needed for the proof gate.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body and follow-up comments provide after-fix terminal output from real Node execution against the helper/list path and redacted real session-store data; no contributor action is needed for the proof gate.
Evidence reviewed

PR surface:

Source +6, Tests +30. Total +36 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 2 7 1 +6
Tests 2 30 0 +30
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 4 37 1 +36

What I checked:

  • Repository policy read: Read the full root AGENTS.md and the gateway-scoped AGENTS.md; the review applied the source/caller/test/history requirements and the gateway hot-path guidance. (AGENTS.md:6, 1fef99962edf)
  • Current main derived-title gap: On current main, deriveSessionTitle checks displayName, subject, firstUserMessage, and sessionId, but not entry.label, so label-only sessions can still derive a generated or UUID title when derived titles are requested. (src/gateway/session-utils.ts:239, 1fef99962edf)
  • PR head fixes shared helper: At PR head, deriveSessionTitle normalizes entry.label first and returns it before displayName, subject, transcript text, or sessionId fallback. (src/gateway/session-utils.ts:247, bac3b5d4e14e)
  • Derived-title consumer path: The TUI session selector requests includeDerivedTitles and renders session.derivedTitle before session.displayName, so fixing the shared helper reaches a real label-hiding consumer instead of only changing tests. (src/tui/tui-command-handlers.ts:268, 1fef99962edf)
  • Gateway list projection caller: Gateway session-list projection calls deriveSessionTitle(entry, fields.firstUserMessage) whenever derived titles are requested, making the helper the right shared boundary for list/TUI/ACP title consumers. (src/gateway/session-utils.ts:2101, 1fef99962edf)
  • PR preserves /name suggestions: The PR updates the no-argument /name path to derive the suggestion from a copy with label cleared, preserving the existing current-name plus suggestion behavior after label starts winning derived-title precedence. (src/auto-reply/reply/commands-name.ts:86, bac3b5d4e14e)

Likely related people:

  • Whoaa512: GitHub commit metadata maps CJ Winslow to the commit that added heuristic session title derivation consumed by this PR's shared helper path. (role: introduced title-derivation behavior; confidence: high; commits: 83d5e30027ea; files: src/gateway/session-utils.ts)
  • steipete: Committed the original title-derivation work, authored the session-list label fallback commit, and directly patched this PR branch to prioritize explicit labels and preserve /name suggestions. (role: committer and recent area contributor; confidence: high; commits: 83d5e30027ea, 9d9fff2991a9, 7c2065603d02; files: src/gateway/session-utils.ts, src/gateway/session-utils.test.ts, src/auto-reply/reply/commands-name.ts)
  • azade-c: Authored the commit that exposed session labels through sessions.list and label lookup, which is the persisted metadata this PR now prioritizes in derived titles. (role: label contract contributor; confidence: medium; commits: 3133c7c84e8a; files: src/gateway/server-methods/sessions.ts, src/gateway/session-utils.ts)
  • BSG2000: Authored the merged /name command that persists user-controlled session labels and opened the linked bug report describing this display drift. (role: adjacent session-naming contributor; confidence: medium; commits: b48238aa88b0; files: src/auto-reply/reply/commands-name.ts, docs/tools/slash-commands.md)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. labels Jul 2, 2026
@SunnyShu0925

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Proof updated — real runtime evidence added beyond unit tests:

1. Direct runtime proof (node --import tsx calling production deriveSessionTitle):

label-only → "My Custom /name"               ← was: UUID
label + firstUserMessage → "My Custom /name"  ← was: "Hello..." (auto-derived)
subject + label → "Dev Team Chat"              ← subject still wins ✓
displayName + label → "Explicit Title"         ← displayName still wins ✓
empty label → "Hello!"                         ← whitespace gate works ✓

2. Full pipeline proof (listSessionsFromStore with includeDerivedTitles=true, matching TUI picker code path):

Label-only sessions now get derivedTitle: "My Renamed Session" instead of UUID.

3. Supplementary unit tests: 6 new cases + 10 existing, all 3 CI shards pass.

Not tested: Live Control UI/TUI browser session rename and refresh (needs running gateway + browser — maintainer can use @openclaw-mantis visual task: verify a /name-renamed Control UI or TUI session shows the persisted label after refresh/reconnect instead of the UUID).

@clawsweeper

clawsweeper Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 2, 2026
@SunnyShu0925

Copy link
Copy Markdown
Contributor Author

Proof updated with real gateway session store evidence (redacted production sessions.json, 19 entries, 11 with /name labels) added to PR body. See Evidence section for full output.

Summary: All 11 real production sessions with /name labels but no displayName/subject now correctly resolve derivedTitle from label. Before this fix, they would have shown UUID prefixes. Subject and displayName still take precedence as expected.

@clawsweeper clawsweeper Bot added rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jul 2, 2026
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. labels Jul 2, 2026
@steipete steipete self-assigned this Jul 3, 2026
SunnyShu0925 and others added 4 commits July 3, 2026 09:21
When a session is renamed with /name, the user-provided label is persisted
in sessions.json but was ignored by deriveSessionTitle. This caused the
TUI session picker and other derived-title consumers to show auto-generated
or UUID-based names instead of the user's label.

Add entry.label to the deriveSessionTitle fallback chain after
displayName and subject, before the auto-derived firstUserMessage and
sessionId fallbacks. This aligns with the existing ACP translator
precedence (derivedTitle ?? displayName ?? label ?? key).

Related to openclaw#98742

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@steipete
steipete force-pushed the fix/session-label-title-98742 branch from a789783 to bac3b5d Compare July 3, 2026 08:33
@steipete

steipete commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Land-ready verification for exact head bac3b5d4e14ec69c13ac925c8ca17179ab59c5bd:

  • Explicit /name labels now win in the canonical Gateway title derivation before generated displayName/subject metadata.
  • Preserved no-argument /name suggestions by deriving the suggestion from a shallow copy with the current label removed.
  • Gateway/session utility coverage — 444 passed; name-command regressions — 10 passed.
  • Live source-built Gateway proof — sessions.patch persisted Durable Custom Label; sessions.list(includeDerivedTitles=true) returned it as derivedTitle even with competing generated group display and subject values.
  • Two accepted autoreview findings were fixed; final local and full-branch reviews are clean.
  • Repo-native prepare gate — exact-head hosted CI/Testbox passed.

No screenshot attached: this fixes session metadata returned over Gateway RPC; the before/after proof is the exact RPC result. Thanks @SunnyShu0925 for the fix.

@steipete
steipete merged commit 68e06b9 into openclaw:main Jul 3, 2026
104 of 106 checks passed
@steipete

steipete commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 4, 2026
…ain (openclaw#98841)

* fix(gateway): include session label in deriveSessionTitle fallback chain

When a session is renamed with /name, the user-provided label is persisted
in sessions.json but was ignored by deriveSessionTitle. This caused the
TUI session picker and other derived-title consumers to show auto-generated
or UUID-based names instead of the user's label.

Add entry.label to the deriveSessionTitle fallback chain after
displayName and subject, before the auto-derived firstUserMessage and
sessionId fallbacks. This aligns with the existing ACP translator
precedence (derivedTitle ?? displayName ?? label ?? key).

Related to openclaw#98742

Co-Authored-By: Claude Opus 4.8 <[email protected]>

* test(gateway): tighten session label precedence coverage

* fix(gateway): prioritize explicit session labels

* fix(commands): preserve named-session suggestions

---------

Co-authored-by: Claude Opus 4.8 <[email protected]>
Co-authored-by: Peter Steinberger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway Gateway runtime P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: XS status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Control UI session names can disappear even though label is still persisted

2 participants