Skip to content

feat(desktop): reference bounded Session snapshots from Composer - #4446

Open
testikun wants to merge 27 commits into
apache:mainfrom
testikun:codex/issue-4309-session-reference
Open

feat(desktop): reference bounded Session snapshots from Composer#4446
testikun wants to merge 27 commits into
apache:mainfrom
testikun:codex/issue-4309-session-reference

Conversation

@testikun

@testikun testikun commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #4309

Add a read-only Session reference to the Composer @ menu.

  • The picker offers active, same-Runtime-Host Sessions other than the current one.
  • Selecting a Session reads one bounded snapshot and stages it as a provenance-preserving QuoteRef.
  • Session rows use the compact MessagesSquare conversation icon and show the Session name only.
  • @ keeps the complete list open; whitespace-separated input searches Session names only.
  • The reference never messages, wakes, forks, or imports the full history of the selected Session.
  • Existing file references and / commands keep their previous behavior.

The snapshot projection contains only non-empty user and assistant text. Tool calls, tool results, system records, and permission records stay out of the projection. The default snapshot budget is 12,000 characters (hard maximum 32,000), and omitted older transcript pages remain visible through the truncated provenance flag.

Verification

  • npm --workspace @maka/ui run typecheck
  • npm --workspace @maka/ui run build
  • node scripts/apply-dependency-patches.mjs applies all dependency patches successfully
  • npm --workspace @maka/core run typecheck
  • Core Session snapshot tests: 4 passed, including tiny-budget role-prefix regression coverage
  • Compiled UI suite: 285 passed across 29 suites
  • Real macOS Electron verification: 1 Playwright test passed, covering @, trailing @ , name selection, the MessagesSquare icon, and the staged Session chip

Real-window screenshots from the current PR build:

image image image

AI use

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: OpenAI Codex assisted with issue analysis, implementation, regression tests, and local verification. The human contributor remains responsible for review, accuracy, and submission.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

Add a read-only same-Host Session picker to the Composer and carry bounded transcript snapshots as provenance-preserving QuoteRefs. Keep snapshot reads redacted, bounded, reconnectable, and safe across owner changes.

Generated-by: OpenAI Codex
@testikun

testikun commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

Implementation note / 实现说明

This PR keeps the scope intentionally narrow: selecting @Session reads one bounded, read-only snapshot and stages it as a QuoteRef in the current Composer. It does not message, wake, fork, or follow the referenced Session, and it never imports the full transcript.

The snapshot is built from the Runtime Host transcript tail and keeps only non-empty user/assistant text. Same-Host filtering happens before selection; the IPC boundary rejects archived Sessions; omitted older transcript pages are preserved as truncated provenance. The send path waits for an in-flight snapshot and ignores stale results if the current Session changes, so an immediate send cannot silently lose or misroute the reference.

The Composer keeps Session references separate from serialized draft text and renders them with a distinct book icon. Existing file references and Skill mentions keep their previous behavior.

中文摘要:

本 PR 按 issue 的窄范围实现:在 Composer 的 @ 菜单选择 Session 后,只读取一次有界、只读快照,并作为带来源信息的 QuoteRef 注入当前消息;不会向目标 Session 发消息、唤醒、创建分支或导入完整历史。快照只保留用户和助手文本,同 Host、归档 Session、长历史截断、切换 Session 以及“选中后立即发送”的竞态都有明确保护。

@github-actions github-actions Bot added the effort/XL Under 2500 readable lines label Sep 1, 2026
testikun added 6 commits September 1, 2026 18:29
This reverts commit 5025030.

Generated-by: OpenAI Codex
Generated-by: OpenAI Codex
Generated-by: OpenAI Codex
@testikun
testikun force-pushed the codex/issue-4309-session-reference branch from d81736a to ada4863 Compare September 1, 2026 10:51
@testikun testikun closed this Sep 2, 2026
@testikun testikun reopened this Sep 2, 2026
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

No description provided.

testikun added 7 commits September 2, 2026 10:05
…ion-reference

# Conflicts:
#	apps/desktop/renderer-architecture.json
#	apps/desktop/src/renderer/app-shell.tsx
#	docs/astryx-surface-file-inventory.md
…ion-reference

# Conflicts:
#	apps/desktop/renderer-architecture.json
#	apps/desktop/src/renderer/composition/desktop-feature-services.tsx
#	docs/astryx-surface-file-inventory.md
…ion-reference

# Conflicts:
#	apps/desktop/renderer-architecture.json
#	apps/desktop/src/renderer/features/conversation/index.ts
#	patches/@astryxdesign+core+0.5.2.patch

@me2seeks me2seeks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

Method: traced the full path renderer → preload → ScopedIpcMain → main-process IPC → Runtime Host client → server subscription; built @maka/core at this head and ran the new tests locally (session-reference, events: 9/9 pass; the new isQuoteRef assertions fail on main, so they pin the change). Two suspected issues were checked and cleared before listing anything: the extra scope argument in preload is consumed and validated by ScopedIpcMain (not a parameter-order bug), and Session names are capped at 80 code points (SESSION_NAME_MAX_CODE_POINTS), so Session: <name> cannot overflow the 200-char quote-label limit at the send boundary.

Findings

P1 — Branch conflicts with main and carries an unrelated change. packages/cli/src/__tests__/runtime-host-local-target-activation.test.ts bumps settlementTimeoutMs 50 → 500 (commit 96de6d6), which is unrelated to Session references. main already fixed the same test differently in #4469, and the two edits textually conflict. On rebase, drop this hunk and take main's version; regenerate docs/astryx-surface-file-inventory.md to clear the second conflict. Please keep the PR scoped to the feature.

P2 — The e2e verification case is not committed. Verification describes one real-Electron Playwright test covering @, trailing @ , name selection, the MessagesSquare icon, and the staged chip, but no spec under apps/desktop/e2e/ is in this diff. Recent practice (#3981) commits exactly this class of interaction regression as an e2e spec. Either commit the spec or state why unit/integration coverage is sufficient here.

P2 — useComposerQuotes' mutable bucket needs a guard rail. use-composer-quotes.ts:34 mutates a ref during render and publish() shallow-copies the map while sharing bucket array references. The live array is what makes same-tick send observe a freshly picked snapshot (the "send waits for the snapshot" test pins this), but the array's identity now survives across mutations: any future useMemo/useEffect keyed on pendingQuotes silently goes stale. I verified no current consumer does this. Cheapest fix now: document on the returned pendingQuotes that its identity must not be used as a memo/effect dependency; alternatively schedule a follow-up to replace closure capture with an explicit getPendingQuotes(draftKey) accessor in the send path.

P3 — Truncation can split a surrogate pair. session-reference.ts:119 (text.slice(0, contentBudget)) and the join slice at :130 cut at UTF-16 code-unit boundaries; a message containing emoji at the budget edge yields a lone surrogate in model context. Backing off to a surrogate boundary after slicing is enough.

P3 — The vendored useTriggerMenu hunk should be tracked upstream. The @-across-whitespace behavior rides the @astryxdesign/core patch (patches/README.md documents the removal condition — good). The old Composer comment already said "the fix belongs upstream"; please file the upstream issue/PR so the hunk can eventually be deleted.

Production code that can be deleted

None identified. composer-mentions.tsx and use-app-shell-composer-quotes.ts shrink to thin compatibility entries; the moved logic lands in the existing feature-services pattern rather than a parallel path.

Low-quality tests to delete or replace

None identified. The new tests assert behavior, not implementation: redaction of tool/system records, truncation accounting including the role-prefix edge, quote-attribute escaping against tag injection (<research>), subscription close semantics, and the all-or-nothing provenance validation at both the codec and the IPC boundary.

Review-relevant risks

QuoteRef is part of the event log and wire contract; this PR extends it with optional fields (old payloads still validate against the widened shape). The @ menu now also stays open across whitespace for file mentions, a user-visible behavior change beyond Session references — stated in the Summary and consistent with the AND-of-substring matcher. Per CONTRIBUTING.md, material user-visible and contract changes require independent human review; this automated review is not an approval.

Conclusion

  1. The solution is optimal for the actual problem: it reuses the QuoteRef transport and the bounded-tail subscription instead of creating a parallel channel, and the three budget layers (Core 12k/32k, IPC 32k, renderer 32k) agree.
  2. Deletable production code: none identified.
  3. Deletable/replaceable tests: none identified.
  4. Deeper refactor: not required; the features/conversation extraction follows the established services pattern.
  5. Merge readiness: not yet — the P1 conflict/unrelated hunk must be resolved and the two P2 items answered or planned.
  6. Residual risks: the @-menu behavior change for file mentions is the main product call; cross-version quote-field skew is bounded by the shared !== true picker filter and co-versioned desktop/Host releases.

…ion-reference

# Conflicts:
#	docs/astryx-surface-file-inventory.md
#	packages/cli/src/__tests__/runtime-host-local-target-activation.test.ts
@testikun

testikun commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Addressed in ce7b65a75:

  • Synced with current main, dropped the unrelated CLI timeout hunk in favor of test(cli): wait for hung settlement before the activator deadline #4469, and regenerated the Astryx surface inventory.
  • Added apps/desktop/e2e/composer-session-reference.spec.ts, covering @, trailing @ browsing, name-only search, the MessagesSquare icon, the staged Session chip, and chip consumption on send.
  • Documented the intentional live-bucket contract for pendingQuotes: consumers must read its contents and must not use its stable array identity as a memo/effect dependency.
  • Made Session snapshot truncation back off at UTF-16 surrogate boundaries and added regression tests for emoji at both truncation paths.

The @astryxdesign/core trigger-menu change remains a local compatibility patch as documented in patches/README.md; upstream tracking is a follow-up outside this PR's implementation scope.

Local verification: targeted Electron E2E passed, Core snapshot/events tests passed, and Desktop/UI/Core typechecks passed.

…ion-reference

# Conflicts:
#	docs/astryx-surface-file-inventory.md

@hqhq1025 hqhq1025 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

Reviewed exact head 6c8d9ef905e05e77072d07af4e63c1131bfb23e7.

This change adds same-Host, non-shared Session discovery to the Composer @ picker, reads a bounded read-only transcript snapshot through Runtime Host IPC, stores source/timestamp/truncation provenance in QuoteRef, and folds that snapshot into the active model context. It also updates the Astryx trigger patch so @ search can span spaces and adds the corresponding unit, IPC, and Electron coverage.

Finding

One P1 trust-boundary issue is attached inline: retained user and assistant messages bypass the repository's canonical secret redaction, so a selected Session can forward credentials verbatim into the active Session's model request. This directly violates the accepted scope for credential filtering.

Verification

  • Clean npm ci at the exact head, including all dependency patches
  • build:test and full typecheck passed
  • Core: 777 passed; Runtime: 3,155 passed / 13 skipped; UI: 333 passed
  • Desktop: 1,998 passed / 8 cancelled / 0 failed; the cancellations are the existing MCP OAuth timer cases
  • Focused Session-reference, wire, IPC, Composer, and model-context suites: 63/63 passed
  • Real Electron Session-reference E2E: 3/3 repeated runs passed after the clean install
  • Clean synthetic merge onto current main 9d4002b38239d1f07cec57293b2633e506575139: build, full typecheck, 67 focused tests, renderer architecture 71/71 plus ledger, Biome, ASF headers, and diff checks passed
  • The exact-head secret probe showed Authorization: Bearer sk-live-secret-token-value unchanged in both createSessionSnapshot() and formatTextWithInlineRefs() output, while redactSecrets() returns Authorization: Bearer [redacted]

The hosted audit and windows_recovery checks are green. The required hosted test check is red in apps/desktop/e2e/code-scroll.spec.ts (an untouched file), so I am not treating the check set as green. I did not run native macOS/Windows UI coverage or a live third-party provider call; the model-facing formatter itself was exercised directly.

Conclusion: not merge-ready until the credential-redaction finding is fixed and re-reviewed on the resulting head.

Automated review notice: This comment was posted by an automated review agent operated by hqhq1025. It is not an independent human review and does not replace one.

Comment thread packages/core/src/session-reference.ts
testikun added 2 commits September 3, 2026 16:45
…ion-reference

# Conflicts:
#	apps/desktop/renderer-architecture.json
#	docs/astryx-surface-file-inventory.md
@testikun
testikun force-pushed the codex/issue-4309-session-reference branch from 018a577 to 660b48e Compare September 3, 2026 09:04
@github-actions github-actions Bot added effort/XXL Over 2500 readable lines and removed effort/XL Under 2500 readable lines labels Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/XXL Over 2500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(desktop): support referencing another session from the composer

3 participants