Skip to content

feat(thread-chat): 持久化后台生成,支持刷新恢复与消息版本操作 - #30

Merged
hifizz merged 304 commits into
codex/tavily-proactive-research-demofrom
p0-resume-messages
Sep 2, 2026
Merged

feat(thread-chat): 持久化后台生成,支持刷新恢复与消息版本操作#30
hifizz merged 304 commits into
codex/tavily-proactive-research-demofrom
p0-resume-messages

Conversation

@hifizz

@hifizz hifizz commented Aug 19, 2026

Copy link
Copy Markdown
Owner

关联 Issue

Refs #29

合并依赖

Blocked by #34

PR #30 在 Issue #34 完成前不得视为完成,也不得转为 Ready for review 或合并。

计划中的合并链路:

  1. 针对 Issue 架构重构:Thread Chat 领域模型、持久化与前端状态 #34 创建独立修复 PR,并以 p0-resume-messages 为目标分支。
  2. Issue 架构重构:Thread Chat 领域模型、持久化与前端状态 #34 的领域模型、持久化、服务端命令边界、前端状态重构和规定的回归验证完成后,将该修复 PR 合入 p0-resume-messages
  3. p0-resume-messages 继续作为 PR feat(thread-chat): 持久化后台生成,支持刷新恢复与消息版本操作 #30 的汇总分支,最后由 PR feat(thread-chat): 持久化后台生成,支持刷新恢复与消息版本操作 #30 整体进入主干合并链路。

PR #30 只有在 Issue #34 已完成、相关 OpenSpec/ADR 已收口、迁移和回归验证通过后,才可以重新标记为 Ready for review。

本 PR 解决 Issue #29 中“客户端断连后任务继续执行、刷新恢复最终结果、重试不重复消息/计费”的韧性部分;request/error ID、跨层 trace、结构化 telemetry 与告警仍留在 Issue #29 后续完成。

背景

此前 thread-chat 的回复流由浏览器直接持有:用户刷新、关闭标签页或网络抖动后,前端 SSE 会断开,正在生成的 assistant 回复可能整条丢失;即使模型随后完成,页面也无法恢复最终结果。异常状态还可能留下只有 user message、没有可恢复 assistant 的“孤儿轮次”。

这个 PR 将生成任务从浏览器生命周期中解耦,同时补齐消息编辑、重新生成、版本切换、反馈和失败恢复能力。

主要改动

1. 服务端持有 generation 生命周期

  • 新增 owner-scoped branch_generations sidecar,记录 attempt、current 状态、turn snapshot、heartbeat、结构化结果、usage 和 billing 状态。
  • 调用模型前,严格持久化 user message、assistant placeholder 和 generation identity;持久化失败时不发起付费模型请求。
  • 浏览器断连只停止消费本地流,不再传播为模型取消;只有显式 Stop 才会请求服务端终止 generation。
  • 服务端独立消费完整响应流,并以事务完成终态持久化和幂等计费。
  • 通过 current-attempt CAS 防止旧 Retry/Regenerate 结果晚到后覆盖当前回复。
  • stale generation 超出租约后收敛为可重试失败,避免页面永久转圈。

2. 刷新后恢复后台状态和最终回复

  • Tree GET 会协调持久化树与 generation sidecar,合并 completed/failed/stopped 终态。
  • generation 仍在运行时,页面展示“正在后台生成,完成后显示”并轮询状态。
  • generation 完成后,正文、Markdown Artifact、联网研究结果、来源和研究计划会原子恢复。
  • P0 只恢复后台状态与最终结果,不重放刷新期间错过的 token 动画。

3. 不可变消息 DAG 与消息操作

  • 将消息历史升级为 strict schema-v2 DAG,以 parentMessageIdactiveLeafMessageId 表达回复版本。
  • 编辑 user message 会创建 sibling user + assistant;重新生成会创建 sibling assistant,不覆盖原消息。
  • 支持回复版本切换,并保留旧版本派生的子 Thread、引用、fork 和 Artifact provenance。
  • 为 user message 增加复制、重新编辑;为完成的 assistant message 增加复制、重新生成、点赞和点踩。
  • pending、streaming、error 回复不展示完成态 toolbar;失败使用独立 Retry 入口。
  • orphan user / interrupted assistant 可从原位置重试,不再让整棵树失去操作入口。

4. Message feedback 与 generation 解耦

  • 产品反馈绑定稳定的 messageId,不再要求浏览器持有 generationId
  • 新增 branch_message_feedback 和 owner-scoped message feedback API。
  • 重新生成的新 message 不继承旧反馈;切回旧版本时恢复原 message 的反馈。
  • 系统生成且标记为 done 的 assistant message 必须能在服务端反查到 completed generation。

5. 并发、所有权与一致性保护

  • branch tree、generation、Stop、版本切换和 feedback API 全部按当前登录用户隔离;非 owner 统一返回不泄露资源存在性的响应。
  • branch_trees.revision + CAS 防止旧标签页用整树快照覆盖新节点、版本选择或 Artifact。
  • generation start intent、tree revision 和 strict-v2 graph 均为显式必填契约。
  • 运行中的 generation 会阻止删除其持久化目标。

数据库与 API

新增/调整:

  • branch_generations
  • branch_message_feedback
  • branch_trees.user_id / branch_trees.revision
  • usage_records.app_generation_id
  • GET /api/branch-generations/:generationId
  • POST /api/branch-generations/:generationId/stop
  • PATCH /api/branch-trees/:treeId/active-leaf
  • PUT /api/branch-trees/:treeId/messages/:messageId/feedback

部署与兼容性

  • 部署前必须先运行 pnpm db:migrate,再发布依赖新 schema 的服务端和客户端。
  • 本实现只接受 strict schema-v2、显式 generation intent 和 revision,不保留旧线性树或 generation-scoped feedback 的兼容路径。
  • 当前阶段不会在进程崩溃后恢复同一次供应商模型执行;stale lease 会明确收敛为失败并允许重试。

详细设计与行为契约:

  • openspec/changes/persist-thread-chat-generations/
  • openspec/changes/add-thread-chat-message-actions/

验证

已覆盖:

  • generation start replay、current attempt、Stop/complete 竞态、supersede、stale lease 和幂等计费
  • tree revision CAS、跨用户隔离和 generation-vs-tree 写入竞态
  • strict message graph、编辑/重生成 patch、版本切换和 Artifact provenance
  • message feedback set/repeat/switch/clear、刷新恢复和 owner isolation
  • partial/error/empty reply、Markdown Artifact 与联网研究结果的结构化投影
  • 刷新期间后台继续生成、完成后恢复最终答案、列模式与画布模式一致性

执行检查:

  • pnpm typecheck
  • pnpm lint
  • pnpm openspec:validate
  • focused thread-chat pure/controller/database tests
  • next build --webpack
  • ego-browser nodejs localhost end-to-end verification

@cr-gpt

cr-gpt Bot commented Aug 19, 2026

Copy link
Copy Markdown

Seems you are using me but didn't get OPENAI_API_KEY seted in Variables/Secrets for this repo. you could follow readme for more information

@vercel

vercel Bot commented Aug 19, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
thread-chatbot Error Error Sep 2, 2026 4:05pm UTC

@cr-gpt

cr-gpt Bot commented Aug 19, 2026

Copy link
Copy Markdown

Seems you are using me but didn't get OPENAI_API_KEY seted in Variables/Secrets for this repo. you could follow readme for more information

@hifizz hifizz changed the title feat: 修复P0级问题,前端抖动后后端需要继续保存消息,不能丢失.刷新后能看到最终生成的消息 feat(thread-chat): 持久化后台生成,支持刷新恢复与消息版本操作 Aug 19, 2026
@cr-gpt

cr-gpt Bot commented Aug 20, 2026

Copy link
Copy Markdown

Seems you are using me but didn't get OPENAI_API_KEY seted in Variables/Secrets for this repo. you could follow readme for more information

@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 555 files, which is 255 over the limit of 300.

To get a review, reduce the PR to 300 files or fewer by splitting it into smaller PRs or changing its base branch.

Usage-priced reviews support at most 300 files.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Team

Run ID: f0e86f0f-3286-40f0-b7a5-85be7f729193

📥 Commits

Reviewing files that changed from the base of the PR and between 59df9eb and bfd238f.

⛔ Files ignored due to path filters (5)
  • evals/agent/fixtures/corrupt.pdf is excluded by !**/*.pdf
  • evals/agent/fixtures/synthetic-report.pdf is excluded by !**/*.pdf
  • evals/agent/fixtures/synthetic-status.svg is excluded by !**/*.svg
  • evals/agent/fixtures/unsupported.bin is excluded by !**/*.bin
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (555)
  • .agents/skills/ai-sdk/SKILL.md
  • .agents/skills/debug-root/SKILL.md
  • .agents/skills/migrate-ai-sdk-v6-to-v7/SKILL.md
  • .coderabbit.yaml
  • .env.example
  • .github/workflows/agent-evals-scheduled.yml
  • .github/workflows/agent-evals.yml
  • .github/workflows/openspec.yml
  • .github/workflows/project-workspace-ci.yml
  • .gitignore
  • .nvmrc
  • CLAUDE.md
  • README.md
  • README.zh-CN.md
  • app/api/attachments/[id]/ingest/route.ts
  • app/api/attachments/[id]/insights/route.ts
  • app/api/attachments/[id]/route.ts
  • app/api/attachments/route.ts
  • app/api/branch-title/route.ts
  • app/api/branch-trees/[treeId]/route.ts
  • app/api/branch-trees/route.ts
  • app/api/chat/conversation-text.ts
  • app/api/chat/request-context.ts
  • app/api/chat/research-context.ts
  • app/api/chat/research-tool-capabilities.ts
  • app/api/chat/route.ts
  • app/api/chat/stream-lifecycle.ts
  • app/api/chat/surface-tools.ts
  • app/api/chat/system-prompt.ts
  • app/api/chat/tool-set.ts
  • app/api/chat/tool-step-policy.ts
  • app/api/thread-chat/v1/artifacts/[artifactId]/route.ts
  • app/api/thread-chat/v1/messages/[messageId]/edit/route.ts
  • app/api/thread-chat/v1/messages/[messageId]/feedback/route.ts
  • app/api/thread-chat/v1/messages/[messageId]/retry/route.ts
  • app/api/thread-chat/v1/messages/[messageId]/route.ts
  • app/api/thread-chat/v1/messages/[messageId]/stop/route.ts
  • app/api/thread-chat/v1/messages/[messageId]/stream/route.ts
  • app/api/thread-chat/v1/projects/[projectId]/files/[attachmentId]/route.ts
  • app/api/thread-chat/v1/projects/[projectId]/files/route.ts
  • app/api/thread-chat/v1/projects/[projectId]/route.ts
  • app/api/thread-chat/v1/projects/[projectId]/start/route.ts
  • app/api/thread-chat/v1/projects/route.ts
  • app/api/thread-chat/v1/threads/[threadId]/forks/route.ts
  • app/api/thread-chat/v1/threads/[threadId]/messages/route.ts
  • app/api/thread-chat/v1/threads/[threadId]/route.ts
  • app/api/thread-chat/v1/threads/[threadId]/title/route.ts
  • app/api/title/route.ts
  • app/thread-chat-gate-3-harness/[projectId]/page.tsx
  • app/thread-chat/[treeId]/page.tsx
  • app/thread-chat/attachment-composer-demo/page.tsx
  • app/thread-chat/branching/assistant/anchored-assistant-body.tsx
  • app/thread-chat/branching/assistant/anchored-markdown.tsx
  • app/thread-chat/branching/assistant/assistant-part-render-plan.ts
  • app/thread-chat/branching/assistant/web-research-placement.ts
  • app/thread-chat/branching/branchable-chat.tsx
  • app/thread-chat/branching/selection-bubble.tsx
  • app/thread-chat/branching/selection/bubble-position.ts
  • app/thread-chat/branching/selection/bubble-shape.tsx
  • app/thread-chat/branching/selection/selection-bubble.tsx
  • app/thread-chat/branching/selection/selection-composer-dimensions.ts
  • app/thread-chat/branching/selection/selection-draft-guard.css
  • app/thread-chat/branching/selection/selection-placement-map.tsx
  • app/thread-chat/branching/selection/text-anchor.ts
  • app/thread-chat/branching/selection/use-assistant-text-selection.ts
  • app/thread-chat/chat/actions/assistant-message-toolbar.tsx
  • app/thread-chat/chat/actions/message-action-commands.ts
  • app/thread-chat/chat/actions/message-action-presentation.ts
  • app/thread-chat/chat/actions/message-action-session-logic.ts
  • app/thread-chat/chat/actions/message-action-types.ts
  • app/thread-chat/chat/actions/message-toolbar.tsx
  • app/thread-chat/chat/actions/use-copy-markdown.ts
  • app/thread-chat/chat/actions/use-message-actions.ts
  • app/thread-chat/chat/chat-view.tsx
  • app/thread-chat/chat/composer/attachment-composer-demo-model.ts
  • app/thread-chat/chat/composer/attachment-composer-demo.tsx
  • app/thread-chat/chat/composer/conversation-composer-logic.ts
  • app/thread-chat/chat/composer/conversation-composer.tsx
  • app/thread-chat/chat/composer/thread-model-selector.tsx
  • app/thread-chat/chat/message/conversation-message-logic.ts
  • app/thread-chat/chat/message/conversation-message.tsx
  • app/thread-chat/chat/message/editable-user-message.tsx
  • app/thread-chat/chat/message/markdown-body.tsx
  • app/thread-chat/chat/message/smooth-text.ts
  • app/thread-chat/chat/message/ui-message-parts.tsx
  • app/thread-chat/core/message-graph.ts
  • app/thread-chat/core/projected-store.ts
  • app/thread-chat/core/projections.ts
  • app/thread-chat/core/seed.ts
  • app/thread-chat/core/selectors.ts
  • app/thread-chat/core/store.ts
  • app/thread-chat/core/types.ts
  • app/thread-chat/core/use-thread-store.ts
  • app/thread-chat/gate-3-harness/mock-v1-runtime.ts
  • app/thread-chat/gate-3-harness/normalized-harness.tsx
  • app/thread-chat/layout.tsx
  • app/thread-chat/net/assistant-output.ts
  • app/thread-chat/net/boot/conversation-boot.ts
  • app/thread-chat/net/branch-title.ts
  • app/thread-chat/net/chat-controller.ts
  • app/thread-chat/net/client.ts
  • app/thread-chat/net/commands/conversation-commands.ts
  • app/thread-chat/net/persist.ts
  • app/thread-chat/net/persistence/workspace-state.ts
  • app/thread-chat/net/project-file-upload.ts
  • app/thread-chat/net/prompt.ts
  • app/thread-chat/net/prompt/prompt-pure.ts
  • app/thread-chat/net/sanitize-loaded-state.ts
  • app/thread-chat/net/stream/generation-connection.ts
  • app/thread-chat/net/stream/sse-client.ts
  • app/thread-chat/net/stream/terminal-poller.ts
  • app/thread-chat/net/stream/ui-message-reducer.ts
  • app/thread-chat/net/transient-state.ts
  • app/thread-chat/net/ui-stream.ts
  • app/thread-chat/orchestration/artifact-drawer.tsx
  • app/thread-chat/orchestration/artifacts/artifact-drawer.tsx
  • app/thread-chat/orchestration/artifacts/markdown-artifact-card.tsx
  • app/thread-chat/orchestration/artifacts/message-artifacts-logic.ts
  • app/thread-chat/orchestration/artifacts/message-artifacts.tsx
  • app/thread-chat/orchestration/artifacts/project-panel.tsx
  • app/thread-chat/orchestration/artifacts/store-bound-project-panel.tsx
  • app/thread-chat/orchestration/canvas-node.tsx
  • app/thread-chat/orchestration/canvas/canvas-actions.ts
  • app/thread-chat/orchestration/canvas/canvas-card-dimensions.ts
  • app/thread-chat/orchestration/canvas/canvas-dimensions.ts
  • app/thread-chat/orchestration/canvas/canvas-expand.tsx
  • app/thread-chat/orchestration/canvas/canvas-layout.ts
  • app/thread-chat/orchestration/canvas/canvas-node.tsx
  • app/thread-chat/orchestration/canvas/thread-canvas.tsx
  • app/thread-chat/orchestration/canvas/use-canvas-layout.ts
  • app/thread-chat/orchestration/columns/placement.ts
  • app/thread-chat/orchestration/columns/thread-columns.tsx
  • app/thread-chat/orchestration/columns/use-column-resize.ts
  • app/thread-chat/orchestration/columns/use-column-slots.ts
  • app/thread-chat/orchestration/columns/use-column-viewport.ts
  • app/thread-chat/orchestration/navigation/account-button.tsx
  • app/thread-chat/orchestration/navigation/switcher-dimensions.ts
  • app/thread-chat/orchestration/navigation/thread-chat-topbar-logic.ts
  • app/thread-chat/orchestration/navigation/thread-chat-topbar.tsx
  • app/thread-chat/orchestration/navigation/thread-switcher-panel.tsx
  • app/thread-chat/orchestration/navigation/thread-switcher.tsx
  • app/thread-chat/orchestration/navigation/tree-list-row.tsx
  • app/thread-chat/orchestration/navigation/tree-list.tsx
  • app/thread-chat/orchestration/overlays/dialog-close-to-shell.ts
  • app/thread-chat/orchestration/overlays/help-panel.tsx
  • app/thread-chat/orchestration/overlays/shortcut-hint.tsx
  • app/thread-chat/orchestration/overlays/use-workspace-overlays.ts
  • app/thread-chat/orchestration/overlays/web-research-panel.tsx
  • app/thread-chat/orchestration/overlays/workspace-overlay-logic.ts
  • app/thread-chat/orchestration/overlays/workspace-toast-logic.ts
  • app/thread-chat/orchestration/overlays/workspace-toast.tsx
  • app/thread-chat/orchestration/thread-columns.tsx
  • app/thread-chat/orchestration/thread-switcher.tsx
  • app/thread-chat/orchestration/workspace/use-conversation-runtime.ts
  • app/thread-chat/orchestration/workspace/use-normalized-workspace.ts
  • app/thread-chat/styles/artifact-card.css
  • app/thread-chat/styles/boot-loading.css
  • app/thread-chat/styles/branch-source.css
  • app/thread-chat/styles/canvas.css
  • app/thread-chat/styles/columns-collapse.css
  • app/thread-chat/styles/columns.css
  • app/thread-chat/styles/composer.css
  • app/thread-chat/styles/drawer.css
  • app/thread-chat/styles/help-panel.css
  • app/thread-chat/styles/keyframes.css
  • app/thread-chat/styles/markdown.css
  • app/thread-chat/styles/message-actions.css
  • app/thread-chat/styles/messages-stream.css
  • app/thread-chat/styles/messages.css
  • app/thread-chat/styles/scrollbar.css
  • app/thread-chat/styles/selection-extras.css
  • app/thread-chat/styles/selection.css
  • app/thread-chat/styles/switcher-subtree.css
  • app/thread-chat/styles/switcher.css
  • app/thread-chat/styles/tokens.css
  • app/thread-chat/styles/topbar-help.css
  • app/thread-chat/styles/topbar.css
  • app/thread-chat/thread-chat-demo.tsx
  • app/thread-chat/thread-chat.css
  • app/thread-chat/tree-redirect.tsx
  • components/assistant-ui/model-selector.tsx
  • constants/ark.ts
  • constants/generation.ts
  • constants/model-call.ts
  • constants/model.ts
  • constants/observability.ts
  • constants/pricing.ts
  • constants/project-workspace.ts
  • constants/research.ts
  • constants/selection-bubble.ts
  • constants/thread-chat-stream.ts
  • constants/thread-chat.ts
  • docs/composer/01-composer-interaction-system-research.md
  • docs/composer/02-attachment-composer-demo-mvp.md
  • docs/markdown/syntax-highlighting-research.md
  • docs/observability/01-implementation-baseline.md
  • docs/observability/02-telemetry-foundation.md
  • docs/observability/03-agent-trace-lifecycle.md
  • docs/observability/04-provider-attempts.md
  • docs/observability/05-feedback-scores.md
  • docs/observability/06-langfuse-cloud-rollout.md
  • docs/observability/07-loop-engineering.md
  • docs/observability/08-operations-and-acceptance.md
  • docs/observability/evidence/langfuse-rollout-template.md
  • docs/project/01-project-workspace-research.md
  • docs/project/02-dependent-thread-handoff-research.md
  • docs/project/03-reference-and-outcome-preliminary-research.md
  • docs/project/04-project-mvp-scope-and-roadmap.md
  • drizzle.test.config.ts
  • drizzle/0001_mysterious_wendigo.sql
  • drizzle/0002_complex_millenium_guard.sql
  • drizzle/0003_strong_bulldozer.sql
  • drizzle/0004_normalized_thread_chat_conversations.sql
  • drizzle/0005_legacy_thread_chat_backup.sql
  • drizzle/0006_ambitious_silk_fever.sql
  • drizzle/meta/0001_snapshot.json
  • drizzle/meta/0002_snapshot.json
  • drizzle/meta/0003_snapshot.json
  • drizzle/meta/0004_snapshot.json
  • drizzle/meta/0005_snapshot.json
  • drizzle/meta/0006_snapshot.json
  • drizzle/meta/_journal.json
  • e2e/observability/agent-trace-contract.test.mjs
  • e2e/observability/eval-foundation.test.mjs
  • e2e/observability/eval-loop.test.mjs
  • e2e/observability/eval-scorers.test.mjs
  • e2e/observability/feedback-score.test.mjs
  • e2e/observability/langfuse-release.test.mjs
  • e2e/observability/observability-foundation.test.mjs
  • e2e/observability/project-workspace-eval-harness.test.mjs
  • e2e/observability/provider-attempt.test.mjs
  • e2e/thread-chat/README.md
  • e2e/thread-chat/artifact-card-css-ownership.test.mjs
  • e2e/thread-chat/artifact-drawer-accessibility.test.mjs
  • e2e/thread-chat/artifact-drawer-copy.test.mjs
  • e2e/thread-chat/artifact-drawer-css.test.mjs
  • e2e/thread-chat/attachment-composer-demo-model.test.mjs
  • e2e/thread-chat/boot-loading-css-ownership.test.mjs
  • e2e/thread-chat/branch-source-css.test.mjs
  • e2e/thread-chat/canvas-card-dimensions.test.mjs
  • e2e/thread-chat/canvas-dimensions.test.mjs
  • e2e/thread-chat/canvas-expand-ownership.test.mjs
  • e2e/thread-chat/canvas-layout-cache.test.mjs
  • e2e/thread-chat/chat-conversation-text.test.mjs
  • e2e/thread-chat/chat-request-context.test.mjs
  • e2e/thread-chat/chat-surface-tools.test.mjs
  • e2e/thread-chat/chat-system-prompt.test.mjs
  • e2e/thread-chat/chat-tool-set.test.mjs
  • e2e/thread-chat/column-control-css-ownership.test.mjs
  • e2e/thread-chat/composer-css-source.test.mjs
  • e2e/thread-chat/conversation-composer.test.mjs
  • e2e/thread-chat/conversation-message.test.mjs
  • e2e/thread-chat/dialog-close-to-shell.test.mjs
  • e2e/thread-chat/help-panel-css-ownership.test.mjs
  • e2e/thread-chat/markdown-artifact-state.test.mjs
  • e2e/thread-chat/markdown-artifact.test.mjs
  • e2e/thread-chat/message-action-availability.test.mjs
  • e2e/thread-chat/message-action-contract-ownership.test.mjs
  • e2e/thread-chat/message-action-presentation.test.mjs
  • e2e/thread-chat/message-action-session.test.mjs
  • e2e/thread-chat/message-artifacts.test.mjs
  • e2e/thread-chat/message-feedback-contract.test.mjs
  • e2e/thread-chat/message-id-order-selector.test.mjs
  • e2e/thread-chat/message-quote-css-ownership.test.mjs
  • e2e/thread-chat/model-pricing-registry.test.mjs
  • e2e/thread-chat/model-selection.test.mjs
  • e2e/thread-chat/normalized-client-store.test.mjs
  • e2e/thread-chat/normalized-conversation-contract.test.mjs
  • e2e/thread-chat/normalized-conversation-db.test.mjs
  • e2e/thread-chat/normalized-cutover-db.test.mjs
  • e2e/thread-chat/normalized-framework-contract.test.mjs
  • e2e/thread-chat/normalized-generation-db.test.mjs
  • e2e/thread-chat/normalized-stream-session.test.mjs
  • e2e/thread-chat/normalized-ui-message-pipeline.test.mjs
  • e2e/thread-chat/normalized-v1-api-contract.test.mjs
  • e2e/thread-chat/normalized-v1-api-db.test.mjs
  • e2e/thread-chat/openrouter-models.test.mjs
  • e2e/thread-chat/project-artifact-context-isolation.test.mjs
  • e2e/thread-chat/project-contract-generation-boundary.test.mjs
  • e2e/thread-chat/project-panel-ui-contract.test.mjs
  • e2e/thread-chat/project-panel-workspace-state.test.mjs
  • e2e/thread-chat/project-workspace-api-db.test.mjs
  • e2e/thread-chat/project-workspace-context.test.mjs
  • e2e/thread-chat/project-workspace-db.test.mjs
  • e2e/thread-chat/project-workspace-history-stability.test.mjs
  • e2e/thread-chat/project-workspace-migration-compatibility.test.mjs
  • e2e/thread-chat/prompt-budget.test.mjs
  • e2e/thread-chat/research-context.test.mjs
  • e2e/thread-chat/research-events.test.mjs
  • e2e/thread-chat/research-router-context.test.mjs
  • e2e/thread-chat/search-abort.test.mjs
  • e2e/thread-chat/selection-composer-dimensions.test.mjs
  • e2e/thread-chat/selection-css-ownership.test.mjs
  • e2e/thread-chat/selection-observer-ownership.test.mjs
  • e2e/thread-chat/selection-placement-map-ownership.test.mjs
  • e2e/thread-chat/stream-lifecycle.test.mjs
  • e2e/thread-chat/style-extension-order.test.mjs
  • e2e/thread-chat/switcher-dimensions.test.mjs
  • e2e/thread-chat/text-anchor.test.mjs
  • e2e/thread-chat/thread-chat-topbar.test.mjs
  • e2e/thread-chat/thread-switcher-panel.test.mjs
  • e2e/thread-chat/tool-step-policy.test.mjs
  • e2e/thread-chat/topbar-css-ownership.test.mjs
  • e2e/thread-chat/tree-list-row.test.mjs
  • e2e/thread-chat/ui-message-parts-rendering.test.mjs
  • e2e/thread-chat/umapis-models.test.mjs
  • e2e/thread-chat/usage-cost-evidence.test.mjs
  • e2e/thread-chat/verify-attachment-composer-demo.mjs
  • e2e/thread-chat/verify-bubble-composer.mjs
  • e2e/thread-chat/verify-canvas-chat.mjs
  • e2e/thread-chat/verify-live.mjs
  • e2e/thread-chat/verify-markdown-artifact.mjs
  • e2e/thread-chat/verify-persist.mjs
  • e2e/thread-chat/verify-syntax-highlighting.mjs
  • e2e/thread-chat/verify-tree-list.mjs
  • e2e/thread-chat/web-research-placement.test.mjs
  • e2e/thread-chat/workspace-overlay.test.mjs
  • e2e/thread-chat/workspace-toast.test.mjs
  • evals/agent/README.md
  • evals/agent/baseline.ts
  • evals/agent/baselines/fixture-ci-v1.json
  • evals/agent/baselines/fixture-scheduled-v1.json
  • evals/agent/baselines/fixture-v1.json
  • evals/agent/cases.ts
  • evals/agent/cases/core-answer.json
  • evals/agent/cases/foundation.json
  • evals/agent/cases/memory-context.json
  • evals/agent/cases/multimodal.json
  • evals/agent/cases/project-workspace.json
  • evals/agent/cases/reliability.json
  • evals/agent/cases/search-routing.json
  • evals/agent/cli.ts
  • evals/agent/compare-cli.ts
  • evals/agent/compare.ts
  • evals/agent/executors/content.ts
  • evals/agent/executors/fixture.ts
  • evals/agent/executors/lifecycle.ts
  • evals/agent/executors/production-harness.ts
  • evals/agent/fingerprint.ts
  • evals/agent/fixtures/README.md
  • evals/agent/fixtures/judge-calibration.json
  • evals/agent/fixtures/synthetic-runbook.txt
  • evals/agent/identity.ts
  • evals/agent/isolation.ts
  • evals/agent/langfuse.ts
  • evals/agent/manifest.ts
  • evals/agent/manifests/v1.json
  • evals/agent/remote-policy.ts
  • evals/agent/result.ts
  • evals/agent/runner.ts
  • evals/agent/schema.ts
  • evals/agent/scorers/aggregate.ts
  • evals/agent/scorers/deterministic.ts
  • evals/agent/scorers/helpers.ts
  • evals/agent/scorers/index.ts
  • evals/agent/scorers/judge.ts
  • evals/agent/scorers/memory.ts
  • evals/agent/scorers/search.ts
  • evals/agent/scoring.ts
  • evals/agent/selection.ts
  • instrumentation.ts
  • lib/ai/embeddings.ts
  • lib/ai/generation-cancellation.ts
  • lib/ai/model-call-logger.ts
  • lib/ai/private-relay.ts
  • lib/ai/provider.ts
  • lib/ai/search.ts
  • lib/attachments/insights.ts
  • lib/auth/server.ts
  • lib/billing/credits.ts
  • lib/billing/usage-cost-evidence.ts
  • lib/chat/attachment-content-resolver.ts
  • lib/chat/attachment-context-policy.ts
  • lib/chat/markdown-artifact.ts
  • lib/chat/project-contract.ts
  • lib/chat/research-contract.ts
  • lib/chat/research-events.ts
  • lib/chat/research-router.ts
  • lib/chat/research-tools.ts
  • lib/chat/resolve-attachments.ts
  • lib/chat/tree-id.ts
  • lib/chat/web-research-activity.ts
  • lib/db/billing-schema.ts
  • lib/db/schema.ts
  • lib/observability/ai-sdk.ts
  • lib/observability/config.ts
  • lib/observability/context.ts
  • lib/observability/error.ts
  • lib/observability/feedback-backfill.ts
  • lib/observability/feedback-outbox.ts
  • lib/observability/feedback-post-commit.ts
  • lib/observability/feedback-score.ts
  • lib/observability/identity.ts
  • lib/observability/mask.ts
  • lib/observability/provider-attempt.ts
  • lib/observability/register-node.ts
  • lib/observability/release-readiness.ts
  • lib/observability/trace.ts
  • lib/observability/types.ts
  • lib/thread-chat/application/command-utils.ts
  • lib/thread-chat/application/compile-model-context.ts
  • lib/thread-chat/application/edit-turn.ts
  • lib/thread-chat/application/errors.ts
  • lib/thread-chat/application/fork-thread.ts
  • lib/thread-chat/application/index.ts
  • lib/thread-chat/application/project-mutations.ts
  • lib/thread-chat/application/prompt-policy.ts
  • lib/thread-chat/application/queries.ts
  • lib/thread-chat/application/retry-message.ts
  • lib/thread-chat/application/send-message.ts
  • lib/thread-chat/application/serialize-message-for-model.ts
  • lib/thread-chat/application/set-feedback.ts
  • lib/thread-chat/application/start-project.ts
  • lib/thread-chat/application/stop-message.ts
  • lib/thread-chat/application/title-generator.ts
  • lib/thread-chat/application/title-service.ts
  • lib/thread-chat/contracts/command-replay.ts
  • lib/thread-chat/contracts/commands.ts
  • lib/thread-chat/contracts/dto.ts
  • lib/thread-chat/contracts/errors.ts
  • lib/thread-chat/contracts/index.ts
  • lib/thread-chat/contracts/message-action-failure.ts
  • lib/thread-chat/contracts/message-feedback.ts
  • lib/thread-chat/contracts/stream.ts
  • lib/thread-chat/contracts/title-request.ts
  • lib/thread-chat/contracts/ui-message.ts
  • lib/thread-chat/contracts/ui-message.type-test.ts
  • lib/thread-chat/domain/conversation.ts
  • lib/thread-chat/domain/fork-context.ts
  • lib/thread-chat/domain/index.ts
  • lib/thread-chat/domain/message-graph.ts
  • lib/thread-chat/domain/root-thread.ts
  • lib/thread-chat/domain/selection-bubble.ts
  • lib/thread-chat/domain/selectors.ts
  • lib/thread-chat/domain/state-machine.ts
  • lib/thread-chat/domain/text-anchor.ts
  • lib/thread-chat/domain/timeline.ts
  • lib/thread-chat/domain/types.ts
  • lib/thread-chat/index.ts
  • lib/thread-chat/persistence/artifact-repository.ts
  • lib/thread-chat/persistence/command-repository.ts
  • lib/thread-chat/persistence/feedback-score-outbox-repository.ts
  • lib/thread-chat/persistence/index.ts
  • lib/thread-chat/persistence/mappers.ts
  • lib/thread-chat/persistence/message-parts.ts
  • lib/thread-chat/persistence/message-repository.ts
  • lib/thread-chat/persistence/project-file-repository.ts
  • lib/thread-chat/persistence/project-repository.ts
  • lib/thread-chat/persistence/thread-repository.ts
  • lib/thread-chat/persistence/transaction.ts
  • lib/thread-chat/server/auth.ts
  • lib/thread-chat/server/handlers.ts
  • lib/thread-chat/server/index.ts
  • lib/thread-chat/server/route-utils.ts
  • lib/thread-chat/server/start-session-after-commit.ts
  • lib/thread-chat/streaming/artifacts.ts
  • lib/thread-chat/streaming/checkpoint.ts
  • lib/thread-chat/streaming/finalize.ts
  • lib/thread-chat/streaming/generation-outcome.ts
  • lib/thread-chat/streaming/generation-plan.ts
  • lib/thread-chat/streaming/generation-tools.ts
  • lib/thread-chat/streaming/index.ts
  • lib/thread-chat/streaming/run-generation.ts
  • lib/thread-chat/streaming/runtime.ts
  • lib/thread-chat/streaming/session-store.ts
  • lib/thread-chat/streaming/sse.ts
  • lib/thread-chat/streaming/stream-session.ts
  • lib/thread-chat/streaming/ui-message-pipeline.ts
  • nixpacks.toml
  • openspec/changes/add-agent-observability-and-evaluation/.openspec.yaml
  • openspec/changes/add-agent-observability-and-evaluation/design.md
  • openspec/changes/add-agent-observability-and-evaluation/proposal.md
  • openspec/changes/add-agent-observability-and-evaluation/specs/agent-evaluation/spec.md
  • openspec/changes/add-agent-observability-and-evaluation/specs/agent-observability/spec.md
  • openspec/changes/add-agent-observability-and-evaluation/tasks.md
  • openspec/changes/add-attachment-composer-demo/.openspec.yaml
  • openspec/changes/add-attachment-composer-demo/design.md
  • openspec/changes/add-attachment-composer-demo/proposal.md
  • openspec/changes/add-attachment-composer-demo/specs/attachment-composer-demo/spec.md
  • openspec/changes/add-attachment-composer-demo/tasks.md
  • openspec/changes/add-branch-tree-persistence/proposal.md
  • openspec/changes/add-branch-tree-persistence/tasks.md
  • openspec/changes/add-bubble-composer/design.md
  • openspec/changes/add-bubble-composer/proposal.md
  • openspec/changes/add-bubble-composer/tasks.md
  • openspec/changes/add-canvas-conversations/proposal.md
  • openspec/changes/add-markdown-artifacts/markdown-generation-progress-research.md
  • openspec/changes/add-markdown-artifacts/plan.md
  • openspec/changes/add-markdown-artifacts/proposal.md
  • openspec/changes/add-project-workspace-mvp/.openspec.yaml
  • openspec/changes/add-project-workspace-mvp/design.md
  • openspec/changes/add-project-workspace-mvp/proposal.md
  • openspec/changes/add-project-workspace-mvp/specs/project-workspace/spec.md
  • openspec/changes/add-project-workspace-mvp/tasks.md
  • openspec/changes/add-thread-chat-message-actions/.openspec.yaml
  • openspec/changes/add-thread-chat-message-actions/design.md
  • openspec/changes/add-thread-chat-message-actions/ears-requirements.md
  • openspec/changes/add-thread-chat-message-actions/message-and-generation-identity-decision.md
  • openspec/changes/add-thread-chat-message-actions/message-dag-explainer.md
  • openspec/changes/add-thread-chat-message-actions/proposal.md
  • openspec/changes/add-thread-chat-message-actions/qa-regression-cases.md
  • openspec/changes/add-thread-chat-message-actions/specs/thread-chat-message-actions/spec.md
  • openspec/changes/add-thread-chat-message-actions/tasks.md
  • openspec/changes/add-tree-list-ui/proposal.md
  • openspec/changes/add-user-auth/design.md
  • openspec/changes/add-user-auth/proposal.md
  • openspec/changes/add-user-auth/tasks.md
  • openspec/changes/archive/2026-08-20-improve-branch-title-generation/.openspec.yaml
  • openspec/changes/archive/2026-08-20-improve-branch-title-generation/design.md
  • openspec/changes/archive/2026-08-20-improve-branch-title-generation/proposal.md
  • openspec/changes/archive/2026-08-20-improve-branch-title-generation/specs/branch-title-generation/spec.md
  • openspec/changes/archive/2026-08-20-improve-branch-title-generation/tasks.md
  • openspec/changes/archive/2026-08-21-generate-main-thread-title/.openspec.yaml
  • openspec/changes/archive/2026-08-21-generate-main-thread-title/design.md
  • openspec/changes/archive/2026-08-21-generate-main-thread-title/proposal.md
  • openspec/changes/archive/2026-08-21-generate-main-thread-title/specs/title-generation/spec.md
  • openspec/changes/archive/2026-08-21-generate-main-thread-title/tasks.md
  • openspec/changes/fix-thread-chat-help-panel/proposal.md
  • openspec/changes/normalize-thread-chat-conversations/.openspec.yaml
  • openspec/changes/normalize-thread-chat-conversations/design.md
  • openspec/changes/normalize-thread-chat-conversations/evidence/gate-0-ux-baseline.md
  • openspec/changes/normalize-thread-chat-conversations/evidence/gate-1-backend-evidence.md
  • openspec/changes/normalize-thread-chat-conversations/evidence/gate-2-stream-api-evidence.md
  • openspec/changes/normalize-thread-chat-conversations/evidence/gate-3-normalized-client-evidence.md
  • openspec/changes/normalize-thread-chat-conversations/evidence/gate-4-exit-evidence.md
  • openspec/changes/normalize-thread-chat-conversations/evidence/gate-4-legacy-retirement-inventory.md
  • openspec/changes/normalize-thread-chat-conversations/evidence/incident-2026-08-27-recoverable-tool-error-terminal-failed.md
  • openspec/changes/normalize-thread-chat-conversations/proposal.md
  • openspec/changes/normalize-thread-chat-conversations/runbooks/gate-4-cutover.md
  • openspec/changes/normalize-thread-chat-conversations/specs/conversation-client-state/spec.md
  • openspec/changes/normalize-thread-chat-conversations/specs/conversation-command-api/spec.md
  • openspec/changes/normalize-thread-chat-conversations/specs/conversation-cutover/spec.md
  • openspec/changes/normalize-thread-chat-conversations/specs/conversation-generation-lifecycle/spec.md
  • openspec/changes/normalize-thread-chat-conversations/specs/conversation-persistence/spec.md
  • openspec/changes/normalize-thread-chat-conversations/specs/domain/spec.md
  • openspec/changes/normalize-thread-chat-conversations/specs/thread-chat-stream-sessions/spec.md
  • openspec/changes/normalize-thread-chat-conversations/tasks.md
  • openspec/changes/persist-thread-chat-generations/.openspec.yaml
  • openspec/changes/persist-thread-chat-generations/design.md
  • openspec/changes/persist-thread-chat-generations/proposal.md
  • openspec/changes/persist-thread-chat-generations/specs/thread-chat-generation-persistence/spec.md
  • openspec/changes/persist-thread-chat-generations/tasks.md
  • openspec/specs/domain/spec.md
  • openspec/specs/title-generation/spec.md
  • package.json
  • proxy.ts
  • scripts/backfill-feedback-scores.ts
  • scripts/check-observability-release.ts
  • scripts/check-thread-chat-cutover.mjs
  • scripts/check-thread-chat-v1-boundaries.mjs
  • scripts/codex-worktree-setup.sh
  • scripts/drain-feedback-score-outbox.ts
  • scripts/reset-thread-chat-schema.mjs
  • scripts/setup-thread-chat-test-database.mjs
  • skills-lock.json

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Comment @coderabbitai help to get the list of available commands.

@cr-gpt

cr-gpt Bot commented Aug 20, 2026

Copy link
Copy Markdown

Seems you are using me but didn't get OPENAI_API_KEY seted in Variables/Secrets for this repo. you could follow readme for more information

@cr-gpt

cr-gpt Bot commented Aug 20, 2026

Copy link
Copy Markdown

Seems you are using me but didn't get OPENAI_API_KEY seted in Variables/Secrets for this repo. you could follow readme for more information

@hifizz

hifizz commented Aug 20, 2026

Copy link
Copy Markdown
Owner Author

[!IMPORTANT]

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7362da52-623d-49c8-bcb5-db22dd46ee55

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@coderabbitai review

@cr-gpt

cr-gpt Bot commented Aug 20, 2026

Copy link
Copy Markdown

Seems you are using me but didn't get OPENAI_API_KEY seted in Variables/Secrets for this repo. you could follow readme for more information

@cr-gpt

cr-gpt Bot commented Aug 20, 2026

Copy link
Copy Markdown

Seems you are using me but didn't get OPENAI_API_KEY seted in Variables/Secrets for this repo. you could follow readme for more information

@cr-gpt

cr-gpt Bot commented Aug 20, 2026

Copy link
Copy Markdown

Seems you are using me but didn't get OPENAI_API_KEY seted in Variables/Secrets for this repo. you could follow readme for more information

@cr-gpt

cr-gpt Bot commented Aug 20, 2026

Copy link
Copy Markdown

Seems you are using me but didn't get OPENAI_API_KEY seted in Variables/Secrets for this repo. you could follow readme for more information

hifizz added 8 commits August 21, 2026 11:16
Before: legacy retry and retryAssistant duplicated source lookup, parent-user resolution, IDs, regenerate-assistant intent, append-only patch preparation, and not-found/not-latest policy in the controller.

After: net/regeneration-command.ts owns pure assistant retry preparation and exposes a prepared start consumed by one controller helper. Assistant-retry policy strings/intents in the controller are zero and it shrank from 505 to 457 lines.

Automated: Prettier, TypeScript, targeted ESLint, valid sibling patch, missing/wrong-role source, non-latest source, legacy/new controller wiring, and an architecture assertion passed.

Manual: blocked before task-space creation because ego-browser could not connect to the ego_cli bootstrap. Per repository policy no alternate browser was used, and this check is not reported as passed.
Before: retryUserTurn created IDs, built retry-orphan-user intent, prepared the domain patch, mapped rejection, detached, and started generation inline in the controller.

After: net/regeneration-command.ts owns pure orphan-user retry preparation; the controller supplies IDs and consumes the shared prepared start. Orphan retry intent/error policy in the controller is zero and it shrank from 457 to 439 lines.

Automated: Prettier, TypeScript, targeted ESLint, active orphan success, completed-turn rejection, missing-user rejection, assistant-retry regression, controller wiring, and an architecture assertion passed.

Manual: blocked because ego-browser remained unavailable after the prior ego_cli bootstrap connection failure. Per repository policy no browser retry or alternate browser tool was used, and this check is not reported as passed.
Before: editAndRegenerate created IDs, built edit-last-user intent, prepared the domain patch, mapped rejection, detached, and started generation inline in the controller.

After: net/regeneration-command.ts owns pure user-edit preparation, including trim and quote-preserving append-only messages; the controller supplies IDs and consumes the shared prepared start. Direct domain patch construction/user-edit policy in the controller is zero and it shrank from 439 to 420 lines.

Automated: Prettier, TypeScript, targeted ESLint, trim/source/quote preservation, original-state immutability, empty/non-latest rejection, both retry preparation regressions, controller wiring, and an architecture assertion passed.

Manual: blocked because ego-browser remained unavailable after the ego_cli bootstrap connection failure. Per repository policy no alternate browser was used, and this check is not reported as passed.
Before: ChatView and CanvasExpand each owned an uncontrolled textarea, auto-grow limit, prefill focus, IME Enter guard, send/stop buttons, and model selector wiring. The same interaction capability could drift across column and canvas surfaces.

After: ConversationComposer owns the common behavior and exposes explicit column/canvas variants plus host callbacks. The canvas keeps its prior missing-state behavior: the textarea remains visible, the model selector is absent, and unavailable actions do not clear the draft. Pure submission and keyboard rules live in conversation-composer-logic for isolated verification. ChatView shrinks from 316 to 250 lines; canvas-node shrinks from 430 to 372 lines.

Automated verification: pnpm typecheck; targeted ESLint on the changed source/test files; node --import tsx e2e/thread-chat/conversation-composer.test.mjs; node --import tsx e2e/thread-chat/message-actions-controller.test.mjs; static duplicate assertion confirms neither host retains textarea, auto-grow, IME, or composer-root implementation; git diff --check.

Manual case: intended to verify column and canvas Enter, Shift+Enter, Chinese IME confirmation, prefill focus, model selector, send and stop parity at localhost:4040. Not executed because the mandated ego-browser bootstrap is unavailable; no alternate browser tool was used.
Before: ChatView and CanvasExpand independently rendered the same message role shell, pending/streaming visibility rules, background status, typing indicator, caret, error retry, editable user action, assistant toolbar, feedback, and turn variants. Fixes could drift between column and canvas surfaces.

After: ConversationMessage owns one message-level capability and accepts explicit slots for user fallback, assistant body, and post-message artifacts. Column-only role labels and bubble spacing remain props; canvas keeps its hidden user fallback when actions are unavailable and retains AnchoredMarkdown/artifact ownership. Pure conversation-message-logic centralizes the assistant presentation matrix. ChatView shrinks from 250 to 142 lines; canvas-node shrinks from 372 to 288 lines.

Automated verification: pnpm typecheck; targeted ESLint on changed source/test files; node --import tsx e2e/thread-chat/conversation-message.test.mjs covers waiting, streaming text, web research, and artifact-only states; node --import tsx e2e/thread-chat/message-actions-controller.test.mjs; static assertion confirms both hosts no longer import or implement generic message roles, status UI, or action components; git diff --check.

Manual case: intended to compare column and canvas for user edit/recovery, empty pending typing, streamed caret, background label, failed retry, copy/feedback/regenerate, variant switching, web research, and artifact cards. Not executed because the mandated ego-browser bootstrap remains unavailable; no alternate browser tool was used.
Before: the composite BranchableChat page module also exported the low-level AnchoredMarkdown renderer, so canvas-node imported an upper-level branching screen merely to reuse Markdown, smooth streaming, anchor painting, and click delegation. This coupled orchestration to a composite UI module and risked a file-level cycle.

After: branching/anchored-markdown.tsx owns that atomic presentation capability. BranchableChat and CanvasExpand compose it directly; branchable-chat now contains only branch-column assembly. The MarkdownBody ownership comment follows the new module. BranchableChat shrinks from 480 to 311 lines.

Automated verification: pnpm typecheck; targeted ESLint on the three component modules; node --import tsx e2e/thread-chat/text-anchor.test.mjs covers position, exact, fuzzy, threshold, loss, and substring recovery; architecture assertions confirm orchestration no longer imports branchable-chat and branchable-chat no longer owns MarkdownBody, smooth text, or DOM anchor painting; git diff --check.

Manual case: intended to verify stable and streaming Markdown in both column and canvas, research panel insertion offset, anchor highlight/footnote restoration, click navigation, and Command/Ctrl-click keep-source behavior. Not executed because the mandated ego-browser bootstrap remains unavailable; no alternate browser tool was used.
Before: BranchableChat and CanvasExpand each rebuilt the same AnchoredMarkdown plus WebResearchPanel composition, including the activity gate, recorded text offset fallback, route/plan projection, and completion state.

After: AnchoredAssistantBody exposes that atomic rich-reply capability to both surfaces. webResearchPlacement owns and tests the rule that no panel appears before the first activity and that activity insertion uses the recorded offset or zero fallback. BranchableChat shrinks from 311 to 296 lines; canvas-node shrinks from 288 to 271 lines.

Automated verification: pnpm typecheck; targeted ESLint; node --import tsx e2e/thread-chat/web-research-placement.test.mjs; node --import tsx e2e/thread-chat/generation-persistence.test.mjs; architecture assertion confirms neither host directly owns WebResearchPanel, research offsets, or AnchoredMarkdown composition; git diff --check.

Manual case: intended to compare no-activity routing, first search/read event insertion, recorded mid-answer insertion offset, streaming research progress, completion copy, and anchor navigation in both column and canvas. Not executed because the mandated ego-browser bootstrap remains unavailable; no alternate browser tool was used.
Before: BranchableChat and CanvasExpand independently selected artifact ids, skipped missing records, resolved source-thread depth, rendered Markdown progress, mapped completed cards, wired open actions, and applied canvas compact mode.

After: MessageArtifacts owns that message-level collection capability with compact as the only surface variant. It preserves progress without state/actions and exposes completed cards only when both records and an open action exist. selectMessageArtifacts keeps declared order while omitting unavailable records. BranchableChat shrinks from 296 to 277 lines; canvas-node shrinks from 271 to 248 lines.

Automated verification: pnpm typecheck; targeted ESLint; node --import tsx e2e/thread-chat/message-artifacts.test.mjs; node --import tsx e2e/thread-chat/generation-persistence.test.mjs; architecture assertion confirms neither host directly imports artifact card primitives, maps artifact ids, or reads the artifact table; git diff --check.

Manual case: intended to compare starting and streaming Markdown progress, compact canvas presentation, multiple completed artifacts in message order, missing artifact omission, source-depth color, and drawer opening in both surfaces. Not executed because the mandated ego-browser bootstrap remains unavailable; no alternate browser tool was used.
hifizz and others added 27 commits September 1, 2026 03:55
- keep bubble open on outside click / scroll / resize while draft exists
- ignore new text selections with a draft (copy-paste into the composer)
- Esc with a draft opens a confirm dialog and shakes the bubble
- entering/shake animations moved off steady-state to avoid tc-pop replay flash
- draft-guard styles co-located with the component
- focus the question textarea only after the measured bubble becomes visible
- replay the entrance transition for every new selection
- compensate textarea borders to avoid phantom overflow
- reuse a global slim scrollbar utility with Firefox support
…esign

spec(project): 增加 Project 功能
…luation

feat: agent observability evaluation
refactor: arch and domain redesign
@hifizz
hifizz marked this pull request as ready for review September 2, 2026 16:05
@hifizz
hifizz merged commit 48f2878 into main Sep 2, 2026
4 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant