Skip to content

feat: Windows platform adaptation - #1

Merged
op7418 merged 2 commits into
op7418:mainfrom
xuxu777xu:feat/windows-drive-switcher
Feb 7, 2026
Merged

feat: Windows platform adaptation#1
op7418 merged 2 commits into
op7418:mainfrom
xuxu777xu:feat/windows-drive-switcher

Conversation

@xuxu777xu

@xuxu777xuxuxu777xu commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

Summary

CodePilot 原本仅支持 macOS,本 PR 添加完整的 Windows 平台适配,使其可以在 Windows 上正常构建、运行和使用。

Changes

跨平台基础设施

  • 新增 src/lib/platform.ts:统一的跨平台工具模块,包含 Claude CLI 发现逻辑(Windows .cmd/.bat shell 处理、where/which 回退)、PATH 扩展(AppData/npm 等 Windows 路径)
  • 重构 src/app/api/claude-status/route.ts:移除硬编码的 Unix 路径,改用共享的 platform 工具
  • 重构 src/lib/claude-client.ts:同上,并确保 USERPROFILE 和扩展 PATH 在 SDK 子进程中可用

Electron 主进程

  • electron/main.ts
    • Windows 进程派生使用 windowsHide 防止控制台窗口闪烁
    • PATH 构建适配 Windows 分隔符(;)和目录结构(AppData/npm)
    • 窗口标题栏适配:macOS hiddenInset / Windows hidden + titleBarOverlay
    • 图标适配:Windows 使用 .ico
    • loadUserShellEnv() 跳过非 macOS 平台

构建配置

  • electron-builder.yml:新增 win + nsis 构建目标,支持自定义安装目录、桌面/开始菜单快捷方式
  • package.json:新增 electron:pack:win 脚本,原 electron:pack 改为平台无关
  • build/icon.ico:Windows 应用图标

UI 适配

  • src/components/chat/FolderPicker.tsx:新增盘符下拉切换器,解决 Windows 盘符根目录无法向上导航的问题
  • src/app/api/files/browse/route.ts:API 返回可用 Windows 盘符列表
  • src/components/skills/SkillsManager.tsx:修复 key 重复警告

Test plan

  • Windows 上 npm run electron:pack:win 构建成功
  • 安装后启动,Claude CLI 自动检测并连接
  • 标题栏样式正确(隐藏标题栏 + overlay 控制按钮)
  • FolderPicker 盘符切换正常工作
  • macOS 上 npm run electron:pack:mac 构建无回归

🤖 Generated with Claude Code

xuxu777xuand others added 2 commits February 7, 2026 13:29
When navigating to a drive root on Windows (e.g. C:\), path.dirname
returns itself, disabling the "go up" button and trapping the user on
that drive. This adds a compact dropdown next to the up button that
lists all available drives (auto-detected via fs.accessSync), allowing
quick switching between drives. macOS/Linux are unaffected (empty array,
dropdown not rendered).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add src/lib/platform.ts: cross-platform Claude CLI discovery
(candidate paths, .cmd/.bat shell handling, where/which fallback)
- Refactor claude-status route and claude-client to use shared platform utils
- Electron main: Windows process spawning (windowsHide), PATH construction
with AppData/npm dirs, titleBarOverlay, .ico icon support
- electron-builder.yml: add win/nsis build targets
- package.json: add electron:pack:win script
- FolderPicker: drive switcher dropdown for navigating between drives
- SkillsManager: fix duplicate key warning with filePath fallback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@xuxu777xuxuxu777xu changed the title feat: add Windows drive switcher in FolderPickerfeat: Windows platform adaptationFeb 7, 2026
@op7418
op7418 merged commit b819eb7 into op7418:mainFeb 7, 2026
op7418 added a commit that referenced this pull request Apr 12, 2026
…ion for Native Runtime
Two feature gaps where Native Runtime didn't match SDK Runtime, both
surfaced during post-hermes-upgrade manual testing:
── #1: Compression notification now human-readable ──
Before: chat/route.ts:402 emitted `message: 'context_compressed'` as
a machine string. useSSEStream's notification branch showed this raw
string in the status bar — users saw "context_compressed" flash by.
After: message is now `"Context compressed: N older messages summarized,
~X tokens saved"` with structured `stats: { messagesCompressed, tokensSaved }`
for future rich UI handling. Added `subtype: 'context_compressed'` for
dedicated frontend handlers.
── #3: AskUserQuestion tool for Native Runtime ──
Before: only SDK Runtime had AskUserQuestion (built into Claude Code CLI).
Native Runtime had no such tool, so the model could never ask structured
questions — the existing AskUserQuestionUI in PermissionPrompt.tsx was
unreachable dead UI code for Native Runtime users.
After:
- New builtin tool `src/lib/builtin-tools/ask-user-question.ts`
registered in index.ts, condition 'always'
- Zod schema: 1-6 questions, each with 1-6 options, optional multiSelect
- Execute receives answers from permission flow (injected by frontend)
and formats as Q/A pairs for the model
- permission-checker.ts: new ALWAYS_ASK_TOOLS set ensures AskUserQuestion
(and ExitPlanMode) always show UI even in trust mode — without this,
trust mode would auto-approve and return empty answers
- PermissionPrompt.tsx: NEVER_AUTO_APPROVE set prevents full_access mode
from auto-approving AskUserQuestion — the UI must render so the user
can answer
The data flow:
Model → AskUserQuestion({ questions }) → permission wrapper intercepts
→ SSE permission_request → frontend AskUserQuestionUI renders
→ user picks options → updatedInput({ questions, answers }) → tool
execute formats answers → model gets "Q: ... A: ..." string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KevinYoung-Kw referenced this pull request in KevinYoung-Kw/CodePilot Apr 15, 2026
**补充修复**
在 #1 斜杠命令保留已有文本的修复基础上,进一步确保选择命令后光标自动定位到输入框尾部,而不是默认的首部。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KevinYoung-Kw referenced this pull request in KevinYoung-Kw/CodePilot Apr 15, 2026
**补充修复**
在 #1 斜杠命令保留已有文本的修复基础上,进一步确保选择命令后光标自动定位到输入框尾部,而不是默认的首部。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
v0.56.x 计划 Phase 1:建立稳定性治理入口,并用当前源码重新核验 Notion/issue 列出的
7 个 issue(不采信 issue 自述根因)。
GitHub 侧(已在仓库生效,非本 commit 内容):
- 创建 milestone #1「v0.56.x Stability / Trust」。
- 创建 9 个治理 label:P0-crash-or-interrupt / P0-data-loss-risk / P1-runtime-session /
P1-context / P1-file-reference / P1-installer-update / P1-performance / needs-repro /
v0.57+ parking-lot。
- 给 #626/#628/#629/#632/#633/#634/#635 按复核结论打 milestone + 优先级 label。
本 commit 文件:
- .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml:bug 表单强制必填
版本/OS/runtime/provider-model/可复现/复现步骤/期望vs实际 + 影响面勾选;feature
表单注明 v0.56.x 冻结新功能 → v0.57+ parking-lot;config 关闭空白 issue + 冻结说明
与 Discussions 入口。
- .github/PULL_REQUEST_TEMPLATE.md:Summary / Repro+root cause / Changes / Tests /
Screenshots-logs / 自查清单(链到 CLAUDE.md 与 AGENTS.md,不复制维护)。
- .github/TRIAGE.md:对外冻结说明、label 体系、issue/PR triage 规则、自动化候选。
- v0.56.x-stability-trust.md:标 Phase 0 完成 + 新增「2026-06-19 Claude Code 源码复核」
表(7 issue 逐条 file:line 证据)。关键复核结论:
* #632 ">100%" 确认是未 clamp 的 ratio*100 显示 bug(RunCockpit.tsx:169 等),分母
contextWindow 不可靠;"跨会话串" 源码不成立。
* #629 空 assistant 已防护,残留真实 gap:is_error result 路径不清坏 sdk_session_id
(claude-client.ts:1908 先置 resultEmitted)。
* #635 截图-only,最强候选 = SDK runtime 无自生成 keepalive(claude-client.ts:1956),
慢 proxy 静默 >330s 被 idle abort(B-019)。
* #628 确认真实风险:@file origin path 在 MessageInput.tsx:161 丢失,body.mentions[]
送达但 route.ts 从不消费 → 写 .codepilot-uploads 副本,AI 改副本。
* #634 根因不成立——5 个 notify/schedule 工具均注册(builtin-tools/index.ts:250),
issue 引用的 UI 串不在当前源码(疑旧版);附带 Plan 模式 list_tasks 泄漏。
* #626 polling 排除(8h 间隔),候选 animate-pulse × backdrop-filter 重绘。
* #633 mac 无法复现;NSIS-only + 未签名 + 无 portable + CI 不验安装启动。
- issue-tracker.md:新增「v0.56.x 治理 issue」看板索引表(指向 plan 复核表,不重复分析)。
验证:docs-drift 通过;npm run test(hook)。Phase 1 验收(milestone/labels/模板/冻结
说明就绪)达成。下一步 Phase 2:按复核结论修 chat 主链路(上下文百分比语义、context-cost
不阻断发送、Codex 多模态发送、发送后清草稿)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: issue #632 报"上下文 >100% / 假百分比 / 压缩后跳变";Phase 1 源码复核确认是
真实显示 bug("跨会话串"不成立)。
Triage(当前源码): 用量百分比 = usage.ratio*100,在 RunCockpit.tsx 与
RunCockpitPopoverContent.tsx 两处直接渲染、未封顶;usage.ratio = used / contextWindow,
而 contextWindow 来自 sdkContextWindow ?? latestSdkContextWindow ?? catalogContextWindow
(useContextUsage.ts)。很多第三方 proxy 不上报 context_window → 落到静态 catalog 兜底
(一个猜测值),used 又会在压缩后跳变 → 百分比蹦到 200%/500%。根因是"拿不可信的分母
算百分比",不是上下文真的超了。
Fix:
- useContextUsage.ts: 新增 ContextUsageData.contextWindowTrusted —— 仅当 SDK/上游真实
上报窗口时为 true(catalog 兜底不算)。三个 return 分支(baseline / snapshot / no-baseline)
都按各自来源正确赋值。不可信时不把窗口喂给 buildContextUsageBreakdown,dot-matrix 退回
按已用 token 的构成比例,不编造容量。
- RunCockpit.tsx: hasFullCtx 增加 && usage.contextWindowTrusted —— 不可信时自动落到既有的
绝对已用 token 显示(触发按钮)/ showUnknownCapacityBlock 分支(浮层,已测试的"容量未知"
路径)。百分比文案 clamp ≤100%。
- RunCockpitPopoverContent.tsx: 浮层 header 百分比同样 clamp ≤100%(防可信窗口被 used 短暂
超过时仍蹦 >100%)。
语义验收: 输入框右下角不可信时只显示已用绝对值;浮层不可信时只显示已用 + 不同种类构成
比例(无百分比/remaining/unused/假总量);可信时百分比封顶 100%。
Verify: typecheck 通过;context-window-trusted.test.ts 6 条 source-pin + 既有
run-cockpit-unknown-capacity / context-dot-matrix / context-usage-walk / context-breakdown
全绿;全量单测 3366/3366。未做:真实 untrusted-window provider 会话的 CDP 视觉走查
(fix 把 untrusted 路由到既有已发布的"容量未知"分支,风险低;视觉走查列为后续)。
Guardrail: context-window-trusted.test.ts 钉死 trusted 派生只认 SDK 来源、不可信时不喂窗口、
hasFullCtx 必须 gate trusted、两处显示 clamp ≤100%,防回退到"拿 catalog 当真实分母算百分比"。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: Codex 复核 fix#1(b842628)后发现 P2 残留——文字已改成"只显示已用 token",
但输入框右下角触发按钮旁的 mini dot-bar 仍用 200K 兜底画出"用了多少/还剩多少"的容量
暗示,与"拿不到总长度就不显示容量"及 commit message 的"不编造容量"不一致。
Triage(当前源码): ContextDotMatrix.tsx 有 FALLBACK_CONTEXT_WINDOW=200_000,
minCellsPerKind=0(mini-bar)在窗口未知时用它当分母(:88);RunCockpit.tsx:200 的触发
按钮无条件渲染这个 mini-bar。所以即使 b842628 把文字降级为绝对已用,小条仍画假容量。
minCellsPerKind=0 全仓只有 RunCockpit 触发按钮一个调用方。
Fix:
- RunCockpit.tsx: mini-bar 用 {hasFullCtx && (...)} 包裹——仅在可信窗口下渲染容量小条;
不可信时触发按钮只剩绝对已用 token 文本(贴合"输入框右下角只显示已用数值")。
- ContextDotMatrix.tsx: 删除 FALLBACK_CONTEXT_WINDOW(200K)。窗口未知时两种模式都按
used+pending 分配(构成视图,非容量%),不再编造容量。
Verify: typecheck 通过;context-dot-matrix.test.ts 旧的"unknown mini-bar 用 200K 兜底
(filled<=2)"语义改为新的"used 构成(filled>=8)";context-window-trusted.test.ts 加 2 条
guardrail(mini-bar gate 在 hasFullCtx + 源码无 200K 兜底残留);全量单测 3368/3368。
Guardrail: 两条 source-pin 钉死"触发按钮 mini-bar 必须 gate 在 hasFullCtx"且"ContextDotMatrix
不得再出现 FALLBACK_CONTEXT_WINDOW/200_000",防回退到拿假容量画小条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
用户复核 fix#1 后明确显示格式:输入框右下角的上下文小标,在有可信窗口时显示
"百分比 + 已用上下文"(如 56.6% 452K),没有可信窗口时只显示已用(如 452K),
不单列"剩余"数字。
改动:RunCockpit.tsx 触发按钮 ratioText 的可信分支由 "{pct}%" 改为
"{pct}% {used}"(1 位小数,匹配用户给的 56.6% 示例);不可信/无数据分支不变。
context-window-trusted.test.ts 的 clamp pin 扩为同时断言"百分比 + 已用"格式。
验证:dev 应用热重载干净(✓ Compiled);context-window-trusted 8/8;typecheck(hook)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: 用户在运行的应用里看到 GLM-5-turbo(Claude Code/Native 会话)仍显示总上下文
200K,指出"这并不是我们知道的部分"。fix#1 本应让 catalog 静态值不可信、只显示已用。
Triage(当前源码,用户 review 驱动): agent-loop.ts:641-651(Native)在 token_usage
没有 context_window 时,从静态 catalog 填 totalUsage.context_window = getContextWindow(modelId)
(GLM-5-turbo 在 catalog 是 z.ai 核实的 202752)。而 context-usage-walk 把
token_usage.context_window 当作 SDK 实报窗口读,fix#1 的 contextWindowTrusted 据此判可信
→ catalog 猜测被"洗白"成可信 → Native GLM 显示 200K。即上游 mutator 打败了 helper 修复
(feedback_fix_all_consumers)。claude-client(Claude Code)只从 SDK modelUsage 写,不洗白;
ContextUsageIndicator 是死组件(无人 import)。
Fix: 删掉 agent-loop 的 catalog 洗白。Native 无 runtime 实报时 context_window 留空 →
useContextUsage 回落 catalog 为不可信 → 只显示已用绝对值,不再有假百分比/假总量。
仅对新 turn 生效(历史消息已存的 context_window 不改写,遵守不改用户数据;旧会话发新消息后转为已用-only)。
Verify: typecheck;context-window-trusted.test.ts 新增 pin 断言 agent-loop 不再
`.context_window = catalogWindow`;该文件 9 测 + agent-loop-error-event 全过。运行中 dev 应用
server 重编译干净(Native GLM 需发新消息验证)。
Guardrail: source-pin 防 Native 再把 catalog 洗进 SDK-authoritative 字段。
设计记录(用户批准"先记计划再实现"): v0.56.x 计划写入 context-window 来源优先级修订设计
(runtime 实报 > provider 配置 contextWindow > 压缩阈值 > catalog 不可信)+ 跨 Runtime 用户
配置源(#1,待实现) + 显示分母对齐压缩阈值(#3,待实现)。本提交是设计第一步(去洗白)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
把"为什么 GLM 显示 200K + 窗口来源该怎么改"写成评审稿放进 v0.56.x Phase 2,按
外部事实 / 本地证据(file:line) / 推断与设计三层分写,供 Codex 核实。
要点:
- Agent SDK v0.2.111 的 modelUsage.contextWindow(sdk.d.ts:945)是未文档化字段,来自
SDK 内置模型目录而非 API;第一方可靠、第三方(经 base_url 的 GLM)返回通用默认值;
无 SDK 设置可覆盖;Anthropic 建议自维护窗口表。
- 实测 GLM 会话 token_usage.context_window=200000 ≠ 本地 catalog 202752,证实来自 SDK
默认而非 catalog/Native 洗白;该会话是 Claude Code(故上一提交的 Native 修复不覆盖它)。
- 修订设计:窗口来源优先级 = 用户覆盖 > 已核实 catalog/provider 配置 > SDK(仅第一方) >
只显示已用;第三方忽略 SDK 默认值;跨 Runtime;显示分母对齐压缩阈值(#3)。
- 列出待定决策(已核实优先 vs 纯手动) + 给 Codex 的 5 个核实点。
未改任何产品代码(纯文档)。#1/#3 实现待 Codex 核实后进行。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Codex 复核设计稿后订正(实现 #1/#3 前必须):
- A:原"官方文档不记载 contextWindow/maxOutputTokens"不准 → 改为 SDK TypeScript
reference 有字段定义,是 cost-tracking 指南未解释来源/可信度。
- B/C:原"catalog 202752 比 SDK 200000 更准且 z.ai 核实"站不住 → z.ai 官方写
200K/128K,catalog 该条来源存疑;结论收敛为"SDK 200000 不可作为 provider 实报采信",
不延伸到"catalog 更准";另标记需单独核 model-context.ts:42 的真实来源。
- D + 决策日志:统一优先级(消除冲突,旧决策日志把第三方 SDK 又洗白成可信)→
用户手动覆盖 > provider/model 配置且来源已验证 > 第一方 runtime 实报 > 只显示已用;
第三方 SDK contextWindow 默认不可信、无明确来源 catalog 不当可信%显示。
- "Anthropic 官方建议自维护表"未核到原文 → 降级为工程结论。
- 澄清:用户实际看到 200K 的 GLM 会话是 Claude Code(SDK 默认 200000),非 Native 洗白
路径(681706b 的 Native 修复有效但治另一条路径)。
- E:决策收敛为一条基线 + 剩余一项请用户定(第一方 SDK 实报是否自动显示百分比)。
Codex 核为真的部分(sdk.d.ts:945 字段、代码写入 token_usage、历史 SDK 窗口被当可信、
Native 洗白已去、显示分母 vs 压缩阈值脱节)保留。纯文档,未动产品代码。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
F 段核实点 #1 还残留旧"官方文档未记载(A)",与已订正的 A 段不一致。改为:
sdk.d.ts:945 的 contextWindow/maxOutputTokens 存在,SDK TypeScript reference 已列,
只是 cost-tracking 指南未解释来源/可信度。纯文档。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
… Phase 2 ①)
Signal: 用户 GLM-5-turbo(Claude Code 经代理)显示总上下文 200K,且 Codex 核实 SDK 的
modelUsage.contextWindow 来自 SDK 内置目录、对第三方是通用默认值、无 SDK 设置可覆盖。
Triage: claude-client.ts extractTokenUsage 把 SDK modelUsage.contextWindow 无条件写入
token_usage.context_window;walk + fix#1 据此判可信 → 第三方代理(GLM)的 SDK 默认 200000
被当可信显示。Native 的 catalog 洗白已于 681706b 去掉;本提交补 SDK 路径。
Fix(Codex 统一口径"第一方 runtime 实报可信、第三方不可信"):
- ai-provider.ts 导出 isFirstPartyAnthropicEndpoint(baseUrl)(空/anthropic.com → 第一方)。
- extractTokenUsage 增 trustContextWindow,仅 true 时写 context_window;两个调用点都传
isFirstPartyAnthropicEndpoint(resolved.provider?.base_url)。第三方(自定义 base_url,如 GLM)
→ 不写 context_window → useContextUsage 回落 catalog 为不可信 → 只显示已用。
效果 + 边界: 第一方 Anthropic 继续显示百分比+已用;第三方代理新 turn 起只显示已用。
仅对新写入生效(历史消息已存的 context_window 不改写,遵守不改用户数据);现有 GLM 会话
仍显示旧值,需新会话/新 turn 验证(walk 会读历史,故旧会话需自然滚动出旧窗口或新建)。
Verify: typecheck;extract-token-usage-context-window.test.ts 增 2 pin(gate + 两调用点传
第一方判别);全量 3371/3371。
Guardrail: source-pin 钉死 context_window 写入受 trustContextWindow 门控 + 两调用点必须传
isFirstPartyAnthropicEndpoint,防回退到无条件信任第三方 SDK 窗口。
remaining(Phase 2 ①/③ 未完): provider/model 配置窗口作为最高优先可信源(用户覆盖) + 渲染层
对现有会话按第一方 gate(治旧会话) + #3 显示分母对齐压缩阈值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
计划文档状态审计修正(决策日志准、但概览层过期):
- frontmatter 状态行:📋 待接手 → 🚧 Phase 0/1 已完成、Phase 2 进行中。
- 「状态总览」表:Phase 1 待开始 → ✅ 已完成(2026-06-19);Phase 2 待开始 → 🚧 进行中。
- Phase 2 加进度 note:Composer/Context 主链路 #1#5 全部收口(含 commit + #3 真实
Codex 冒烟回复 circle);Session/Stream cluster #629/#635 + 终态原因码 + 压缩回滚
+ 诊断导出字段待续。
- Phase 2 执行清单 4 项已完成项 [ ]→[x](上下文 UI 语义 / context-cost 去阻断 /
Codex 多模态发送 / 发送后草稿清理)。
CLAUDE.md 执行计划段新增「完成即回写进度(与 Codex 对齐协作)」:任一 Phase/子项做完
必须立即回写三处且一致——执行清单勾选 / 状态总览表+frontmatter / 决策日志(commit
+验证结论);Claude 实施+回写、Codex 审查+维护;三者不一致视为状态失真须先对齐。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
打回上一条状态同步的一处失真:我把 #4/#5「发送后内容残留」标成完成(checklist [x] +
进度 note 列为 done),但同一文档决策日志(2026-06-20 条)已写明用户再次确认"内容已发出
但文本仍残留输入框"、#615 source-pin 不覆盖该症状、不能算闭环——状态表/清单与决策日志
自相矛盾,违反刚加的"三者必须一致"。
修正(与决策日志对齐):
- checklist「复现并修发送后内容残留」[x] → [ ],标注"待复核/待修复(用户 2026-06-20 再报)"。
- Phase 2 进度 note:拆分——#4/#5 仅失败保留有基础修复(#615),发送成功后文本残留待复核;
note 标题从"主链路已收口"改为"#1#3 收口、#4/#5 待复核";待续列表补回 #4/#5(重新打开)。
- #2 context-cost 非阻断保持完成(checklist [x] + note)不变。
后续修 #4/#5 时重点:PromptInput 受控/非受控清空边界、setInputValue('') 与
controller.textInput.clear() 是否同源、成功 accepted 后 remount/local draft 恢复、
badge/confirm/image 分支与普通 Enter 分支是否一致(决策日志已记排查方向)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
按"完成即回写进度"规则同步三处:
- checklist「复现并修发送后内容残留」[ ]→[x],标注已修 + CDP 验证 + 根因/修法(58c7aad)。
- Phase 2 进度 note:#1#5 全部落地;#4/#5 从"待复核"改为"已定位+修复"(含根因/CDP 结论);
待续列表移除 #4/#5、只留 Session/Stream cluster。
- 决策日志加同日条目:CDP 埋点定位 = 首条消息 accept 布局翻转 remount composer、inputValue
从 sessionStorage 草稿重读;修法 = accept 处清草稿;3401/3401 + CDP 文本/图文首条 800ms 即清。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
用户在浏览器实测不残留、仅桌面 App 残留 → Claude 协助完整重启 electron:dev(kill 整棵
进程树 + 释放 3000 + 后台重启)→ 用户在重启后真实 App 验证发送即清空 → #4/#5 闭环。
根因:58c7aad(page.tsx accept 处清首条草稿)一直是对的;用户残留是 Electron dev 没把
page.tsx 改动热更新进 renderer、窗口刷新无效,得整进程重启。这解释了全程「Claude CDP
浏览器清、用户残留」的矛盾——不是 Electron 行为差异,是构建新鲜度差异(Claude 浏览器硬刷
过有修复、用户 Electron 旧构建没有)。
回写:checklist [x](用户真实 App 验证)、进度 note #1#5 全闭环、验收去 ⚠️、决策日志加
闭环条目 + 教训(UI 修复在桌面 App 验证必须整重启 electron:dev)。Codex P1(prefill/
initialValue 回灌)仍是 58c7aad 的真实独立漏洞、值得单独补,与本次残留无关。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
纯文档同步,无代码改动。目的:让下一个进程打开文档时不从旧状态误判进度。
三处状态表此前已标 Phase 0/1 ✅、决策日志也已确认完成,唯独执行清单 checkbox
与 README 索引、issue-tracker #632 仍停在旧值——三处不一致即状态失真,本次对齐。
README.md:
- v0.56.x 索引行状态列 "📋 待 Phase 0 收束" → "🚧 Phase 0/1 ✅;Phase 2 进行中
(Composer/Context 主链路 #1#5 闭环,Session/Stream cluster #629/#635 待续)",
追上 plan frontmatter 与决策日志。
v0.56.x-stability-trust.md:
- Phase 0 执行清单 8 项 [ ]→[x],逐条带回溯(3360/3360、9c6e772、f99edbb/d00449f)。
A2 计时器项如实标注:按 keyed-remount 构造性消除 + 截图不可判别记录入 Smoke Ledger,
非逐帧视觉确认(反假数据,不谎称做了视觉确认)。
- Phase 1 执行清单 5 项 [ ]→[x],带回溯(milestone #1 / 9 labels / .github/TRIAGE.md)。
issue-tracker.md:
- #632 状态 "🔴 待修" → "🟡 假%已修,item3 分母对齐待续"。核心显示 bug(假百分比/>100%)
已由 effective-base-URL 写入 gate + 渲染期 trusted gate + clamp 修复并经真实 GLM
会话验证;item3(显示分母对齐压缩阈值)是独立待续阶段,故标部分修复而非已修复。
- 顶部"最后更新"同步到 2026-06-26 + #632 同步说明。
验证:git diff 确认仅 3 文档、16/16 行 checkbox 与状态文字,无代码/意外文件。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jul 4, 2026
- docs/research/ai-sdk-7-toolloop-parity-gaps.md: 新增「Phase 5 处置」节,全部 gap
收口——P1×3 关闭(#1/#2 补偿由 parity 8/8 复跑锁定;#3 降级论证:Phase 4 已证
approval HMAC 不需要 SDK toolApproval 停机语义,维持 in-execute 路线),
P2/P3 关闭或 backlog(#4/#5 列为替换路线前置条件,#7 归档 tech-debt #49#8 有 Phase 5 新实证)
- scripts/smoke-ai-sdk7-phase5-decision.ts: 新增决策门对照 smoke——prod runAgentLoop
与 POC runToolLoopAgentPoc 用同一 AgentLoopOptions 逐场景对照(长文本 / approval
批准 / approval 拒绝 / abort→continue),机械比较归一化事件序列 + 尾部契约 +
usage 存在性;DB 只读、数据目录隔离、输出全 scrub。探针注意:approval 批准分支
用 printf(echo 命中 permission-checker 自动放行规则不会触发 ask)
- docs/exec-plans/active/_smoke-evidence/ai-sdk7-phase5-decision-smoke.json:
OpenRouter 真实渠道 4/4 场景 contractMatch=true(input_tokens 逐场景完全相同,
tool_result 逐字相同,中断轮双侧 done 收尾、同 session 续发一次通过);
凭据形态 grep=0
- docs/research/ai-sdk-7-adoption-decision.md: 新增采用决策文档——结论 partial
(依赖升级 go / provider 能力 capability-gated go / Phase 4 外围能力 go /
@ai-sdk/mcp 与默认 loop 替换 no-go-现在),四层 rollback plan(能力开关→
wrapper→runtime switch→known-good version),每项结论标注 Phase 1-5 证据来源;
默认 Runtime 切换留人类闸门
- docs/exec-plans/tech-debt-tracker.md: 新增 #49(tool-error part 被两条 loop
一致吞掉的既有 UX 债,独立于采用决策)
- docs/exec-plans/active/ai-sdk-7-runtime-loop-adoption.md: Phase 5 状态回写 +
决策日志 + Smoke Ledger / Loop Ledger 各一行
- docs/research/README.md: 索引新增决策文档条目
验证: npm run test 3598/3598 全绿;smoke 4/4 contractMatch(1 个 fix cycle 收敛,
两处均为脚本层问题非 loop 差异);src/ 零改动(默认 Runtime/聊天路径零变化)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jul 4, 2026
用户批准 partial(2026-07-04, run issue #10): 采用 ai@7/@ai-sdk/* 依赖升级、
provider 参数能力 capability-gated、openai-chat image wrapper、timeout 原因码/
approval HMAC/trace 脱敏四件套(默认值经用户确认); @ai-sdk/mcp adapter 与
ToolLoopAgent 默认 loop 替换均不采用(留实验路径)。发版前保留官方一方 key
smoke gate。冲突仅 ai-sdk-7 计划决策日志一处,union 双方条目解决。
五个 phase 全部经 hands-off loop 完成并 Codex accepted(issues #1/#6/#7/#8/#10)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ion for Native Runtime
Two feature gaps where Native Runtime didn't match SDK Runtime, both
surfaced during post-hermes-upgrade manual testing:
── op7418#1: Compression notification now human-readable ──
Before: chat/route.ts:402 emitted `message: 'context_compressed'` as
a machine string. useSSEStream's notification branch showed this raw
string in the status bar — users saw "context_compressed" flash by.
After: message is now `"Context compressed: N older messages summarized,
~X tokens saved"` with structured `stats: { messagesCompressed, tokensSaved }`
for future rich UI handling. Added `subtype: 'context_compressed'` for
dedicated frontend handlers.
── op7418#3: AskUserQuestion tool for Native Runtime ──
Before: only SDK Runtime had AskUserQuestion (built into Claude Code CLI).
Native Runtime had no such tool, so the model could never ask structured
questions — the existing AskUserQuestionUI in PermissionPrompt.tsx was
unreachable dead UI code for Native Runtime users.
After:
- New builtin tool `src/lib/builtin-tools/ask-user-question.ts`
registered in index.ts, condition 'always'
- Zod schema: 1-6 questions, each with 1-6 options, optional multiSelect
- Execute receives answers from permission flow (injected by frontend)
and formats as Q/A pairs for the model
- permission-checker.ts: new ALWAYS_ASK_TOOLS set ensures AskUserQuestion
(and ExitPlanMode) always show UI even in trust mode — without this,
trust mode would auto-approve and return empty answers
- PermissionPrompt.tsx: NEVER_AUTO_APPROVE set prevents full_access mode
from auto-approving AskUserQuestion — the UI must render so the user
can answer
The data flow:
Model → AskUserQuestion({ questions }) → permission wrapper intercepts
→ SSE permission_request → frontend AskUserQuestionUI renders
→ user picks options → updatedInput({ questions, answers }) → tool
execute formats answers → model gets "Q: ... A: ..." string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ge generation results
GPT-Image-2.0 skill silent failure had two compounding causes both
on the 'tool result' loop:
P0 op7418#1 — function_call_output translated with sentinel toolName
translate-input.ts wrote toolName: '__from_responses_proxy__' for every
tool-result and the comment claimed 'ai-sdk doesn't use this for
routing'. That was wrong. Anthropic and OpenAI Responses both look
up the tool definition by tool-result.toolName when reconciling the
result with the request's tool surface; with a sentinel they can't
correlate and refuse to produce the continuation turn — exactly the
'tool ran, no follow-up text' the user saw.
Fix: walk the input array once first to build call_id → toolName
from function_call items, then look up the real name when translating
function_call_output. Orphan results (no matching function_call) fall
back to a named sentinel '__orphan_function_call_output__' AND emit
console.warn naming the call_id. The divergence stays loud.
P0 op7418#2 — imageGeneration / imageView silently dropped
event-mapper.ts had both item types in CHAT_ONLY_ITEM_TYPES, which
returns null on item/started + item/completed. That set is correct
for agentMessage/plan/reasoning (they have streaming delta channels
so the content arrives separately), but imageGeneration / imageView
have NO delta channel — their final item is the only surface where
the result reaches the user. Silent drop meant 'tool ran' with no
visible image.
Fix: move both types to TOOL_LIKE_ITEM_TYPES, add explicit
translateItemStarted branches with names image_generation /
image_view, and the existing TOOL_LIKE_ITEM_TYPES completion branch
already packs the full item into output — preserving result,
savedPath, revisedPrompt, path for chat-side rendering.
ThreadItemLike grew matching fields so TS doesn't downgrade access
to (item as { path?: string }).path casts.
Tests (8 new)
src/__tests__/unit/codex-proxy-translators.test.ts (+3):
- toolName resolves from matching function_call (gpt_image_2 case)
- toolName resolves correctly with interleaved out-of-order calls
- orphan function_call_output → named sentinel + console.warn
src/__tests__/unit/codex-event-mapper.test.ts (+4):
- imageGeneration item/started → tool_started(name='image_generation')
- imageGeneration item/completed → tool_completed with full
result + savedPath + revisedPrompt payload
- imageView item/started → tool_started(name='image_view') + path
- imageView item/completed → tool_completed with path preserved
src/__tests__/unit/codex-proxy-tool-contract.test.ts (+1):
- End-to-end continuation: function_call → function_call_output →
streamText(messages) — MockLanguageModelV3 must see toolName
'gpt_image_2' in its prompt, NOT '__from_responses_proxy__'.
Continuation text-delta event fires.
The mapper-side translate also removed the chatOnly array's
imageView / imageGeneration entries from the old 'returns null'
parameterised test; replaced with the new lifecycle describe block.
Closeout doc records round 7 ✅ items; remaining must-haves
unchanged (4-family smoke matrix + codex-sdk POC).
All 2416 tests pass (was 2412 + 8 new − 4 obsolete from the chatOnly
table for imageView/imageGeneration).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ce 2a
Direction approved; three sharpenings folded into the existing
Phase 2 plan structure without restructuring.
1. Widget wire-format single source (review revision op7418#1)
slice 7's WIDGET_SYSTEM_PROMPT template-literal-embeds
WIDGET_WIRE_FORMAT_SPEC. With artifactContracts ordered BEFORE
capabilityFragments in the compiler, the wire spec would land in
the final system prompt twice (once from artifactContract, once
from the capability fragment tail). The plan now declares hard
constraints — CANONICAL_SHOW_WIDGET_JSON, the "FINAL OUTPUT
FORMAT" title, and WIDGET_WIRE_FORMAT_SPEC each must appear
exactly once in the compiled system prompt — and assigns slice
2c a small refactor that strips the wire spec from
WIDGET_SYSTEM_PROMPT so artifactContract becomes the sole holder.
Compile-time sanity check (capability fragment text MUST NOT
contain artifactContract.canonicalJson) added as a defence-in-
depth FAIL path.
2. Expected Differences Ledger (review revision op7418#2)
2b's "compiler output === Runtime current prompt" stance
directly conflicted with slice 2d's plan to canonicalize Native
memory / notify / media-import paraphrases. Equivalence reading
strictly would have locked the old drift in. Plan now introduces
`src/lib/harness/expected-differences.ts` with typed entries
(runtimeId, capability, diff kind, justification,
plannedResolution, compilerSource, runtimeSource). 2b harness
reads "compiler vs runtime diff ⊆ ledger"; unregistered
differences fail. Initial ledger seeded with the four known
Phase 5c slice 7b tech-debt items, three earmarked for slice 2d
and one (image_generation MediaBlock shape) earmarked
follow_up. Slice 2d completion = manual ledger entry removal
(deliberate non-automation, preserves audit trail).
3. runtimeHints boundary (review revision op7418#3)
Plan tightens the runtimeHints type declaration so it cannot
become a fourth prompt-assembly point. Allowed: IDs (mcp server
names, tool keys, builtin tool name set), fragmentIds refs into
CompiledContext, adapter options (stopWhen / stepCount /
passthroughToolTypes). Forbidden: any prompt text string, tool
description paraphrase, capability redefinition. Three test
layers — type-level (string fields ≤ 64 chars, no newline / no
markdown), runtime-level (no template-literal-shaped values),
source-grep level (no multi-line template literals in
runtimeHints assignments) — plus a dangling-reference check
that every fragmentId in runtimeHints resolves in
CompiledContext.
Regression test list extended 9 → 12. Decision log records all
three revisions with rationale.
Plan still in 📋 status. No code; awaiting Codex re-review on the
revised draft, then slice 2a opens.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
User mode change: "internal slice order preserved, external single
delivery; stop only after Phase 2 is done; Codex review takes the
batch." This commit lands slices 2a–2e together with all post-
review hardenings (Widget wire-format single source, Expected
Differences Ledger, runtimeHints prose ban).
Internal slice walk
2a — context-compiler.ts (NEW)
Pure function `compileContext(input): CompiledContext`. No IO,
no provider calls. Resolves enabledCapabilities (null = catalog
live default), looks up exposure for the calling runtime, emits
capabilityFragments + artifactContracts + memory + workspace +
toolDescriptors + runtimeHints + budget + systemPromptText +
diagnostics. Hard contracts: artifactContract before capability
in the assembled prompt; fragmentId uniqueness; cross-runtime
fragment text identity; compile-time FAIL if a capability
fragment text contains an artifact contract canonicalJson
(wire-format dedup); compile-time FAIL if load-bearing fragments
exceed budget. runtimeHints types strictly ID/refs/adapter
options — no prose, no template literals.
2b — expected-differences.ts (NEW)
Drift ledger. Initial 4 entries from slice 7b tech-debt. Three
slice_2d entries consumed by this commit (see 2d below); the
one remaining `follow_up` is image_generation MediaBlock shape
(non-prompt, future slice).
2c — ClaudeCode SDK (claude-client.ts) source-pin only
The SDK path has always imported MCP canonicals directly
(memory-search-mcp, notification-mcp, media-import-mcp,
cli-tools-mcp, dashboard-mcp) — no paraphrase ever existed.
Slice 2c codifies this with a contract test: claude-client.ts
must not import capability prompts from builtin-tools/* and
must not declare its own _SYSTEM_PROMPT scalars.
2d — Native Runtime (builtin-tools/*) re-export MCP canonicals
`memory-search.ts` now `export const MEMORY_SEARCH_SYSTEM_PROMPT =
CANONICAL_MEMORY_SEARCH_SYSTEM_PROMPT` (imported from
memory-search-mcp.ts). Same pattern for `notification.ts`
(NOTIFICATION_SYSTEM_PROMPT = NOTIFICATION_MCP_SYSTEM_PROMPT)
and `media.ts` (MEDIA_SYSTEM_PROMPT = MEDIA_MCP_SYSTEM_PROMPT
from media-import-mcp.ts). Three ledger entries removed in
sync.
2e — Codex bridge (builtin-bridge.ts + unified-adapter.ts)
Bridge no longer holds WIDGET_PROMPT / MEDIA_PROMPT /
MEMORY_PROMPT / NOTIFY_PROMPT scalars (all four declarations
deleted). `createCodePilotBuiltinTools().systemPrompt` is
permanently `''`. `unified-adapter.ts` now calls
`compileContext({ runtimeId: 'codex_runtime', ... })` and feeds
`compiled.systemPromptText` to Codex's `instructions`. A new
helper `capabilitiesFromBridgeToolNames` maps the bridge's
mounted tool names back to capability ids so the compiler's
enabledCapabilities aligns with what the bridge actually
exposes (workspace-gated memory tools naturally drop out when
workspacePath is empty).
Slice 2c Widget wire-format single source (review revision op7418#1)
WIDGET_SYSTEM_PROMPT in widget-guidelines.ts no longer
template-literal-embeds `${WIDGET_WIRE_FORMAT_SPEC}`. The
artifactContract is now the sole holder of the wire-format spec
+ canonical JSON. Compiler's `detectWireFormatDuplication` sanity
check throws at compile time if any capability fragment text
contains the artifact contract canonicalJson — that's the forcing
function preventing the spec from being re-injected.
Three regression pins enforce single occurrence in the compiled
prompt: CANONICAL_SHOW_WIDGET_JSON × 1, "FINAL OUTPUT FORMAT —
non-negotiable" × 1, WIDGET_WIRE_FORMAT_SPEC × 1.
runtimeHints boundary (review revision op7418#3)
ClaudeCodeHints / NativeHints / CodexProxyHints types now carry
only IDs (mcp server names, tool keys, builtin tool name set) +
adapter options (stopWhen, stepCount, passthroughToolTypes).
Tests pin: type-level (no string field > 64 chars, no newline,
no Markdown markers), runtime-level (scan all string values for
prose), source-grep (CodexProxyHints type definition can't
contain `promptOverride` / `promptExtra` / `widgetPrompt` / etc).
Tests
New harness-context-compiler.test.ts (23 pins): catalog hygiene,
Widget wire-format single source (op7418#10), ordering, budget
enforcement, cross-runtime fragment identity (op7418#9), tool
descriptors, runtimeHints boundary (op7418#11), Expected Differences
Ledger consistency (op7418#12), JSON parseability of every artifact
contract.
New harness-context-compiler-equivalence.test.ts (9 pins):
compiler source reachability, runtime drift honesty,
ledger/slice ownership correctness, "post-slice-2d: Native
ledger holds only the follow_up MediaBlock entry".
Updated harness-capability-contract.test.ts: drift pins now
check (a) bridge holds no local _PROMPT scalars, (b) Native
builtin-tools re-export MCP canonicals, (c) unified-adapter
imports compileContext + consumes systemPromptText, (d)
claude-client.ts doesn't import from builtin-tools/* and
doesn't declare own _SYSTEM_PROMPT.
Updated codex-widget-format-contract.test.ts: the "WIDGET_SYSTEM_PROMPT
embeds WIDGET_WIRE_FORMAT_SPEC" and "appears inside
WIDGET_SYSTEM_PROMPT" pins are flipped — slice 2c REMOVED the
embed; the new pins verify the compiler-side import line.
Updated codex-builtin-bridge.test.ts: tests previously asserting
`bridge.systemPrompt` contained capability tags now assert it
equals `''` (bridge is no longer the prompt-assembly point).
Verification
CODEX_DISABLED=1 npx tsx --test \
src/__tests__/unit/harness-context-compiler.test.ts \
src/__tests__/unit/harness-context-compiler-equivalence.test.ts \
src/__tests__/unit/harness-capability-contract.test.ts \
src/__tests__/unit/codex-widget-format-contract.test.ts \
src/__tests__/unit/codex-builtin-bridge.test.ts
→ 74/74 pass
npm run test → 2576/2576 pass
Completion criteria check (per user spec)
[x] npm run test all green (2576/2576)
[x] Context Compiler unit tests all green
[x] equivalence / expected-diff harness all green
[x] harness-capability-contract / codex-widget-format /
codex-builtin-bridge tests all green
[x] no new runtime-local prompt duplicates (Native re-exports
canonical; ClaudeCode imports canonical; bridge holds none)
[x] Codex bridge no longer holds WIDGET_PROMPT / MEDIA_PROMPT /
MEMORY_PROMPT / NOTIFY_PROMPT scalars (all four removed,
drift test pins their absence)
[x] all three Runtimes adapt compiler output, none redefine
capability prompts
Docs
- phase-5d-phase-2-context-compiler.md: slice statuses 2a–2e all
✅ 2026-05-17; note the one-shot delivery mode change.
- phase-5d-harness-capability-contract.md: Phase 2 row ✅, awaiting
Codex review.
- handover/harness-capability-contract.md: new "Context Compiler"
section detailing inputs/outputs/constraints, three-runtime
consumption pattern, Expected Differences Ledger contract.
- refactor-closeout.md: new decision-log entry recording the
Phase 2 delivery shape + completion criteria check.
Phase 5d Phase 2 ✅ pending Codex review. Phase 3 (Runtime
Capability Adapter) / Phase 4 (Artifact Contract) / Phase 5
(new-Runtime Playbook) intentionally NOT opened — stopping per
user instruction.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
… to breakdown
## 用户视角
升级前:popover 的"文件与附件 / 本次待加入"两行永远 0 —— 数据通道没接通。即使 composer 里挂了 4 个 mention 和 2 个目录引用,popover breakdown 显示 0。
升级后:MessageInput → ChatView/page → RunCockpit → useContextUsage → buildContextUsageBreakdown 全链路联通。composer 里的 attachment / mention / directory 实时累加到对应类别。trigger 上的迷你点阵 + popover 主条 + 列表行三处同步更新。
发送消息后 pending 归 0;下一轮 history 里的真实 token_usage 接管 used 部分;conversation 类自动吸收。
## 不做什么
- 不改 hook 其他字段(used / ratio / state / source 等不动)
- 不改 trigger 主结构(百分比文字仍在;只有点阵 cells 在分配时反映 pending)
- 不改 composer text 估算(composerTextTokens 仍 0;那是 Phase 3+ 的事)
## 怎么验收
- npm run test → 2921/2921 pass
- composer 里加附件 / @mention / "+" 目录 → trigger 上 pending 部分立刻有虚线 cells
- 发送消息 → pending 归零;下轮 used cells 更新
## 改动(6 文件)
### src/lib/message-input-logic.ts
新增 `PendingContextSubTotals` interface + `computePendingContextSubTotals()` 函数。逻辑 mirror `computePendingContextTokens`(同样的 null 过滤、同样的迭代顺序),但返回 { attachment, mention, directory } 三键。两个函数加起来 = 等于 computePendingContextTokens 总数。
### src/hooks/useContextUsage.ts
options 加可选 `pending?: { attachmentTokens?, mentionTokens?, directoryTokens?, composerTextTokens? }`。三条返回路径(snapshot / walk / noData)都把 options?.pending 转发给 buildContextUsageBreakdown。useMemo deps 数组加 options?.pending。
### src/components/chat/RunCockpit.tsx
RunCockpitProps 加可选 `pendingContextSubTotals?: { attachment, mention, directory }`。组件内部把它转换成 hook options.pending 形态(attachment → attachmentTokens 等)。可选 prop 默认 undefined → 不破坏现有 callsites。
### src/components/chat/MessageInput.tsx
- import 加 computePendingContextSubTotals + PendingContextSubTotals type
- props 加可选 `onPendingContextSubTotalsChange?` callback(跟现有 onPendingContextTokensChange 并列)
- 新增 useMemo 算 pendingContextSubTotals + useEffect emit callback
- 与现有 pendingContextTokens 走同一份 source 数据,逻辑同步无 divergence
### src/components/chat/ChatView.tsx
- 加 state `pendingContextSubTotals` (PendingContextSubTotals | undefined)
- MessageInput 上 wire `onPendingContextSubTotalsChange={setPendingContextSubTotals}`
- RunCockpit 上传 `pendingContextSubTotals={pendingContextSubTotals}`
### src/app/chat/page.tsx
- 跟 ChatView 完全镜像:state + MessageInput callback + RunCockpit prop
- 两个入口独立持有 state(按 StreamSession guardrail 不变量 op7418#1)
## Scope discipline
- 不新增测试(Codex 负责测试覆盖;用户分工已明确)
- 不动 buildContextUsageBreakdown / computePendingContextTokens 既有签名 → 旧调用 zero-risk
- 不改 chat-static-graph 排除清单 → MessageInput / RunCockpit 改动属于增量 prop,没新依赖链
- composerTextTokens 仍未 wire(composer 纯文本估算属于未来扩展,pending_next_turn 行暂时仍 0)
## StreamSession guardrail 合规
- 双入口(page.tsx 首消息 + ChatView 后续)独立 state — 不变量 op7418#1 ✅
- onSend / onCommand 签名不变 — rewind point 不变量 op7418#2 ✅
- 不动 capability cache — 不变量 op7418#3 ✅
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…18#31)
Codex review second round caught two real P1 inconsistencies introduced by
the Dashboard/CLI split slice plus non-blocking contract drift.
P1.1 — Dashboard injection gate ≠ route auth gate.
runtime.ts injected the dashboard read/write MCPs whenever prompt + working
directory + dashboard keyword matched, but the route's `authorize` requires
`sameRealPath(workspacePath, assistant_workspace_path)`. Mismatch → the model
sees the tool and Codex 403s at call time. Fix: dashboard injection mirrors
memory's gate exactly (same sameRealPath check, same `assistantWorkspacePath`
passed as `workspacePath`) so "inject" and "route-authorize" never disagree.
CLI tools don't need this (no workspace scope).
P1.2 — Matrix promoted only for codex_account; runtime injects for ALL
codex_runtime providers.
The runtime didn't gate injection by provider, so under a CodePilot proxy
provider the dashboard/cli MCPs WERE injected (callable), but the matrix
returned `perception_only` for non-codex_account — the opposite drift from
P1.1 ("model says yes, Settings says no"). Fix per Codex's preferred option:
move the promotion into `capabilityMatrixForRuntime` so it applies to ALL
codex_runtime providers; `capabilityMatrixForRuntimeProvider` now only adds
codex_account-specific overrides (native notes + image/media demotion).
`buildCapabilityMatrix` delegates to `capabilityMatrixForRuntime` so every
matrix entry point stays aligned.
Non-blocking op7418#1 — contract text drift.
capability-contract.ts dashboard/cli `deferredReason` + `codex_proxy.notes`
rewritten — explicit that the LEGACY provider-proxy bridge is unsupported
(true), and that the codex_runtime path now ships via the mutation-level MCP
split + matrix-layer promotion. No schema changes (`kind: 'unsupported'`
stays accurate for the legacy bridge surface); the existing matrix invariant
test gets a `MATRIX_LAYER_PROMOTIONS` exception list documenting why the two
promoted cells are allowed to be executable despite `kind: 'unsupported'`.
Schema cleanup (introduce a new `mcp_server_split` kind, drop the exception
list) tracked as tech-debt op7418#33.
Non-blocking op7418#2 — elicitation policy pins.
codex-mcp-events.test.ts now pins all 4 new server names:
codepilot_{dashboard,cli_tools}_read → auto_accept,
codepilot_{dashboard,cli_tools}_write → user_approval.
Also added a regression guard: `codex_runtime + non-codex_account provider`
must STILL show dashboard/cli_tools executable with mixed trust + the right
noteKey. Updated the two pre-existing tests that asserted the OLD behaviour
(dashboard/cli perception_only on codex_runtime) — they now assert the
promoted state. Also synced the static `CAPABILITY_EXECUTABLE_RUNTIMES` map.
Per Codex review's explicit ask: the "待真账号 smoke" wording stays in the
op7418#31 capability table — this commit fixes the inconsistencies, but the
real-account end-to-end smoke for natural-conversation triggering + write
approval card + Deny blocking is still owed by the user.
Full unit suite 3045/3045. Live route: bad workspace still 403 (auth gate
intact); tools/list subsets unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Codex review 认可方向,按 5 条反馈修订(纯文档,无代码):
- Phase A 增"开工前核验"(Opus 4.8 官方 model id / context window / thinking·effort / 1M beta,不臆测)
- Phase A 实现范围增"泛化 Opus 4.7 专属逻辑"(isOpus47Model / OPUS_4_7_PATTERN / applyContext1mBeta /
effort 门控 / claude-client sanitizer,配回归测试)—— catalog 显示 ≠ 请求正确
- OpenRouter Opus 4.8 改 deferred(不臆测 slug),首轮只接 Anthropic direct
- opus 别名 / 默认先不动(仍 4.7),只新增显式 claude-opus-4-8,切换待 smoke 后用户拍板
- Phase D 拆 D0/D:D0 把 apply-discovery-diff 全量 flake + no-verify 事件记入 tech-debt op7418#30(本提交即 D0);
D 建议先于 A/B/C,代码 phase 不再靠 --no-verify
- Open Questions op7418#1/op7418#2 据上述决议收敛
本提交纯文档;pre-commit 同样因 apply-discovery-diff 全量 flake 用 --no-verify,已确认 docs-drift 绿。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
v0.56.x 计划 Phase 1:建立稳定性治理入口,并用当前源码重新核验 Notion/issue 列出的
7 个 issue(不采信 issue 自述根因)。
GitHub 侧(已在仓库生效,非本 commit 内容):
- 创建 milestone op7418#1「v0.56.x Stability / Trust」。
- 创建 9 个治理 label:P0-crash-or-interrupt / P0-data-loss-risk / P1-runtime-session /
P1-context / P1-file-reference / P1-installer-update / P1-performance / needs-repro /
v0.57+ parking-lot。
- 给 op7418#626/op7418#628/op7418#629/op7418#632/op7418#633/op7418#634/op7418#635 按复核结论打 milestone + 优先级 label。
本 commit 文件:
- .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml:bug 表单强制必填
版本/OS/runtime/provider-model/可复现/复现步骤/期望vs实际 + 影响面勾选;feature
表单注明 v0.56.x 冻结新功能 → v0.57+ parking-lot;config 关闭空白 issue + 冻结说明
与 Discussions 入口。
- .github/PULL_REQUEST_TEMPLATE.md:Summary / Repro+root cause / Changes / Tests /
Screenshots-logs / 自查清单(链到 CLAUDE.md 与 AGENTS.md,不复制维护)。
- .github/TRIAGE.md:对外冻结说明、label 体系、issue/PR triage 规则、自动化候选。
- v0.56.x-stability-trust.md:标 Phase 0 完成 + 新增「2026-06-19 Claude Code 源码复核」
表(7 issue 逐条 file:line 证据)。关键复核结论:
* op7418#632 ">100%" 确认是未 clamp 的 ratio*100 显示 bug(RunCockpit.tsx:169 等),分母
contextWindow 不可靠;"跨会话串" 源码不成立。
* op7418#629 空 assistant 已防护,残留真实 gap:is_error result 路径不清坏 sdk_session_id
(claude-client.ts:1908 先置 resultEmitted)。
* op7418#635 截图-only,最强候选 = SDK runtime 无自生成 keepalive(claude-client.ts:1956),
慢 proxy 静默 >330s 被 idle abort(B-019)。
* op7418#628 确认真实风险:@file origin path 在 MessageInput.tsx:161 丢失,body.mentions[]
送达但 route.ts 从不消费 → 写 .codepilot-uploads 副本,AI 改副本。
* op7418#634 根因不成立——5 个 notify/schedule 工具均注册(builtin-tools/index.ts:250),
issue 引用的 UI 串不在当前源码(疑旧版);附带 Plan 模式 list_tasks 泄漏。
* op7418#626 polling 排除(8h 间隔),候选 animate-pulse × backdrop-filter 重绘。
* op7418#633 mac 无法复现;NSIS-only + 未签名 + 无 portable + CI 不验安装启动。
- issue-tracker.md:新增「v0.56.x 治理 issue」看板索引表(指向 plan 复核表,不重复分析)。
验证:docs-drift 通过;npm run test(hook)。Phase 1 验收(milestone/labels/模板/冻结
说明就绪)达成。下一步 Phase 2:按复核结论修 chat 主链路(上下文百分比语义、context-cost
不阻断发送、Codex 多模态发送、发送后清草稿)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…e 2 op7418#1)
Signal: issue op7418#632 报"上下文 >100% / 假百分比 / 压缩后跳变";Phase 1 源码复核确认是
真实显示 bug("跨会话串"不成立)。
Triage(当前源码): 用量百分比 = usage.ratio*100,在 RunCockpit.tsx 与
RunCockpitPopoverContent.tsx 两处直接渲染、未封顶;usage.ratio = used / contextWindow,
而 contextWindow 来自 sdkContextWindow ?? latestSdkContextWindow ?? catalogContextWindow
(useContextUsage.ts)。很多第三方 proxy 不上报 context_window → 落到静态 catalog 兜底
(一个猜测值),used 又会在压缩后跳变 → 百分比蹦到 200%/500%。根因是"拿不可信的分母
算百分比",不是上下文真的超了。
Fix:
- useContextUsage.ts: 新增 ContextUsageData.contextWindowTrusted —— 仅当 SDK/上游真实
上报窗口时为 true(catalog 兜底不算)。三个 return 分支(baseline / snapshot / no-baseline)
都按各自来源正确赋值。不可信时不把窗口喂给 buildContextUsageBreakdown,dot-matrix 退回
按已用 token 的构成比例,不编造容量。
- RunCockpit.tsx: hasFullCtx 增加 && usage.contextWindowTrusted —— 不可信时自动落到既有的
绝对已用 token 显示(触发按钮)/ showUnknownCapacityBlock 分支(浮层,已测试的"容量未知"
路径)。百分比文案 clamp ≤100%。
- RunCockpitPopoverContent.tsx: 浮层 header 百分比同样 clamp ≤100%(防可信窗口被 used 短暂
超过时仍蹦 >100%)。
语义验收: 输入框右下角不可信时只显示已用绝对值;浮层不可信时只显示已用 + 不同种类构成
比例(无百分比/remaining/unused/假总量);可信时百分比封顶 100%。
Verify: typecheck 通过;context-window-trusted.test.ts 6 条 source-pin + 既有
run-cockpit-unknown-capacity / context-dot-matrix / context-usage-walk / context-breakdown
全绿;全量单测 3366/3366。未做:真实 untrusted-window provider 会话的 CDP 视觉走查
(fix 把 untrusted 路由到既有已发布的"容量未知"分支,风险低;视觉走查列为后续)。
Guardrail: context-window-trusted.test.ts 钉死 trusted 派生只认 SDK 来源、不可信时不喂窗口、
hasFullCtx 必须 gate trusted、两处显示 clamp ≤100%,防回退到"拿 catalog 当真实分母算百分比"。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Signal: Codex 复核 fixop7418#1(9ea29a4)后发现 P2 残留——文字已改成"只显示已用 token",
但输入框右下角触发按钮旁的 mini dot-bar 仍用 200K 兜底画出"用了多少/还剩多少"的容量
暗示,与"拿不到总长度就不显示容量"及 commit message 的"不编造容量"不一致。
Triage(当前源码): ContextDotMatrix.tsx 有 FALLBACK_CONTEXT_WINDOW=200_000,
minCellsPerKind=0(mini-bar)在窗口未知时用它当分母(:88);RunCockpit.tsx:200 的触发
按钮无条件渲染这个 mini-bar。所以即使 9ea29a4 把文字降级为绝对已用,小条仍画假容量。
minCellsPerKind=0 全仓只有 RunCockpit 触发按钮一个调用方。
Fix:
- RunCockpit.tsx: mini-bar 用 {hasFullCtx && (...)} 包裹——仅在可信窗口下渲染容量小条;
不可信时触发按钮只剩绝对已用 token 文本(贴合"输入框右下角只显示已用数值")。
- ContextDotMatrix.tsx: 删除 FALLBACK_CONTEXT_WINDOW(200K)。窗口未知时两种模式都按
used+pending 分配(构成视图,非容量%),不再编造容量。
Verify: typecheck 通过;context-dot-matrix.test.ts 旧的"unknown mini-bar 用 200K 兜底
(filled<=2)"语义改为新的"used 构成(filled>=8)";context-window-trusted.test.ts 加 2 条
guardrail(mini-bar gate 在 hasFullCtx + 源码无 200K 兜底残留);全量单测 3368/3368。
Guardrail: 两条 source-pin 钉死"触发按钮 mini-bar 必须 gate 在 hasFullCtx"且"ContextDotMatrix
不得再出现 FALLBACK_CONTEXT_WINDOW/200_000",防回退到拿假容量画小条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户复核 fixop7418#1 后明确显示格式:输入框右下角的上下文小标,在有可信窗口时显示
"百分比 + 已用上下文"(如 56.6% 452K),没有可信窗口时只显示已用(如 452K),
不单列"剩余"数字。
改动:RunCockpit.tsx 触发按钮 ratioText 的可信分支由 "{pct}%" 改为
"{pct}% {used}"(1 位小数,匹配用户给的 56.6% 示例);不可信/无数据分支不变。
context-window-trusted.test.ts 的 clamp pin 扩为同时断言"百分比 + 已用"格式。
验证:dev 应用热重载干净(✓ Compiled);context-window-trusted 8/8;typecheck(hook)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…llow-up)
Signal: 用户在运行的应用里看到 GLM-5-turbo(Claude Code/Native 会话)仍显示总上下文
200K,指出"这并不是我们知道的部分"。fixop7418#1 本应让 catalog 静态值不可信、只显示已用。
Triage(当前源码,用户 review 驱动): agent-loop.ts:641-651(Native)在 token_usage
没有 context_window 时,从静态 catalog 填 totalUsage.context_window = getContextWindow(modelId)
(GLM-5-turbo 在 catalog 是 z.ai 核实的 202752)。而 context-usage-walk 把
token_usage.context_window 当作 SDK 实报窗口读,fixop7418#1 的 contextWindowTrusted 据此判可信
→ catalog 猜测被"洗白"成可信 → Native GLM 显示 200K。即上游 mutator 打败了 helper 修复
(feedback_fix_all_consumers)。claude-client(Claude Code)只从 SDK modelUsage 写,不洗白;
ContextUsageIndicator 是死组件(无人 import)。
Fix: 删掉 agent-loop 的 catalog 洗白。Native 无 runtime 实报时 context_window 留空 →
useContextUsage 回落 catalog 为不可信 → 只显示已用绝对值,不再有假百分比/假总量。
仅对新 turn 生效(历史消息已存的 context_window 不改写,遵守不改用户数据;旧会话发新消息后转为已用-only)。
Verify: typecheck;context-window-trusted.test.ts 新增 pin 断言 agent-loop 不再
`.context_window = catalogWindow`;该文件 9 测 + agent-loop-error-event 全过。运行中 dev 应用
server 重编译干净(Native GLM 需发新消息验证)。
Guardrail: source-pin 防 Native 再把 catalog 洗进 SDK-authoritative 字段。
设计记录(用户批准"先记计划再实现"): v0.56.x 计划写入 context-window 来源优先级修订设计
(runtime 实报 > provider 配置 contextWindow > 压缩阈值 > catalog 不可信)+ 跨 Runtime 用户
配置源(op7418#1,待实现) + 显示分母对齐压缩阈值(op7418#3,待实现)。本提交是设计第一步(去洗白)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
把"为什么 GLM 显示 200K + 窗口来源该怎么改"写成评审稿放进 v0.56.x Phase 2,按
外部事实 / 本地证据(file:line) / 推断与设计三层分写,供 Codex 核实。
要点:
- Agent SDK v0.2.111 的 modelUsage.contextWindow(sdk.d.ts:945)是未文档化字段,来自
SDK 内置模型目录而非 API;第一方可靠、第三方(经 base_url 的 GLM)返回通用默认值;
无 SDK 设置可覆盖;Anthropic 建议自维护窗口表。
- 实测 GLM 会话 token_usage.context_window=200000 ≠ 本地 catalog 202752,证实来自 SDK
默认而非 catalog/Native 洗白;该会话是 Claude Code(故上一提交的 Native 修复不覆盖它)。
- 修订设计:窗口来源优先级 = 用户覆盖 > 已核实 catalog/provider 配置 > SDK(仅第一方) >
只显示已用;第三方忽略 SDK 默认值;跨 Runtime;显示分母对齐压缩阈值(op7418#3)。
- 列出待定决策(已核实优先 vs 纯手动) + 给 Codex 的 5 个核实点。
未改任何产品代码(纯文档)。op7418#1/op7418#3 实现待 Codex 核实后进行。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Codex 复核设计稿后订正(实现 op7418#1/op7418#3 前必须):
- A:原"官方文档不记载 contextWindow/maxOutputTokens"不准 → 改为 SDK TypeScript
reference 有字段定义,是 cost-tracking 指南未解释来源/可信度。
- B/C:原"catalog 202752 比 SDK 200000 更准且 z.ai 核实"站不住 → z.ai 官方写
200K/128K,catalog 该条来源存疑;结论收敛为"SDK 200000 不可作为 provider 实报采信",
不延伸到"catalog 更准";另标记需单独核 model-context.ts:42 的真实来源。
- D + 决策日志:统一优先级(消除冲突,旧决策日志把第三方 SDK 又洗白成可信)→
用户手动覆盖 > provider/model 配置且来源已验证 > 第一方 runtime 实报 > 只显示已用;
第三方 SDK contextWindow 默认不可信、无明确来源 catalog 不当可信%显示。
- "Anthropic 官方建议自维护表"未核到原文 → 降级为工程结论。
- 澄清:用户实际看到 200K 的 GLM 会话是 Claude Code(SDK 默认 200000),非 Native 洗白
路径(f79fd54 的 Native 修复有效但治另一条路径)。
- E:决策收敛为一条基线 + 剩余一项请用户定(第一方 SDK 实报是否自动显示百分比)。
Codex 核为真的部分(sdk.d.ts:945 字段、代码写入 token_usage、历史 SDK 窗口被当可信、
Native 洗白已去、显示分母 vs 压缩阈值脱节)保留。纯文档,未动产品代码。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
F 段核实点 op7418#1 还残留旧"官方文档未记载(A)",与已订正的 A 段不一致。改为:
sdk.d.ts:945 的 contextWindow/maxOutputTokens 存在,SDK TypeScript reference 已列,
只是 cost-tracking 指南未解释来源/可信度。纯文档。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…#632 / Phase 2 ①)
Signal: 用户 GLM-5-turbo(Claude Code 经代理)显示总上下文 200K,且 Codex 核实 SDK 的
modelUsage.contextWindow 来自 SDK 内置目录、对第三方是通用默认值、无 SDK 设置可覆盖。
Triage: claude-client.ts extractTokenUsage 把 SDK modelUsage.contextWindow 无条件写入
token_usage.context_window;walk + fixop7418#1 据此判可信 → 第三方代理(GLM)的 SDK 默认 200000
被当可信显示。Native 的 catalog 洗白已于 f79fd54 去掉;本提交补 SDK 路径。
Fix(Codex 统一口径"第一方 runtime 实报可信、第三方不可信"):
- ai-provider.ts 导出 isFirstPartyAnthropicEndpoint(baseUrl)(空/anthropic.com → 第一方)。
- extractTokenUsage 增 trustContextWindow,仅 true 时写 context_window;两个调用点都传
isFirstPartyAnthropicEndpoint(resolved.provider?.base_url)。第三方(自定义 base_url,如 GLM)
→ 不写 context_window → useContextUsage 回落 catalog 为不可信 → 只显示已用。
效果 + 边界: 第一方 Anthropic 继续显示百分比+已用;第三方代理新 turn 起只显示已用。
仅对新写入生效(历史消息已存的 context_window 不改写,遵守不改用户数据);现有 GLM 会话
仍显示旧值,需新会话/新 turn 验证(walk 会读历史,故旧会话需自然滚动出旧窗口或新建)。
Verify: typecheck;extract-token-usage-context-window.test.ts 增 2 pin(gate + 两调用点传
第一方判别);全量 3371/3371。
Guardrail: source-pin 钉死 context_window 写入受 trustContextWindow 门控 + 两调用点必须传
isFirstPartyAnthropicEndpoint,防回退到无条件信任第三方 SDK 窗口。
remaining(Phase 2 ①/③ 未完): provider/model 配置窗口作为最高优先可信源(用户覆盖) + 渲染层
对现有会话按第一方 gate(治旧会话) + op7418#3 显示分母对齐压缩阈值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
计划文档状态审计修正(决策日志准、但概览层过期):
- frontmatter 状态行:📋 待接手 → 🚧 Phase 0/1 已完成、Phase 2 进行中。
- 「状态总览」表:Phase 1 待开始 → ✅ 已完成(2026-06-19);Phase 2 待开始 → 🚧 进行中。
- Phase 2 加进度 note:Composer/Context 主链路 op7418#1op7418#5 全部收口(含 commit + op7418#3 真实
Codex 冒烟回复 circle);Session/Stream cluster op7418#629/op7418#635 + 终态原因码 + 压缩回滚
+ 诊断导出字段待续。
- Phase 2 执行清单 4 项已完成项 [ ]→[x](上下文 UI 语义 / context-cost 去阻断 /
Codex 多模态发送 / 发送后草稿清理)。
CLAUDE.md 执行计划段新增「完成即回写进度(与 Codex 对齐协作)」:任一 Phase/子项做完
必须立即回写三处且一致——执行清单勾选 / 状态总览表+frontmatter / 决策日志(commit
+验证结论);Claude 实施+回写、Codex 审查+维护;三者不一致视为状态失真须先对齐。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
打回上一条状态同步的一处失真:我把 op7418#4/op7418#5「发送后内容残留」标成完成(checklist [x] +
进度 note 列为 done),但同一文档决策日志(2026-06-20 条)已写明用户再次确认"内容已发出
但文本仍残留输入框"、op7418#615 source-pin 不覆盖该症状、不能算闭环——状态表/清单与决策日志
自相矛盾,违反刚加的"三者必须一致"。
修正(与决策日志对齐):
- checklist「复现并修发送后内容残留」[x] → [ ],标注"待复核/待修复(用户 2026-06-20 再报)"。
- Phase 2 进度 note:拆分——op7418#4/op7418#5 仅失败保留有基础修复(op7418#615),发送成功后文本残留待复核;
note 标题从"主链路已收口"改为"op7418#1op7418#3 收口、op7418#4/op7418#5 待复核";待续列表补回 op7418#4/op7418#5(重新打开)。
- op7418#2 context-cost 非阻断保持完成(checklist [x] + note)不变。
后续修 op7418#4/op7418#5 时重点:PromptInput 受控/非受控清空边界、setInputValue('') 与
controller.textInput.clear() 是否同源、成功 accepted 后 remount/local draft 恢复、
badge/confirm/image 分支与普通 Enter 分支是否一致(决策日志已记排查方向)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
按"完成即回写进度"规则同步三处:
- checklist「复现并修发送后内容残留」[ ]→[x],标注已修 + CDP 验证 + 根因/修法(de123df)。
- Phase 2 进度 note:op7418#1op7418#5 全部落地;op7418#4/op7418#5 从"待复核"改为"已定位+修复"(含根因/CDP 结论);
待续列表移除 op7418#4/op7418#5、只留 Session/Stream cluster。
- 决策日志加同日条目:CDP 埋点定位 = 首条消息 accept 布局翻转 remount composer、inputValue
从 sessionStorage 草稿重读;修法 = accept 处清草稿;3401/3401 + CDP 文本/图文首条 800ms 即清。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户在浏览器实测不残留、仅桌面 App 残留 → Claude 协助完整重启 electron:dev(kill 整棵
进程树 + 释放 3000 + 后台重启)→ 用户在重启后真实 App 验证发送即清空 → op7418#4/op7418#5 闭环。
根因:de123df(page.tsx accept 处清首条草稿)一直是对的;用户残留是 Electron dev 没把
page.tsx 改动热更新进 renderer、窗口刷新无效,得整进程重启。这解释了全程「Claude CDP
浏览器清、用户残留」的矛盾——不是 Electron 行为差异,是构建新鲜度差异(Claude 浏览器硬刷
过有修复、用户 Electron 旧构建没有)。
回写:checklist [x](用户真实 App 验证)、进度 note op7418#1op7418#5 全闭环、验收去 ⚠️、决策日志加
闭环条目 + 教训(UI 修复在桌面 App 验证必须整重启 electron:dev)。Codex P1(prefill/
initialValue 回灌)仍是 de123df 的真实独立漏洞、值得单独补,与本次残留无关。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
纯文档同步,无代码改动。目的:让下一个进程打开文档时不从旧状态误判进度。
三处状态表此前已标 Phase 0/1 ✅、决策日志也已确认完成,唯独执行清单 checkbox
与 README 索引、issue-tracker op7418#632 仍停在旧值——三处不一致即状态失真,本次对齐。
README.md:
- v0.56.x 索引行状态列 "📋 待 Phase 0 收束" → "🚧 Phase 0/1 ✅;Phase 2 进行中
(Composer/Context 主链路 op7418#1op7418#5 闭环,Session/Stream cluster op7418#629/op7418#635 待续)",
追上 plan frontmatter 与决策日志。
v0.56.x-stability-trust.md:
- Phase 0 执行清单 8 项 [ ]→[x],逐条带回溯(3360/3360、dd4ead4、b853188/2de9c2b)。
A2 计时器项如实标注:按 keyed-remount 构造性消除 + 截图不可判别记录入 Smoke Ledger,
非逐帧视觉确认(反假数据,不谎称做了视觉确认)。
- Phase 1 执行清单 5 项 [ ]→[x],带回溯(milestone op7418#1 / 9 labels / .github/TRIAGE.md)。
issue-tracker.md:
- op7418#632 状态 "🔴 待修" → "🟡 假%已修,item3 分母对齐待续"。核心显示 bug(假百分比/>100%)
已由 effective-base-URL 写入 gate + 渲染期 trusted gate + clamp 修复并经真实 GLM
会话验证;item3(显示分母对齐压缩阈值)是独立待续阶段,故标部分修复而非已修复。
- 顶部"最后更新"同步到 2026-06-26 + op7418#632 同步说明。
验证:git diff 确认仅 3 文档、16/16 行 checkbox 与状态文字,无代码/意外文件。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
- docs/research/ai-sdk-7-toolloop-parity-gaps.md: 新增「Phase 5 处置」节,全部 gap
收口——P1×3 关闭(op7418#1/op7418#2 补偿由 parity 8/8 复跑锁定;op7418#3 降级论证:Phase 4 已证
approval HMAC 不需要 SDK toolApproval 停机语义,维持 in-execute 路线),
P2/P3 关闭或 backlog(op7418#4/op7418#5 列为替换路线前置条件,op7418#7 归档 tech-debt op7418#49op7418#8 有 Phase 5 新实证)
- scripts/smoke-ai-sdk7-phase5-decision.ts: 新增决策门对照 smoke——prod runAgentLoop
与 POC runToolLoopAgentPoc 用同一 AgentLoopOptions 逐场景对照(长文本 / approval
批准 / approval 拒绝 / abort→continue),机械比较归一化事件序列 + 尾部契约 +
usage 存在性;DB 只读、数据目录隔离、输出全 scrub。探针注意:approval 批准分支
用 printf(echo 命中 permission-checker 自动放行规则不会触发 ask)
- docs/exec-plans/active/_smoke-evidence/ai-sdk7-phase5-decision-smoke.json:
OpenRouter 真实渠道 4/4 场景 contractMatch=true(input_tokens 逐场景完全相同,
tool_result 逐字相同,中断轮双侧 done 收尾、同 session 续发一次通过);
凭据形态 grep=0
- docs/research/ai-sdk-7-adoption-decision.md: 新增采用决策文档——结论 partial
(依赖升级 go / provider 能力 capability-gated go / Phase 4 外围能力 go /
@ai-sdk/mcp 与默认 loop 替换 no-go-现在),四层 rollback plan(能力开关→
wrapper→runtime switch→known-good version),每项结论标注 Phase 1-5 证据来源;
默认 Runtime 切换留人类闸门
- docs/exec-plans/tech-debt-tracker.md: 新增 op7418#49(tool-error part 被两条 loop
一致吞掉的既有 UX 债,独立于采用决策)
- docs/exec-plans/active/ai-sdk-7-runtime-loop-adoption.md: Phase 5 状态回写 +
决策日志 + Smoke Ledger / Loop Ledger 各一行
- docs/research/README.md: 索引新增决策文档条目
验证: npm run test 3598/3598 全绿;smoke 4/4 contractMatch(1 个 fix cycle 收敛,
两处均为脚本层问题非 loop 差异);src/ 零改动(默认 Runtime/聊天路径零变化)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户批准 partial(2026-07-04, run issue op7418#10): 采用 ai@7/@ai-sdk/* 依赖升级、
provider 参数能力 capability-gated、openai-chat image wrapper、timeout 原因码/
approval HMAC/trace 脱敏四件套(默认值经用户确认); @ai-sdk/mcp adapter 与
ToolLoopAgent 默认 loop 替换均不采用(留实验路径)。发版前保留官方一方 key
smoke gate。冲突仅 ai-sdk-7 计划决策日志一处,union 双方条目解决。
五个 phase 全部经 hands-off loop 完成并 Codex accepted(issues op7418#1/op7418#6/op7418#7/op7418#8/op7418#10)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
canblmz1 pushed a commit to canblmz1/CodePilot that referenced this pull request Aug 28, 2026
…lease
prefix-safe-json 0.2.0 -> 0.4.3 (exact). 0.4.3 is a security patch
(GHSA-3xpw-9694-2xxp) fixing three root causes in the AI SDK adapter/gate
this integration depends on:
1. AiSdkStreamAdapter.push() used to silently drop every raw event once
it had already observed its own terminal, so late/contradictory
evidence for a call never reached the coordinator at all.
2. takeDecision() used to read a decision snapshot frozen at finish()
time instead of the coordinator's live diagnostics, so evidence
recorded after finish() but before that call's authority was consumed
was never consulted.
3. A raw event carrying conflicting id/toolCallId used to silently
prefer id instead of failing the stream closed.
No public API change - createAiSdkExecutionGuard()/push()/finish()/
takeDecision() and the ExecuteDecision/NonExecutableDecision shapes this
integration reads (action, toolCallId, reason) are unchanged, confirmed
directly against the installed package's .d.ts, not assumed.
Verified against the real 0.4.3 install (resolved version, and lockfile
integrity hash, both confirmed exactly 0.4.3):
- npx tsc --noEmit (full project): clean, 0 errors.
- src/__tests__/unit/execution-guard.test.ts: 16/16 passing, identical
to the 0.2.0 result.
Adds src/__tests__/unit/execution-guard-post-terminal-authority.test.ts,
answering the actual question this bump exists to answer: does this
integration's own code exercise the fix, not just "does the library
still pass its own tests." resolvePendingExecutions() in
execution-guard.ts reads `decisions` directly off guard.finish()'s own
return value in the same statement - it never calls takeDecision().
A fresh guard is created per step and is never reused once its finish()
is read, so there is no async gap between this integration's own
finish() call and its own decision consumption for GHSA-3xpw-9694-2xxp's
literal finish()-to-takeDecision() window to open in here.
What is live in this integration is root cause op7418#1: whether a
late/contradicting raw event that arrives before a step's own
resolvePendingExecutions() call - anywhere in that step's fullStream -
correctly revokes authority instead of being silently dropped by the
adapter. The new test proves that directly, through this repo's real
execution-guard.ts functions (createStepGuard/registerDeferredExecution/
resolvePendingExecutions - the exact call path agent-loop.ts uses), plus
a control case confirming the fix does not overcorrect a genuinely clean
step. A second test exercises the raw prefix-safe-json library
(createAiSdkExecutionGuard directly, real push/finish/takeDecision, no
synthetic decision object) to confirm the literal advisory scenario is
fixed at the library level.
package-lock.json regenerated with `npm install prefix-safe-json@0.4.3
--save-exact`, not hand-edited.
Sign up for freeto 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.

2 participants

@xuxu777xu@op7418
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
feat: Windows platform adaptation by xuxu777xu · Pull Request #1 · op7418/CodePilot · GitHub
Skip to content

feat: Windows platform adaptation - #1

Merged
op7418 merged 2 commits into
op7418:mainfrom
xuxu777xu:feat/windows-drive-switcher
Feb 7, 2026
Merged

feat: Windows platform adaptation#1
op7418 merged 2 commits into
op7418:mainfrom
xuxu777xu:feat/windows-drive-switcher

Conversation

@xuxu777xu

@xuxu777xuxuxu777xu commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

Summary

CodePilot 原本仅支持 macOS,本 PR 添加完整的 Windows 平台适配,使其可以在 Windows 上正常构建、运行和使用。

Changes

跨平台基础设施

  • 新增 src/lib/platform.ts:统一的跨平台工具模块,包含 Claude CLI 发现逻辑(Windows .cmd/.bat shell 处理、where/which 回退)、PATH 扩展(AppData/npm 等 Windows 路径)
  • 重构 src/app/api/claude-status/route.ts:移除硬编码的 Unix 路径,改用共享的 platform 工具
  • 重构 src/lib/claude-client.ts:同上,并确保 USERPROFILE 和扩展 PATH 在 SDK 子进程中可用

Electron 主进程

  • electron/main.ts
    • Windows 进程派生使用 windowsHide 防止控制台窗口闪烁
    • PATH 构建适配 Windows 分隔符(;)和目录结构(AppData/npm)
    • 窗口标题栏适配:macOS hiddenInset / Windows hidden + titleBarOverlay
    • 图标适配:Windows 使用 .ico
    • loadUserShellEnv() 跳过非 macOS 平台

构建配置

  • electron-builder.yml:新增 win + nsis 构建目标,支持自定义安装目录、桌面/开始菜单快捷方式
  • package.json:新增 electron:pack:win 脚本,原 electron:pack 改为平台无关
  • build/icon.ico:Windows 应用图标

UI 适配

  • src/components/chat/FolderPicker.tsx:新增盘符下拉切换器,解决 Windows 盘符根目录无法向上导航的问题
  • src/app/api/files/browse/route.ts:API 返回可用 Windows 盘符列表
  • src/components/skills/SkillsManager.tsx:修复 key 重复警告

Test plan

  • Windows 上 npm run electron:pack:win 构建成功
  • 安装后启动,Claude CLI 自动检测并连接
  • 标题栏样式正确(隐藏标题栏 + overlay 控制按钮)
  • FolderPicker 盘符切换正常工作
  • macOS 上 npm run electron:pack:mac 构建无回归

🤖 Generated with Claude Code

xuxu777xuand others added 2 commits February 7, 2026 13:29
When navigating to a drive root on Windows (e.g. C:\), path.dirname
returns itself, disabling the "go up" button and trapping the user on
that drive. This adds a compact dropdown next to the up button that
lists all available drives (auto-detected via fs.accessSync), allowing
quick switching between drives. macOS/Linux are unaffected (empty array,
dropdown not rendered).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add src/lib/platform.ts: cross-platform Claude CLI discovery
(candidate paths, .cmd/.bat shell handling, where/which fallback)
- Refactor claude-status route and claude-client to use shared platform utils
- Electron main: Windows process spawning (windowsHide), PATH construction
with AppData/npm dirs, titleBarOverlay, .ico icon support
- electron-builder.yml: add win/nsis build targets
- package.json: add electron:pack:win script
- FolderPicker: drive switcher dropdown for navigating between drives
- SkillsManager: fix duplicate key warning with filePath fallback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@xuxu777xuxuxu777xu changed the title feat: add Windows drive switcher in FolderPickerfeat: Windows platform adaptationFeb 7, 2026
@op7418
op7418 merged commit b819eb7 into op7418:mainFeb 7, 2026
op7418 added a commit that referenced this pull request Apr 12, 2026
…ion for Native Runtime
Two feature gaps where Native Runtime didn't match SDK Runtime, both
surfaced during post-hermes-upgrade manual testing:
── #1: Compression notification now human-readable ──
Before: chat/route.ts:402 emitted `message: 'context_compressed'` as
a machine string. useSSEStream's notification branch showed this raw
string in the status bar — users saw "context_compressed" flash by.
After: message is now `"Context compressed: N older messages summarized,
~X tokens saved"` with structured `stats: { messagesCompressed, tokensSaved }`
for future rich UI handling. Added `subtype: 'context_compressed'` for
dedicated frontend handlers.
── #3: AskUserQuestion tool for Native Runtime ──
Before: only SDK Runtime had AskUserQuestion (built into Claude Code CLI).
Native Runtime had no such tool, so the model could never ask structured
questions — the existing AskUserQuestionUI in PermissionPrompt.tsx was
unreachable dead UI code for Native Runtime users.
After:
- New builtin tool `src/lib/builtin-tools/ask-user-question.ts`
registered in index.ts, condition 'always'
- Zod schema: 1-6 questions, each with 1-6 options, optional multiSelect
- Execute receives answers from permission flow (injected by frontend)
and formats as Q/A pairs for the model
- permission-checker.ts: new ALWAYS_ASK_TOOLS set ensures AskUserQuestion
(and ExitPlanMode) always show UI even in trust mode — without this,
trust mode would auto-approve and return empty answers
- PermissionPrompt.tsx: NEVER_AUTO_APPROVE set prevents full_access mode
from auto-approving AskUserQuestion — the UI must render so the user
can answer
The data flow:
Model → AskUserQuestion({ questions }) → permission wrapper intercepts
→ SSE permission_request → frontend AskUserQuestionUI renders
→ user picks options → updatedInput({ questions, answers }) → tool
execute formats answers → model gets "Q: ... A: ..." string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KevinYoung-Kw referenced this pull request in KevinYoung-Kw/CodePilot Apr 15, 2026
**补充修复**
在 #1 斜杠命令保留已有文本的修复基础上,进一步确保选择命令后光标自动定位到输入框尾部,而不是默认的首部。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KevinYoung-Kw referenced this pull request in KevinYoung-Kw/CodePilot Apr 15, 2026
**补充修复**
在 #1 斜杠命令保留已有文本的修复基础上,进一步确保选择命令后光标自动定位到输入框尾部,而不是默认的首部。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
v0.56.x 计划 Phase 1:建立稳定性治理入口,并用当前源码重新核验 Notion/issue 列出的
7 个 issue(不采信 issue 自述根因)。
GitHub 侧(已在仓库生效,非本 commit 内容):
- 创建 milestone #1「v0.56.x Stability / Trust」。
- 创建 9 个治理 label:P0-crash-or-interrupt / P0-data-loss-risk / P1-runtime-session /
P1-context / P1-file-reference / P1-installer-update / P1-performance / needs-repro /
v0.57+ parking-lot。
- 给 #626/#628/#629/#632/#633/#634/#635 按复核结论打 milestone + 优先级 label。
本 commit 文件:
- .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml:bug 表单强制必填
版本/OS/runtime/provider-model/可复现/复现步骤/期望vs实际 + 影响面勾选;feature
表单注明 v0.56.x 冻结新功能 → v0.57+ parking-lot;config 关闭空白 issue + 冻结说明
与 Discussions 入口。
- .github/PULL_REQUEST_TEMPLATE.md:Summary / Repro+root cause / Changes / Tests /
Screenshots-logs / 自查清单(链到 CLAUDE.md 与 AGENTS.md,不复制维护)。
- .github/TRIAGE.md:对外冻结说明、label 体系、issue/PR triage 规则、自动化候选。
- v0.56.x-stability-trust.md:标 Phase 0 完成 + 新增「2026-06-19 Claude Code 源码复核」
表(7 issue 逐条 file:line 证据)。关键复核结论:
* #632 ">100%" 确认是未 clamp 的 ratio*100 显示 bug(RunCockpit.tsx:169 等),分母
contextWindow 不可靠;"跨会话串" 源码不成立。
* #629 空 assistant 已防护,残留真实 gap:is_error result 路径不清坏 sdk_session_id
(claude-client.ts:1908 先置 resultEmitted)。
* #635 截图-only,最强候选 = SDK runtime 无自生成 keepalive(claude-client.ts:1956),
慢 proxy 静默 >330s 被 idle abort(B-019)。
* #628 确认真实风险:@file origin path 在 MessageInput.tsx:161 丢失,body.mentions[]
送达但 route.ts 从不消费 → 写 .codepilot-uploads 副本,AI 改副本。
* #634 根因不成立——5 个 notify/schedule 工具均注册(builtin-tools/index.ts:250),
issue 引用的 UI 串不在当前源码(疑旧版);附带 Plan 模式 list_tasks 泄漏。
* #626 polling 排除(8h 间隔),候选 animate-pulse × backdrop-filter 重绘。
* #633 mac 无法复现;NSIS-only + 未签名 + 无 portable + CI 不验安装启动。
- issue-tracker.md:新增「v0.56.x 治理 issue」看板索引表(指向 plan 复核表,不重复分析)。
验证:docs-drift 通过;npm run test(hook)。Phase 1 验收(milestone/labels/模板/冻结
说明就绪)达成。下一步 Phase 2:按复核结论修 chat 主链路(上下文百分比语义、context-cost
不阻断发送、Codex 多模态发送、发送后清草稿)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: issue #632 报"上下文 >100% / 假百分比 / 压缩后跳变";Phase 1 源码复核确认是
真实显示 bug("跨会话串"不成立)。
Triage(当前源码): 用量百分比 = usage.ratio*100,在 RunCockpit.tsx 与
RunCockpitPopoverContent.tsx 两处直接渲染、未封顶;usage.ratio = used / contextWindow,
而 contextWindow 来自 sdkContextWindow ?? latestSdkContextWindow ?? catalogContextWindow
(useContextUsage.ts)。很多第三方 proxy 不上报 context_window → 落到静态 catalog 兜底
(一个猜测值),used 又会在压缩后跳变 → 百分比蹦到 200%/500%。根因是"拿不可信的分母
算百分比",不是上下文真的超了。
Fix:
- useContextUsage.ts: 新增 ContextUsageData.contextWindowTrusted —— 仅当 SDK/上游真实
上报窗口时为 true(catalog 兜底不算)。三个 return 分支(baseline / snapshot / no-baseline)
都按各自来源正确赋值。不可信时不把窗口喂给 buildContextUsageBreakdown,dot-matrix 退回
按已用 token 的构成比例,不编造容量。
- RunCockpit.tsx: hasFullCtx 增加 && usage.contextWindowTrusted —— 不可信时自动落到既有的
绝对已用 token 显示(触发按钮)/ showUnknownCapacityBlock 分支(浮层,已测试的"容量未知"
路径)。百分比文案 clamp ≤100%。
- RunCockpitPopoverContent.tsx: 浮层 header 百分比同样 clamp ≤100%(防可信窗口被 used 短暂
超过时仍蹦 >100%)。
语义验收: 输入框右下角不可信时只显示已用绝对值;浮层不可信时只显示已用 + 不同种类构成
比例(无百分比/remaining/unused/假总量);可信时百分比封顶 100%。
Verify: typecheck 通过;context-window-trusted.test.ts 6 条 source-pin + 既有
run-cockpit-unknown-capacity / context-dot-matrix / context-usage-walk / context-breakdown
全绿;全量单测 3366/3366。未做:真实 untrusted-window provider 会话的 CDP 视觉走查
(fix 把 untrusted 路由到既有已发布的"容量未知"分支,风险低;视觉走查列为后续)。
Guardrail: context-window-trusted.test.ts 钉死 trusted 派生只认 SDK 来源、不可信时不喂窗口、
hasFullCtx 必须 gate trusted、两处显示 clamp ≤100%,防回退到"拿 catalog 当真实分母算百分比"。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: Codex 复核 fix#1(b842628)后发现 P2 残留——文字已改成"只显示已用 token",
但输入框右下角触发按钮旁的 mini dot-bar 仍用 200K 兜底画出"用了多少/还剩多少"的容量
暗示,与"拿不到总长度就不显示容量"及 commit message 的"不编造容量"不一致。
Triage(当前源码): ContextDotMatrix.tsx 有 FALLBACK_CONTEXT_WINDOW=200_000,
minCellsPerKind=0(mini-bar)在窗口未知时用它当分母(:88);RunCockpit.tsx:200 的触发
按钮无条件渲染这个 mini-bar。所以即使 b842628 把文字降级为绝对已用,小条仍画假容量。
minCellsPerKind=0 全仓只有 RunCockpit 触发按钮一个调用方。
Fix:
- RunCockpit.tsx: mini-bar 用 {hasFullCtx && (...)} 包裹——仅在可信窗口下渲染容量小条;
不可信时触发按钮只剩绝对已用 token 文本(贴合"输入框右下角只显示已用数值")。
- ContextDotMatrix.tsx: 删除 FALLBACK_CONTEXT_WINDOW(200K)。窗口未知时两种模式都按
used+pending 分配(构成视图,非容量%),不再编造容量。
Verify: typecheck 通过;context-dot-matrix.test.ts 旧的"unknown mini-bar 用 200K 兜底
(filled<=2)"语义改为新的"used 构成(filled>=8)";context-window-trusted.test.ts 加 2 条
guardrail(mini-bar gate 在 hasFullCtx + 源码无 200K 兜底残留);全量单测 3368/3368。
Guardrail: 两条 source-pin 钉死"触发按钮 mini-bar 必须 gate 在 hasFullCtx"且"ContextDotMatrix
不得再出现 FALLBACK_CONTEXT_WINDOW/200_000",防回退到拿假容量画小条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
用户复核 fix#1 后明确显示格式:输入框右下角的上下文小标,在有可信窗口时显示
"百分比 + 已用上下文"(如 56.6% 452K),没有可信窗口时只显示已用(如 452K),
不单列"剩余"数字。
改动:RunCockpit.tsx 触发按钮 ratioText 的可信分支由 "{pct}%" 改为
"{pct}% {used}"(1 位小数,匹配用户给的 56.6% 示例);不可信/无数据分支不变。
context-window-trusted.test.ts 的 clamp pin 扩为同时断言"百分比 + 已用"格式。
验证:dev 应用热重载干净(✓ Compiled);context-window-trusted 8/8;typecheck(hook)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: 用户在运行的应用里看到 GLM-5-turbo(Claude Code/Native 会话)仍显示总上下文
200K,指出"这并不是我们知道的部分"。fix#1 本应让 catalog 静态值不可信、只显示已用。
Triage(当前源码,用户 review 驱动): agent-loop.ts:641-651(Native)在 token_usage
没有 context_window 时,从静态 catalog 填 totalUsage.context_window = getContextWindow(modelId)
(GLM-5-turbo 在 catalog 是 z.ai 核实的 202752)。而 context-usage-walk 把
token_usage.context_window 当作 SDK 实报窗口读,fix#1 的 contextWindowTrusted 据此判可信
→ catalog 猜测被"洗白"成可信 → Native GLM 显示 200K。即上游 mutator 打败了 helper 修复
(feedback_fix_all_consumers)。claude-client(Claude Code)只从 SDK modelUsage 写,不洗白;
ContextUsageIndicator 是死组件(无人 import)。
Fix: 删掉 agent-loop 的 catalog 洗白。Native 无 runtime 实报时 context_window 留空 →
useContextUsage 回落 catalog 为不可信 → 只显示已用绝对值,不再有假百分比/假总量。
仅对新 turn 生效(历史消息已存的 context_window 不改写,遵守不改用户数据;旧会话发新消息后转为已用-only)。
Verify: typecheck;context-window-trusted.test.ts 新增 pin 断言 agent-loop 不再
`.context_window = catalogWindow`;该文件 9 测 + agent-loop-error-event 全过。运行中 dev 应用
server 重编译干净(Native GLM 需发新消息验证)。
Guardrail: source-pin 防 Native 再把 catalog 洗进 SDK-authoritative 字段。
设计记录(用户批准"先记计划再实现"): v0.56.x 计划写入 context-window 来源优先级修订设计
(runtime 实报 > provider 配置 contextWindow > 压缩阈值 > catalog 不可信)+ 跨 Runtime 用户
配置源(#1,待实现) + 显示分母对齐压缩阈值(#3,待实现)。本提交是设计第一步(去洗白)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
把"为什么 GLM 显示 200K + 窗口来源该怎么改"写成评审稿放进 v0.56.x Phase 2,按
外部事实 / 本地证据(file:line) / 推断与设计三层分写,供 Codex 核实。
要点:
- Agent SDK v0.2.111 的 modelUsage.contextWindow(sdk.d.ts:945)是未文档化字段,来自
SDK 内置模型目录而非 API;第一方可靠、第三方(经 base_url 的 GLM)返回通用默认值;
无 SDK 设置可覆盖;Anthropic 建议自维护窗口表。
- 实测 GLM 会话 token_usage.context_window=200000 ≠ 本地 catalog 202752,证实来自 SDK
默认而非 catalog/Native 洗白;该会话是 Claude Code(故上一提交的 Native 修复不覆盖它)。
- 修订设计:窗口来源优先级 = 用户覆盖 > 已核实 catalog/provider 配置 > SDK(仅第一方) >
只显示已用;第三方忽略 SDK 默认值;跨 Runtime;显示分母对齐压缩阈值(#3)。
- 列出待定决策(已核实优先 vs 纯手动) + 给 Codex 的 5 个核实点。
未改任何产品代码(纯文档)。#1/#3 实现待 Codex 核实后进行。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Codex 复核设计稿后订正(实现 #1/#3 前必须):
- A:原"官方文档不记载 contextWindow/maxOutputTokens"不准 → 改为 SDK TypeScript
reference 有字段定义,是 cost-tracking 指南未解释来源/可信度。
- B/C:原"catalog 202752 比 SDK 200000 更准且 z.ai 核实"站不住 → z.ai 官方写
200K/128K,catalog 该条来源存疑;结论收敛为"SDK 200000 不可作为 provider 实报采信",
不延伸到"catalog 更准";另标记需单独核 model-context.ts:42 的真实来源。
- D + 决策日志:统一优先级(消除冲突,旧决策日志把第三方 SDK 又洗白成可信)→
用户手动覆盖 > provider/model 配置且来源已验证 > 第一方 runtime 实报 > 只显示已用;
第三方 SDK contextWindow 默认不可信、无明确来源 catalog 不当可信%显示。
- "Anthropic 官方建议自维护表"未核到原文 → 降级为工程结论。
- 澄清:用户实际看到 200K 的 GLM 会话是 Claude Code(SDK 默认 200000),非 Native 洗白
路径(681706b 的 Native 修复有效但治另一条路径)。
- E:决策收敛为一条基线 + 剩余一项请用户定(第一方 SDK 实报是否自动显示百分比)。
Codex 核为真的部分(sdk.d.ts:945 字段、代码写入 token_usage、历史 SDK 窗口被当可信、
Native 洗白已去、显示分母 vs 压缩阈值脱节)保留。纯文档,未动产品代码。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
F 段核实点 #1 还残留旧"官方文档未记载(A)",与已订正的 A 段不一致。改为:
sdk.d.ts:945 的 contextWindow/maxOutputTokens 存在,SDK TypeScript reference 已列,
只是 cost-tracking 指南未解释来源/可信度。纯文档。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
… Phase 2 ①)
Signal: 用户 GLM-5-turbo(Claude Code 经代理)显示总上下文 200K,且 Codex 核实 SDK 的
modelUsage.contextWindow 来自 SDK 内置目录、对第三方是通用默认值、无 SDK 设置可覆盖。
Triage: claude-client.ts extractTokenUsage 把 SDK modelUsage.contextWindow 无条件写入
token_usage.context_window;walk + fix#1 据此判可信 → 第三方代理(GLM)的 SDK 默认 200000
被当可信显示。Native 的 catalog 洗白已于 681706b 去掉;本提交补 SDK 路径。
Fix(Codex 统一口径"第一方 runtime 实报可信、第三方不可信"):
- ai-provider.ts 导出 isFirstPartyAnthropicEndpoint(baseUrl)(空/anthropic.com → 第一方)。
- extractTokenUsage 增 trustContextWindow,仅 true 时写 context_window;两个调用点都传
isFirstPartyAnthropicEndpoint(resolved.provider?.base_url)。第三方(自定义 base_url,如 GLM)
→ 不写 context_window → useContextUsage 回落 catalog 为不可信 → 只显示已用。
效果 + 边界: 第一方 Anthropic 继续显示百分比+已用;第三方代理新 turn 起只显示已用。
仅对新写入生效(历史消息已存的 context_window 不改写,遵守不改用户数据);现有 GLM 会话
仍显示旧值,需新会话/新 turn 验证(walk 会读历史,故旧会话需自然滚动出旧窗口或新建)。
Verify: typecheck;extract-token-usage-context-window.test.ts 增 2 pin(gate + 两调用点传
第一方判别);全量 3371/3371。
Guardrail: source-pin 钉死 context_window 写入受 trustContextWindow 门控 + 两调用点必须传
isFirstPartyAnthropicEndpoint,防回退到无条件信任第三方 SDK 窗口。
remaining(Phase 2 ①/③ 未完): provider/model 配置窗口作为最高优先可信源(用户覆盖) + 渲染层
对现有会话按第一方 gate(治旧会话) + #3 显示分母对齐压缩阈值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
计划文档状态审计修正(决策日志准、但概览层过期):
- frontmatter 状态行:📋 待接手 → 🚧 Phase 0/1 已完成、Phase 2 进行中。
- 「状态总览」表:Phase 1 待开始 → ✅ 已完成(2026-06-19);Phase 2 待开始 → 🚧 进行中。
- Phase 2 加进度 note:Composer/Context 主链路 #1#5 全部收口(含 commit + #3 真实
Codex 冒烟回复 circle);Session/Stream cluster #629/#635 + 终态原因码 + 压缩回滚
+ 诊断导出字段待续。
- Phase 2 执行清单 4 项已完成项 [ ]→[x](上下文 UI 语义 / context-cost 去阻断 /
Codex 多模态发送 / 发送后草稿清理)。
CLAUDE.md 执行计划段新增「完成即回写进度(与 Codex 对齐协作)」:任一 Phase/子项做完
必须立即回写三处且一致——执行清单勾选 / 状态总览表+frontmatter / 决策日志(commit
+验证结论);Claude 实施+回写、Codex 审查+维护;三者不一致视为状态失真须先对齐。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
打回上一条状态同步的一处失真:我把 #4/#5「发送后内容残留」标成完成(checklist [x] +
进度 note 列为 done),但同一文档决策日志(2026-06-20 条)已写明用户再次确认"内容已发出
但文本仍残留输入框"、#615 source-pin 不覆盖该症状、不能算闭环——状态表/清单与决策日志
自相矛盾,违反刚加的"三者必须一致"。
修正(与决策日志对齐):
- checklist「复现并修发送后内容残留」[x] → [ ],标注"待复核/待修复(用户 2026-06-20 再报)"。
- Phase 2 进度 note:拆分——#4/#5 仅失败保留有基础修复(#615),发送成功后文本残留待复核;
note 标题从"主链路已收口"改为"#1#3 收口、#4/#5 待复核";待续列表补回 #4/#5(重新打开)。
- #2 context-cost 非阻断保持完成(checklist [x] + note)不变。
后续修 #4/#5 时重点:PromptInput 受控/非受控清空边界、setInputValue('') 与
controller.textInput.clear() 是否同源、成功 accepted 后 remount/local draft 恢复、
badge/confirm/image 分支与普通 Enter 分支是否一致(决策日志已记排查方向)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
按"完成即回写进度"规则同步三处:
- checklist「复现并修发送后内容残留」[ ]→[x],标注已修 + CDP 验证 + 根因/修法(58c7aad)。
- Phase 2 进度 note:#1#5 全部落地;#4/#5 从"待复核"改为"已定位+修复"(含根因/CDP 结论);
待续列表移除 #4/#5、只留 Session/Stream cluster。
- 决策日志加同日条目:CDP 埋点定位 = 首条消息 accept 布局翻转 remount composer、inputValue
从 sessionStorage 草稿重读;修法 = accept 处清草稿;3401/3401 + CDP 文本/图文首条 800ms 即清。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
用户在浏览器实测不残留、仅桌面 App 残留 → Claude 协助完整重启 electron:dev(kill 整棵
进程树 + 释放 3000 + 后台重启)→ 用户在重启后真实 App 验证发送即清空 → #4/#5 闭环。
根因:58c7aad(page.tsx accept 处清首条草稿)一直是对的;用户残留是 Electron dev 没把
page.tsx 改动热更新进 renderer、窗口刷新无效,得整进程重启。这解释了全程「Claude CDP
浏览器清、用户残留」的矛盾——不是 Electron 行为差异,是构建新鲜度差异(Claude 浏览器硬刷
过有修复、用户 Electron 旧构建没有)。
回写:checklist [x](用户真实 App 验证)、进度 note #1#5 全闭环、验收去 ⚠️、决策日志加
闭环条目 + 教训(UI 修复在桌面 App 验证必须整重启 electron:dev)。Codex P1(prefill/
initialValue 回灌)仍是 58c7aad 的真实独立漏洞、值得单独补,与本次残留无关。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
纯文档同步,无代码改动。目的:让下一个进程打开文档时不从旧状态误判进度。
三处状态表此前已标 Phase 0/1 ✅、决策日志也已确认完成,唯独执行清单 checkbox
与 README 索引、issue-tracker #632 仍停在旧值——三处不一致即状态失真,本次对齐。
README.md:
- v0.56.x 索引行状态列 "📋 待 Phase 0 收束" → "🚧 Phase 0/1 ✅;Phase 2 进行中
(Composer/Context 主链路 #1#5 闭环,Session/Stream cluster #629/#635 待续)",
追上 plan frontmatter 与决策日志。
v0.56.x-stability-trust.md:
- Phase 0 执行清单 8 项 [ ]→[x],逐条带回溯(3360/3360、9c6e772、f99edbb/d00449f)。
A2 计时器项如实标注:按 keyed-remount 构造性消除 + 截图不可判别记录入 Smoke Ledger,
非逐帧视觉确认(反假数据,不谎称做了视觉确认)。
- Phase 1 执行清单 5 项 [ ]→[x],带回溯(milestone #1 / 9 labels / .github/TRIAGE.md)。
issue-tracker.md:
- #632 状态 "🔴 待修" → "🟡 假%已修,item3 分母对齐待续"。核心显示 bug(假百分比/>100%)
已由 effective-base-URL 写入 gate + 渲染期 trusted gate + clamp 修复并经真实 GLM
会话验证;item3(显示分母对齐压缩阈值)是独立待续阶段,故标部分修复而非已修复。
- 顶部"最后更新"同步到 2026-06-26 + #632 同步说明。
验证:git diff 确认仅 3 文档、16/16 行 checkbox 与状态文字,无代码/意外文件。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jul 4, 2026
- docs/research/ai-sdk-7-toolloop-parity-gaps.md: 新增「Phase 5 处置」节,全部 gap
收口——P1×3 关闭(#1/#2 补偿由 parity 8/8 复跑锁定;#3 降级论证:Phase 4 已证
approval HMAC 不需要 SDK toolApproval 停机语义,维持 in-execute 路线),
P2/P3 关闭或 backlog(#4/#5 列为替换路线前置条件,#7 归档 tech-debt #49#8 有 Phase 5 新实证)
- scripts/smoke-ai-sdk7-phase5-decision.ts: 新增决策门对照 smoke——prod runAgentLoop
与 POC runToolLoopAgentPoc 用同一 AgentLoopOptions 逐场景对照(长文本 / approval
批准 / approval 拒绝 / abort→continue),机械比较归一化事件序列 + 尾部契约 +
usage 存在性;DB 只读、数据目录隔离、输出全 scrub。探针注意:approval 批准分支
用 printf(echo 命中 permission-checker 自动放行规则不会触发 ask)
- docs/exec-plans/active/_smoke-evidence/ai-sdk7-phase5-decision-smoke.json:
OpenRouter 真实渠道 4/4 场景 contractMatch=true(input_tokens 逐场景完全相同,
tool_result 逐字相同,中断轮双侧 done 收尾、同 session 续发一次通过);
凭据形态 grep=0
- docs/research/ai-sdk-7-adoption-decision.md: 新增采用决策文档——结论 partial
(依赖升级 go / provider 能力 capability-gated go / Phase 4 外围能力 go /
@ai-sdk/mcp 与默认 loop 替换 no-go-现在),四层 rollback plan(能力开关→
wrapper→runtime switch→known-good version),每项结论标注 Phase 1-5 证据来源;
默认 Runtime 切换留人类闸门
- docs/exec-plans/tech-debt-tracker.md: 新增 #49(tool-error part 被两条 loop
一致吞掉的既有 UX 债,独立于采用决策)
- docs/exec-plans/active/ai-sdk-7-runtime-loop-adoption.md: Phase 5 状态回写 +
决策日志 + Smoke Ledger / Loop Ledger 各一行
- docs/research/README.md: 索引新增决策文档条目
验证: npm run test 3598/3598 全绿;smoke 4/4 contractMatch(1 个 fix cycle 收敛,
两处均为脚本层问题非 loop 差异);src/ 零改动(默认 Runtime/聊天路径零变化)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jul 4, 2026
用户批准 partial(2026-07-04, run issue #10): 采用 ai@7/@ai-sdk/* 依赖升级、
provider 参数能力 capability-gated、openai-chat image wrapper、timeout 原因码/
approval HMAC/trace 脱敏四件套(默认值经用户确认); @ai-sdk/mcp adapter 与
ToolLoopAgent 默认 loop 替换均不采用(留实验路径)。发版前保留官方一方 key
smoke gate。冲突仅 ai-sdk-7 计划决策日志一处,union 双方条目解决。
五个 phase 全部经 hands-off loop 完成并 Codex accepted(issues #1/#6/#7/#8/#10)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ion for Native Runtime
Two feature gaps where Native Runtime didn't match SDK Runtime, both
surfaced during post-hermes-upgrade manual testing:
── op7418#1: Compression notification now human-readable ──
Before: chat/route.ts:402 emitted `message: 'context_compressed'` as
a machine string. useSSEStream's notification branch showed this raw
string in the status bar — users saw "context_compressed" flash by.
After: message is now `"Context compressed: N older messages summarized,
~X tokens saved"` with structured `stats: { messagesCompressed, tokensSaved }`
for future rich UI handling. Added `subtype: 'context_compressed'` for
dedicated frontend handlers.
── op7418#3: AskUserQuestion tool for Native Runtime ──
Before: only SDK Runtime had AskUserQuestion (built into Claude Code CLI).
Native Runtime had no such tool, so the model could never ask structured
questions — the existing AskUserQuestionUI in PermissionPrompt.tsx was
unreachable dead UI code for Native Runtime users.
After:
- New builtin tool `src/lib/builtin-tools/ask-user-question.ts`
registered in index.ts, condition 'always'
- Zod schema: 1-6 questions, each with 1-6 options, optional multiSelect
- Execute receives answers from permission flow (injected by frontend)
and formats as Q/A pairs for the model
- permission-checker.ts: new ALWAYS_ASK_TOOLS set ensures AskUserQuestion
(and ExitPlanMode) always show UI even in trust mode — without this,
trust mode would auto-approve and return empty answers
- PermissionPrompt.tsx: NEVER_AUTO_APPROVE set prevents full_access mode
from auto-approving AskUserQuestion — the UI must render so the user
can answer
The data flow:
Model → AskUserQuestion({ questions }) → permission wrapper intercepts
→ SSE permission_request → frontend AskUserQuestionUI renders
→ user picks options → updatedInput({ questions, answers }) → tool
execute formats answers → model gets "Q: ... A: ..." string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ge generation results
GPT-Image-2.0 skill silent failure had two compounding causes both
on the 'tool result' loop:
P0 op7418#1 — function_call_output translated with sentinel toolName
translate-input.ts wrote toolName: '__from_responses_proxy__' for every
tool-result and the comment claimed 'ai-sdk doesn't use this for
routing'. That was wrong. Anthropic and OpenAI Responses both look
up the tool definition by tool-result.toolName when reconciling the
result with the request's tool surface; with a sentinel they can't
correlate and refuse to produce the continuation turn — exactly the
'tool ran, no follow-up text' the user saw.
Fix: walk the input array once first to build call_id → toolName
from function_call items, then look up the real name when translating
function_call_output. Orphan results (no matching function_call) fall
back to a named sentinel '__orphan_function_call_output__' AND emit
console.warn naming the call_id. The divergence stays loud.
P0 op7418#2 — imageGeneration / imageView silently dropped
event-mapper.ts had both item types in CHAT_ONLY_ITEM_TYPES, which
returns null on item/started + item/completed. That set is correct
for agentMessage/plan/reasoning (they have streaming delta channels
so the content arrives separately), but imageGeneration / imageView
have NO delta channel — their final item is the only surface where
the result reaches the user. Silent drop meant 'tool ran' with no
visible image.
Fix: move both types to TOOL_LIKE_ITEM_TYPES, add explicit
translateItemStarted branches with names image_generation /
image_view, and the existing TOOL_LIKE_ITEM_TYPES completion branch
already packs the full item into output — preserving result,
savedPath, revisedPrompt, path for chat-side rendering.
ThreadItemLike grew matching fields so TS doesn't downgrade access
to (item as { path?: string }).path casts.
Tests (8 new)
src/__tests__/unit/codex-proxy-translators.test.ts (+3):
- toolName resolves from matching function_call (gpt_image_2 case)
- toolName resolves correctly with interleaved out-of-order calls
- orphan function_call_output → named sentinel + console.warn
src/__tests__/unit/codex-event-mapper.test.ts (+4):
- imageGeneration item/started → tool_started(name='image_generation')
- imageGeneration item/completed → tool_completed with full
result + savedPath + revisedPrompt payload
- imageView item/started → tool_started(name='image_view') + path
- imageView item/completed → tool_completed with path preserved
src/__tests__/unit/codex-proxy-tool-contract.test.ts (+1):
- End-to-end continuation: function_call → function_call_output →
streamText(messages) — MockLanguageModelV3 must see toolName
'gpt_image_2' in its prompt, NOT '__from_responses_proxy__'.
Continuation text-delta event fires.
The mapper-side translate also removed the chatOnly array's
imageView / imageGeneration entries from the old 'returns null'
parameterised test; replaced with the new lifecycle describe block.
Closeout doc records round 7 ✅ items; remaining must-haves
unchanged (4-family smoke matrix + codex-sdk POC).
All 2416 tests pass (was 2412 + 8 new − 4 obsolete from the chatOnly
table for imageView/imageGeneration).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ce 2a
Direction approved; three sharpenings folded into the existing
Phase 2 plan structure without restructuring.
1. Widget wire-format single source (review revision op7418#1)
slice 7's WIDGET_SYSTEM_PROMPT template-literal-embeds
WIDGET_WIRE_FORMAT_SPEC. With artifactContracts ordered BEFORE
capabilityFragments in the compiler, the wire spec would land in
the final system prompt twice (once from artifactContract, once
from the capability fragment tail). The plan now declares hard
constraints — CANONICAL_SHOW_WIDGET_JSON, the "FINAL OUTPUT
FORMAT" title, and WIDGET_WIRE_FORMAT_SPEC each must appear
exactly once in the compiled system prompt — and assigns slice
2c a small refactor that strips the wire spec from
WIDGET_SYSTEM_PROMPT so artifactContract becomes the sole holder.
Compile-time sanity check (capability fragment text MUST NOT
contain artifactContract.canonicalJson) added as a defence-in-
depth FAIL path.
2. Expected Differences Ledger (review revision op7418#2)
2b's "compiler output === Runtime current prompt" stance
directly conflicted with slice 2d's plan to canonicalize Native
memory / notify / media-import paraphrases. Equivalence reading
strictly would have locked the old drift in. Plan now introduces
`src/lib/harness/expected-differences.ts` with typed entries
(runtimeId, capability, diff kind, justification,
plannedResolution, compilerSource, runtimeSource). 2b harness
reads "compiler vs runtime diff ⊆ ledger"; unregistered
differences fail. Initial ledger seeded with the four known
Phase 5c slice 7b tech-debt items, three earmarked for slice 2d
and one (image_generation MediaBlock shape) earmarked
follow_up. Slice 2d completion = manual ledger entry removal
(deliberate non-automation, preserves audit trail).
3. runtimeHints boundary (review revision op7418#3)
Plan tightens the runtimeHints type declaration so it cannot
become a fourth prompt-assembly point. Allowed: IDs (mcp server
names, tool keys, builtin tool name set), fragmentIds refs into
CompiledContext, adapter options (stopWhen / stepCount /
passthroughToolTypes). Forbidden: any prompt text string, tool
description paraphrase, capability redefinition. Three test
layers — type-level (string fields ≤ 64 chars, no newline / no
markdown), runtime-level (no template-literal-shaped values),
source-grep level (no multi-line template literals in
runtimeHints assignments) — plus a dangling-reference check
that every fragmentId in runtimeHints resolves in
CompiledContext.
Regression test list extended 9 → 12. Decision log records all
three revisions with rationale.
Plan still in 📋 status. No code; awaiting Codex re-review on the
revised draft, then slice 2a opens.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
User mode change: "internal slice order preserved, external single
delivery; stop only after Phase 2 is done; Codex review takes the
batch." This commit lands slices 2a–2e together with all post-
review hardenings (Widget wire-format single source, Expected
Differences Ledger, runtimeHints prose ban).
Internal slice walk
2a — context-compiler.ts (NEW)
Pure function `compileContext(input): CompiledContext`. No IO,
no provider calls. Resolves enabledCapabilities (null = catalog
live default), looks up exposure for the calling runtime, emits
capabilityFragments + artifactContracts + memory + workspace +
toolDescriptors + runtimeHints + budget + systemPromptText +
diagnostics. Hard contracts: artifactContract before capability
in the assembled prompt; fragmentId uniqueness; cross-runtime
fragment text identity; compile-time FAIL if a capability
fragment text contains an artifact contract canonicalJson
(wire-format dedup); compile-time FAIL if load-bearing fragments
exceed budget. runtimeHints types strictly ID/refs/adapter
options — no prose, no template literals.
2b — expected-differences.ts (NEW)
Drift ledger. Initial 4 entries from slice 7b tech-debt. Three
slice_2d entries consumed by this commit (see 2d below); the
one remaining `follow_up` is image_generation MediaBlock shape
(non-prompt, future slice).
2c — ClaudeCode SDK (claude-client.ts) source-pin only
The SDK path has always imported MCP canonicals directly
(memory-search-mcp, notification-mcp, media-import-mcp,
cli-tools-mcp, dashboard-mcp) — no paraphrase ever existed.
Slice 2c codifies this with a contract test: claude-client.ts
must not import capability prompts from builtin-tools/* and
must not declare its own _SYSTEM_PROMPT scalars.
2d — Native Runtime (builtin-tools/*) re-export MCP canonicals
`memory-search.ts` now `export const MEMORY_SEARCH_SYSTEM_PROMPT =
CANONICAL_MEMORY_SEARCH_SYSTEM_PROMPT` (imported from
memory-search-mcp.ts). Same pattern for `notification.ts`
(NOTIFICATION_SYSTEM_PROMPT = NOTIFICATION_MCP_SYSTEM_PROMPT)
and `media.ts` (MEDIA_SYSTEM_PROMPT = MEDIA_MCP_SYSTEM_PROMPT
from media-import-mcp.ts). Three ledger entries removed in
sync.
2e — Codex bridge (builtin-bridge.ts + unified-adapter.ts)
Bridge no longer holds WIDGET_PROMPT / MEDIA_PROMPT /
MEMORY_PROMPT / NOTIFY_PROMPT scalars (all four declarations
deleted). `createCodePilotBuiltinTools().systemPrompt` is
permanently `''`. `unified-adapter.ts` now calls
`compileContext({ runtimeId: 'codex_runtime', ... })` and feeds
`compiled.systemPromptText` to Codex's `instructions`. A new
helper `capabilitiesFromBridgeToolNames` maps the bridge's
mounted tool names back to capability ids so the compiler's
enabledCapabilities aligns with what the bridge actually
exposes (workspace-gated memory tools naturally drop out when
workspacePath is empty).
Slice 2c Widget wire-format single source (review revision op7418#1)
WIDGET_SYSTEM_PROMPT in widget-guidelines.ts no longer
template-literal-embeds `${WIDGET_WIRE_FORMAT_SPEC}`. The
artifactContract is now the sole holder of the wire-format spec
+ canonical JSON. Compiler's `detectWireFormatDuplication` sanity
check throws at compile time if any capability fragment text
contains the artifact contract canonicalJson — that's the forcing
function preventing the spec from being re-injected.
Three regression pins enforce single occurrence in the compiled
prompt: CANONICAL_SHOW_WIDGET_JSON × 1, "FINAL OUTPUT FORMAT —
non-negotiable" × 1, WIDGET_WIRE_FORMAT_SPEC × 1.
runtimeHints boundary (review revision op7418#3)
ClaudeCodeHints / NativeHints / CodexProxyHints types now carry
only IDs (mcp server names, tool keys, builtin tool name set) +
adapter options (stopWhen, stepCount, passthroughToolTypes).
Tests pin: type-level (no string field > 64 chars, no newline,
no Markdown markers), runtime-level (scan all string values for
prose), source-grep (CodexProxyHints type definition can't
contain `promptOverride` / `promptExtra` / `widgetPrompt` / etc).
Tests
New harness-context-compiler.test.ts (23 pins): catalog hygiene,
Widget wire-format single source (op7418#10), ordering, budget
enforcement, cross-runtime fragment identity (op7418#9), tool
descriptors, runtimeHints boundary (op7418#11), Expected Differences
Ledger consistency (op7418#12), JSON parseability of every artifact
contract.
New harness-context-compiler-equivalence.test.ts (9 pins):
compiler source reachability, runtime drift honesty,
ledger/slice ownership correctness, "post-slice-2d: Native
ledger holds only the follow_up MediaBlock entry".
Updated harness-capability-contract.test.ts: drift pins now
check (a) bridge holds no local _PROMPT scalars, (b) Native
builtin-tools re-export MCP canonicals, (c) unified-adapter
imports compileContext + consumes systemPromptText, (d)
claude-client.ts doesn't import from builtin-tools/* and
doesn't declare own _SYSTEM_PROMPT.
Updated codex-widget-format-contract.test.ts: the "WIDGET_SYSTEM_PROMPT
embeds WIDGET_WIRE_FORMAT_SPEC" and "appears inside
WIDGET_SYSTEM_PROMPT" pins are flipped — slice 2c REMOVED the
embed; the new pins verify the compiler-side import line.
Updated codex-builtin-bridge.test.ts: tests previously asserting
`bridge.systemPrompt` contained capability tags now assert it
equals `''` (bridge is no longer the prompt-assembly point).
Verification
CODEX_DISABLED=1 npx tsx --test \
src/__tests__/unit/harness-context-compiler.test.ts \
src/__tests__/unit/harness-context-compiler-equivalence.test.ts \
src/__tests__/unit/harness-capability-contract.test.ts \
src/__tests__/unit/codex-widget-format-contract.test.ts \
src/__tests__/unit/codex-builtin-bridge.test.ts
→ 74/74 pass
npm run test → 2576/2576 pass
Completion criteria check (per user spec)
[x] npm run test all green (2576/2576)
[x] Context Compiler unit tests all green
[x] equivalence / expected-diff harness all green
[x] harness-capability-contract / codex-widget-format /
codex-builtin-bridge tests all green
[x] no new runtime-local prompt duplicates (Native re-exports
canonical; ClaudeCode imports canonical; bridge holds none)
[x] Codex bridge no longer holds WIDGET_PROMPT / MEDIA_PROMPT /
MEMORY_PROMPT / NOTIFY_PROMPT scalars (all four removed,
drift test pins their absence)
[x] all three Runtimes adapt compiler output, none redefine
capability prompts
Docs
- phase-5d-phase-2-context-compiler.md: slice statuses 2a–2e all
✅ 2026-05-17; note the one-shot delivery mode change.
- phase-5d-harness-capability-contract.md: Phase 2 row ✅, awaiting
Codex review.
- handover/harness-capability-contract.md: new "Context Compiler"
section detailing inputs/outputs/constraints, three-runtime
consumption pattern, Expected Differences Ledger contract.
- refactor-closeout.md: new decision-log entry recording the
Phase 2 delivery shape + completion criteria check.
Phase 5d Phase 2 ✅ pending Codex review. Phase 3 (Runtime
Capability Adapter) / Phase 4 (Artifact Contract) / Phase 5
(new-Runtime Playbook) intentionally NOT opened — stopping per
user instruction.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
… to breakdown
## 用户视角
升级前:popover 的"文件与附件 / 本次待加入"两行永远 0 —— 数据通道没接通。即使 composer 里挂了 4 个 mention 和 2 个目录引用,popover breakdown 显示 0。
升级后:MessageInput → ChatView/page → RunCockpit → useContextUsage → buildContextUsageBreakdown 全链路联通。composer 里的 attachment / mention / directory 实时累加到对应类别。trigger 上的迷你点阵 + popover 主条 + 列表行三处同步更新。
发送消息后 pending 归 0;下一轮 history 里的真实 token_usage 接管 used 部分;conversation 类自动吸收。
## 不做什么
- 不改 hook 其他字段(used / ratio / state / source 等不动)
- 不改 trigger 主结构(百分比文字仍在;只有点阵 cells 在分配时反映 pending)
- 不改 composer text 估算(composerTextTokens 仍 0;那是 Phase 3+ 的事)
## 怎么验收
- npm run test → 2921/2921 pass
- composer 里加附件 / @mention / "+" 目录 → trigger 上 pending 部分立刻有虚线 cells
- 发送消息 → pending 归零;下轮 used cells 更新
## 改动(6 文件)
### src/lib/message-input-logic.ts
新增 `PendingContextSubTotals` interface + `computePendingContextSubTotals()` 函数。逻辑 mirror `computePendingContextTokens`(同样的 null 过滤、同样的迭代顺序),但返回 { attachment, mention, directory } 三键。两个函数加起来 = 等于 computePendingContextTokens 总数。
### src/hooks/useContextUsage.ts
options 加可选 `pending?: { attachmentTokens?, mentionTokens?, directoryTokens?, composerTextTokens? }`。三条返回路径(snapshot / walk / noData)都把 options?.pending 转发给 buildContextUsageBreakdown。useMemo deps 数组加 options?.pending。
### src/components/chat/RunCockpit.tsx
RunCockpitProps 加可选 `pendingContextSubTotals?: { attachment, mention, directory }`。组件内部把它转换成 hook options.pending 形态(attachment → attachmentTokens 等)。可选 prop 默认 undefined → 不破坏现有 callsites。
### src/components/chat/MessageInput.tsx
- import 加 computePendingContextSubTotals + PendingContextSubTotals type
- props 加可选 `onPendingContextSubTotalsChange?` callback(跟现有 onPendingContextTokensChange 并列)
- 新增 useMemo 算 pendingContextSubTotals + useEffect emit callback
- 与现有 pendingContextTokens 走同一份 source 数据,逻辑同步无 divergence
### src/components/chat/ChatView.tsx
- 加 state `pendingContextSubTotals` (PendingContextSubTotals | undefined)
- MessageInput 上 wire `onPendingContextSubTotalsChange={setPendingContextSubTotals}`
- RunCockpit 上传 `pendingContextSubTotals={pendingContextSubTotals}`
### src/app/chat/page.tsx
- 跟 ChatView 完全镜像:state + MessageInput callback + RunCockpit prop
- 两个入口独立持有 state(按 StreamSession guardrail 不变量 op7418#1)
## Scope discipline
- 不新增测试(Codex 负责测试覆盖;用户分工已明确)
- 不动 buildContextUsageBreakdown / computePendingContextTokens 既有签名 → 旧调用 zero-risk
- 不改 chat-static-graph 排除清单 → MessageInput / RunCockpit 改动属于增量 prop,没新依赖链
- composerTextTokens 仍未 wire(composer 纯文本估算属于未来扩展,pending_next_turn 行暂时仍 0)
## StreamSession guardrail 合规
- 双入口(page.tsx 首消息 + ChatView 后续)独立 state — 不变量 op7418#1 ✅
- onSend / onCommand 签名不变 — rewind point 不变量 op7418#2 ✅
- 不动 capability cache — 不变量 op7418#3 ✅
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…18#31)
Codex review second round caught two real P1 inconsistencies introduced by
the Dashboard/CLI split slice plus non-blocking contract drift.
P1.1 — Dashboard injection gate ≠ route auth gate.
runtime.ts injected the dashboard read/write MCPs whenever prompt + working
directory + dashboard keyword matched, but the route's `authorize` requires
`sameRealPath(workspacePath, assistant_workspace_path)`. Mismatch → the model
sees the tool and Codex 403s at call time. Fix: dashboard injection mirrors
memory's gate exactly (same sameRealPath check, same `assistantWorkspacePath`
passed as `workspacePath`) so "inject" and "route-authorize" never disagree.
CLI tools don't need this (no workspace scope).
P1.2 — Matrix promoted only for codex_account; runtime injects for ALL
codex_runtime providers.
The runtime didn't gate injection by provider, so under a CodePilot proxy
provider the dashboard/cli MCPs WERE injected (callable), but the matrix
returned `perception_only` for non-codex_account — the opposite drift from
P1.1 ("model says yes, Settings says no"). Fix per Codex's preferred option:
move the promotion into `capabilityMatrixForRuntime` so it applies to ALL
codex_runtime providers; `capabilityMatrixForRuntimeProvider` now only adds
codex_account-specific overrides (native notes + image/media demotion).
`buildCapabilityMatrix` delegates to `capabilityMatrixForRuntime` so every
matrix entry point stays aligned.
Non-blocking op7418#1 — contract text drift.
capability-contract.ts dashboard/cli `deferredReason` + `codex_proxy.notes`
rewritten — explicit that the LEGACY provider-proxy bridge is unsupported
(true), and that the codex_runtime path now ships via the mutation-level MCP
split + matrix-layer promotion. No schema changes (`kind: 'unsupported'`
stays accurate for the legacy bridge surface); the existing matrix invariant
test gets a `MATRIX_LAYER_PROMOTIONS` exception list documenting why the two
promoted cells are allowed to be executable despite `kind: 'unsupported'`.
Schema cleanup (introduce a new `mcp_server_split` kind, drop the exception
list) tracked as tech-debt op7418#33.
Non-blocking op7418#2 — elicitation policy pins.
codex-mcp-events.test.ts now pins all 4 new server names:
codepilot_{dashboard,cli_tools}_read → auto_accept,
codepilot_{dashboard,cli_tools}_write → user_approval.
Also added a regression guard: `codex_runtime + non-codex_account provider`
must STILL show dashboard/cli_tools executable with mixed trust + the right
noteKey. Updated the two pre-existing tests that asserted the OLD behaviour
(dashboard/cli perception_only on codex_runtime) — they now assert the
promoted state. Also synced the static `CAPABILITY_EXECUTABLE_RUNTIMES` map.
Per Codex review's explicit ask: the "待真账号 smoke" wording stays in the
op7418#31 capability table — this commit fixes the inconsistencies, but the
real-account end-to-end smoke for natural-conversation triggering + write
approval card + Deny blocking is still owed by the user.
Full unit suite 3045/3045. Live route: bad workspace still 403 (auth gate
intact); tools/list subsets unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Codex review 认可方向,按 5 条反馈修订(纯文档,无代码):
- Phase A 增"开工前核验"(Opus 4.8 官方 model id / context window / thinking·effort / 1M beta,不臆测)
- Phase A 实现范围增"泛化 Opus 4.7 专属逻辑"(isOpus47Model / OPUS_4_7_PATTERN / applyContext1mBeta /
effort 门控 / claude-client sanitizer,配回归测试)—— catalog 显示 ≠ 请求正确
- OpenRouter Opus 4.8 改 deferred(不臆测 slug),首轮只接 Anthropic direct
- opus 别名 / 默认先不动(仍 4.7),只新增显式 claude-opus-4-8,切换待 smoke 后用户拍板
- Phase D 拆 D0/D:D0 把 apply-discovery-diff 全量 flake + no-verify 事件记入 tech-debt op7418#30(本提交即 D0);
D 建议先于 A/B/C,代码 phase 不再靠 --no-verify
- Open Questions op7418#1/op7418#2 据上述决议收敛
本提交纯文档;pre-commit 同样因 apply-discovery-diff 全量 flake 用 --no-verify,已确认 docs-drift 绿。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
v0.56.x 计划 Phase 1:建立稳定性治理入口,并用当前源码重新核验 Notion/issue 列出的
7 个 issue(不采信 issue 自述根因)。
GitHub 侧(已在仓库生效,非本 commit 内容):
- 创建 milestone op7418#1「v0.56.x Stability / Trust」。
- 创建 9 个治理 label:P0-crash-or-interrupt / P0-data-loss-risk / P1-runtime-session /
P1-context / P1-file-reference / P1-installer-update / P1-performance / needs-repro /
v0.57+ parking-lot。
- 给 op7418#626/op7418#628/op7418#629/op7418#632/op7418#633/op7418#634/op7418#635 按复核结论打 milestone + 优先级 label。
本 commit 文件:
- .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml:bug 表单强制必填
版本/OS/runtime/provider-model/可复现/复现步骤/期望vs实际 + 影响面勾选;feature
表单注明 v0.56.x 冻结新功能 → v0.57+ parking-lot;config 关闭空白 issue + 冻结说明
与 Discussions 入口。
- .github/PULL_REQUEST_TEMPLATE.md:Summary / Repro+root cause / Changes / Tests /
Screenshots-logs / 自查清单(链到 CLAUDE.md 与 AGENTS.md,不复制维护)。
- .github/TRIAGE.md:对外冻结说明、label 体系、issue/PR triage 规则、自动化候选。
- v0.56.x-stability-trust.md:标 Phase 0 完成 + 新增「2026-06-19 Claude Code 源码复核」
表(7 issue 逐条 file:line 证据)。关键复核结论:
* op7418#632 ">100%" 确认是未 clamp 的 ratio*100 显示 bug(RunCockpit.tsx:169 等),分母
contextWindow 不可靠;"跨会话串" 源码不成立。
* op7418#629 空 assistant 已防护,残留真实 gap:is_error result 路径不清坏 sdk_session_id
(claude-client.ts:1908 先置 resultEmitted)。
* op7418#635 截图-only,最强候选 = SDK runtime 无自生成 keepalive(claude-client.ts:1956),
慢 proxy 静默 >330s 被 idle abort(B-019)。
* op7418#628 确认真实风险:@file origin path 在 MessageInput.tsx:161 丢失,body.mentions[]
送达但 route.ts 从不消费 → 写 .codepilot-uploads 副本,AI 改副本。
* op7418#634 根因不成立——5 个 notify/schedule 工具均注册(builtin-tools/index.ts:250),
issue 引用的 UI 串不在当前源码(疑旧版);附带 Plan 模式 list_tasks 泄漏。
* op7418#626 polling 排除(8h 间隔),候选 animate-pulse × backdrop-filter 重绘。
* op7418#633 mac 无法复现;NSIS-only + 未签名 + 无 portable + CI 不验安装启动。
- issue-tracker.md:新增「v0.56.x 治理 issue」看板索引表(指向 plan 复核表,不重复分析)。
验证:docs-drift 通过;npm run test(hook)。Phase 1 验收(milestone/labels/模板/冻结
说明就绪)达成。下一步 Phase 2:按复核结论修 chat 主链路(上下文百分比语义、context-cost
不阻断发送、Codex 多模态发送、发送后清草稿)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…e 2 op7418#1)
Signal: issue op7418#632 报"上下文 >100% / 假百分比 / 压缩后跳变";Phase 1 源码复核确认是
真实显示 bug("跨会话串"不成立)。
Triage(当前源码): 用量百分比 = usage.ratio*100,在 RunCockpit.tsx 与
RunCockpitPopoverContent.tsx 两处直接渲染、未封顶;usage.ratio = used / contextWindow,
而 contextWindow 来自 sdkContextWindow ?? latestSdkContextWindow ?? catalogContextWindow
(useContextUsage.ts)。很多第三方 proxy 不上报 context_window → 落到静态 catalog 兜底
(一个猜测值),used 又会在压缩后跳变 → 百分比蹦到 200%/500%。根因是"拿不可信的分母
算百分比",不是上下文真的超了。
Fix:
- useContextUsage.ts: 新增 ContextUsageData.contextWindowTrusted —— 仅当 SDK/上游真实
上报窗口时为 true(catalog 兜底不算)。三个 return 分支(baseline / snapshot / no-baseline)
都按各自来源正确赋值。不可信时不把窗口喂给 buildContextUsageBreakdown,dot-matrix 退回
按已用 token 的构成比例,不编造容量。
- RunCockpit.tsx: hasFullCtx 增加 && usage.contextWindowTrusted —— 不可信时自动落到既有的
绝对已用 token 显示(触发按钮)/ showUnknownCapacityBlock 分支(浮层,已测试的"容量未知"
路径)。百分比文案 clamp ≤100%。
- RunCockpitPopoverContent.tsx: 浮层 header 百分比同样 clamp ≤100%(防可信窗口被 used 短暂
超过时仍蹦 >100%)。
语义验收: 输入框右下角不可信时只显示已用绝对值;浮层不可信时只显示已用 + 不同种类构成
比例(无百分比/remaining/unused/假总量);可信时百分比封顶 100%。
Verify: typecheck 通过;context-window-trusted.test.ts 6 条 source-pin + 既有
run-cockpit-unknown-capacity / context-dot-matrix / context-usage-walk / context-breakdown
全绿;全量单测 3366/3366。未做:真实 untrusted-window provider 会话的 CDP 视觉走查
(fix 把 untrusted 路由到既有已发布的"容量未知"分支,风险低;视觉走查列为后续)。
Guardrail: context-window-trusted.test.ts 钉死 trusted 派生只认 SDK 来源、不可信时不喂窗口、
hasFullCtx 必须 gate trusted、两处显示 clamp ≤100%,防回退到"拿 catalog 当真实分母算百分比"。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Signal: Codex 复核 fixop7418#1(9ea29a4)后发现 P2 残留——文字已改成"只显示已用 token",
但输入框右下角触发按钮旁的 mini dot-bar 仍用 200K 兜底画出"用了多少/还剩多少"的容量
暗示,与"拿不到总长度就不显示容量"及 commit message 的"不编造容量"不一致。
Triage(当前源码): ContextDotMatrix.tsx 有 FALLBACK_CONTEXT_WINDOW=200_000,
minCellsPerKind=0(mini-bar)在窗口未知时用它当分母(:88);RunCockpit.tsx:200 的触发
按钮无条件渲染这个 mini-bar。所以即使 9ea29a4 把文字降级为绝对已用,小条仍画假容量。
minCellsPerKind=0 全仓只有 RunCockpit 触发按钮一个调用方。
Fix:
- RunCockpit.tsx: mini-bar 用 {hasFullCtx && (...)} 包裹——仅在可信窗口下渲染容量小条;
不可信时触发按钮只剩绝对已用 token 文本(贴合"输入框右下角只显示已用数值")。
- ContextDotMatrix.tsx: 删除 FALLBACK_CONTEXT_WINDOW(200K)。窗口未知时两种模式都按
used+pending 分配(构成视图,非容量%),不再编造容量。
Verify: typecheck 通过;context-dot-matrix.test.ts 旧的"unknown mini-bar 用 200K 兜底
(filled<=2)"语义改为新的"used 构成(filled>=8)";context-window-trusted.test.ts 加 2 条
guardrail(mini-bar gate 在 hasFullCtx + 源码无 200K 兜底残留);全量单测 3368/3368。
Guardrail: 两条 source-pin 钉死"触发按钮 mini-bar 必须 gate 在 hasFullCtx"且"ContextDotMatrix
不得再出现 FALLBACK_CONTEXT_WINDOW/200_000",防回退到拿假容量画小条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户复核 fixop7418#1 后明确显示格式:输入框右下角的上下文小标,在有可信窗口时显示
"百分比 + 已用上下文"(如 56.6% 452K),没有可信窗口时只显示已用(如 452K),
不单列"剩余"数字。
改动:RunCockpit.tsx 触发按钮 ratioText 的可信分支由 "{pct}%" 改为
"{pct}% {used}"(1 位小数,匹配用户给的 56.6% 示例);不可信/无数据分支不变。
context-window-trusted.test.ts 的 clamp pin 扩为同时断言"百分比 + 已用"格式。
验证:dev 应用热重载干净(✓ Compiled);context-window-trusted 8/8;typecheck(hook)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…llow-up)
Signal: 用户在运行的应用里看到 GLM-5-turbo(Claude Code/Native 会话)仍显示总上下文
200K,指出"这并不是我们知道的部分"。fixop7418#1 本应让 catalog 静态值不可信、只显示已用。
Triage(当前源码,用户 review 驱动): agent-loop.ts:641-651(Native)在 token_usage
没有 context_window 时,从静态 catalog 填 totalUsage.context_window = getContextWindow(modelId)
(GLM-5-turbo 在 catalog 是 z.ai 核实的 202752)。而 context-usage-walk 把
token_usage.context_window 当作 SDK 实报窗口读,fixop7418#1 的 contextWindowTrusted 据此判可信
→ catalog 猜测被"洗白"成可信 → Native GLM 显示 200K。即上游 mutator 打败了 helper 修复
(feedback_fix_all_consumers)。claude-client(Claude Code)只从 SDK modelUsage 写,不洗白;
ContextUsageIndicator 是死组件(无人 import)。
Fix: 删掉 agent-loop 的 catalog 洗白。Native 无 runtime 实报时 context_window 留空 →
useContextUsage 回落 catalog 为不可信 → 只显示已用绝对值,不再有假百分比/假总量。
仅对新 turn 生效(历史消息已存的 context_window 不改写,遵守不改用户数据;旧会话发新消息后转为已用-only)。
Verify: typecheck;context-window-trusted.test.ts 新增 pin 断言 agent-loop 不再
`.context_window = catalogWindow`;该文件 9 测 + agent-loop-error-event 全过。运行中 dev 应用
server 重编译干净(Native GLM 需发新消息验证)。
Guardrail: source-pin 防 Native 再把 catalog 洗进 SDK-authoritative 字段。
设计记录(用户批准"先记计划再实现"): v0.56.x 计划写入 context-window 来源优先级修订设计
(runtime 实报 > provider 配置 contextWindow > 压缩阈值 > catalog 不可信)+ 跨 Runtime 用户
配置源(op7418#1,待实现) + 显示分母对齐压缩阈值(op7418#3,待实现)。本提交是设计第一步(去洗白)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
把"为什么 GLM 显示 200K + 窗口来源该怎么改"写成评审稿放进 v0.56.x Phase 2,按
外部事实 / 本地证据(file:line) / 推断与设计三层分写,供 Codex 核实。
要点:
- Agent SDK v0.2.111 的 modelUsage.contextWindow(sdk.d.ts:945)是未文档化字段,来自
SDK 内置模型目录而非 API;第一方可靠、第三方(经 base_url 的 GLM)返回通用默认值;
无 SDK 设置可覆盖;Anthropic 建议自维护窗口表。
- 实测 GLM 会话 token_usage.context_window=200000 ≠ 本地 catalog 202752,证实来自 SDK
默认而非 catalog/Native 洗白;该会话是 Claude Code(故上一提交的 Native 修复不覆盖它)。
- 修订设计:窗口来源优先级 = 用户覆盖 > 已核实 catalog/provider 配置 > SDK(仅第一方) >
只显示已用;第三方忽略 SDK 默认值;跨 Runtime;显示分母对齐压缩阈值(op7418#3)。
- 列出待定决策(已核实优先 vs 纯手动) + 给 Codex 的 5 个核实点。
未改任何产品代码(纯文档)。op7418#1/op7418#3 实现待 Codex 核实后进行。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Codex 复核设计稿后订正(实现 op7418#1/op7418#3 前必须):
- A:原"官方文档不记载 contextWindow/maxOutputTokens"不准 → 改为 SDK TypeScript
reference 有字段定义,是 cost-tracking 指南未解释来源/可信度。
- B/C:原"catalog 202752 比 SDK 200000 更准且 z.ai 核实"站不住 → z.ai 官方写
200K/128K,catalog 该条来源存疑;结论收敛为"SDK 200000 不可作为 provider 实报采信",
不延伸到"catalog 更准";另标记需单独核 model-context.ts:42 的真实来源。
- D + 决策日志:统一优先级(消除冲突,旧决策日志把第三方 SDK 又洗白成可信)→
用户手动覆盖 > provider/model 配置且来源已验证 > 第一方 runtime 实报 > 只显示已用;
第三方 SDK contextWindow 默认不可信、无明确来源 catalog 不当可信%显示。
- "Anthropic 官方建议自维护表"未核到原文 → 降级为工程结论。
- 澄清:用户实际看到 200K 的 GLM 会话是 Claude Code(SDK 默认 200000),非 Native 洗白
路径(f79fd54 的 Native 修复有效但治另一条路径)。
- E:决策收敛为一条基线 + 剩余一项请用户定(第一方 SDK 实报是否自动显示百分比)。
Codex 核为真的部分(sdk.d.ts:945 字段、代码写入 token_usage、历史 SDK 窗口被当可信、
Native 洗白已去、显示分母 vs 压缩阈值脱节)保留。纯文档,未动产品代码。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
F 段核实点 op7418#1 还残留旧"官方文档未记载(A)",与已订正的 A 段不一致。改为:
sdk.d.ts:945 的 contextWindow/maxOutputTokens 存在,SDK TypeScript reference 已列,
只是 cost-tracking 指南未解释来源/可信度。纯文档。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…#632 / Phase 2 ①)
Signal: 用户 GLM-5-turbo(Claude Code 经代理)显示总上下文 200K,且 Codex 核实 SDK 的
modelUsage.contextWindow 来自 SDK 内置目录、对第三方是通用默认值、无 SDK 设置可覆盖。
Triage: claude-client.ts extractTokenUsage 把 SDK modelUsage.contextWindow 无条件写入
token_usage.context_window;walk + fixop7418#1 据此判可信 → 第三方代理(GLM)的 SDK 默认 200000
被当可信显示。Native 的 catalog 洗白已于 f79fd54 去掉;本提交补 SDK 路径。
Fix(Codex 统一口径"第一方 runtime 实报可信、第三方不可信"):
- ai-provider.ts 导出 isFirstPartyAnthropicEndpoint(baseUrl)(空/anthropic.com → 第一方)。
- extractTokenUsage 增 trustContextWindow,仅 true 时写 context_window;两个调用点都传
isFirstPartyAnthropicEndpoint(resolved.provider?.base_url)。第三方(自定义 base_url,如 GLM)
→ 不写 context_window → useContextUsage 回落 catalog 为不可信 → 只显示已用。
效果 + 边界: 第一方 Anthropic 继续显示百分比+已用;第三方代理新 turn 起只显示已用。
仅对新写入生效(历史消息已存的 context_window 不改写,遵守不改用户数据);现有 GLM 会话
仍显示旧值,需新会话/新 turn 验证(walk 会读历史,故旧会话需自然滚动出旧窗口或新建)。
Verify: typecheck;extract-token-usage-context-window.test.ts 增 2 pin(gate + 两调用点传
第一方判别);全量 3371/3371。
Guardrail: source-pin 钉死 context_window 写入受 trustContextWindow 门控 + 两调用点必须传
isFirstPartyAnthropicEndpoint,防回退到无条件信任第三方 SDK 窗口。
remaining(Phase 2 ①/③ 未完): provider/model 配置窗口作为最高优先可信源(用户覆盖) + 渲染层
对现有会话按第一方 gate(治旧会话) + op7418#3 显示分母对齐压缩阈值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
计划文档状态审计修正(决策日志准、但概览层过期):
- frontmatter 状态行:📋 待接手 → 🚧 Phase 0/1 已完成、Phase 2 进行中。
- 「状态总览」表:Phase 1 待开始 → ✅ 已完成(2026-06-19);Phase 2 待开始 → 🚧 进行中。
- Phase 2 加进度 note:Composer/Context 主链路 op7418#1op7418#5 全部收口(含 commit + op7418#3 真实
Codex 冒烟回复 circle);Session/Stream cluster op7418#629/op7418#635 + 终态原因码 + 压缩回滚
+ 诊断导出字段待续。
- Phase 2 执行清单 4 项已完成项 [ ]→[x](上下文 UI 语义 / context-cost 去阻断 /
Codex 多模态发送 / 发送后草稿清理)。
CLAUDE.md 执行计划段新增「完成即回写进度(与 Codex 对齐协作)」:任一 Phase/子项做完
必须立即回写三处且一致——执行清单勾选 / 状态总览表+frontmatter / 决策日志(commit
+验证结论);Claude 实施+回写、Codex 审查+维护;三者不一致视为状态失真须先对齐。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
打回上一条状态同步的一处失真:我把 op7418#4/op7418#5「发送后内容残留」标成完成(checklist [x] +
进度 note 列为 done),但同一文档决策日志(2026-06-20 条)已写明用户再次确认"内容已发出
但文本仍残留输入框"、op7418#615 source-pin 不覆盖该症状、不能算闭环——状态表/清单与决策日志
自相矛盾,违反刚加的"三者必须一致"。
修正(与决策日志对齐):
- checklist「复现并修发送后内容残留」[x] → [ ],标注"待复核/待修复(用户 2026-06-20 再报)"。
- Phase 2 进度 note:拆分——op7418#4/op7418#5 仅失败保留有基础修复(op7418#615),发送成功后文本残留待复核;
note 标题从"主链路已收口"改为"op7418#1op7418#3 收口、op7418#4/op7418#5 待复核";待续列表补回 op7418#4/op7418#5(重新打开)。
- op7418#2 context-cost 非阻断保持完成(checklist [x] + note)不变。
后续修 op7418#4/op7418#5 时重点:PromptInput 受控/非受控清空边界、setInputValue('') 与
controller.textInput.clear() 是否同源、成功 accepted 后 remount/local draft 恢复、
badge/confirm/image 分支与普通 Enter 分支是否一致(决策日志已记排查方向)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
按"完成即回写进度"规则同步三处:
- checklist「复现并修发送后内容残留」[ ]→[x],标注已修 + CDP 验证 + 根因/修法(de123df)。
- Phase 2 进度 note:op7418#1op7418#5 全部落地;op7418#4/op7418#5 从"待复核"改为"已定位+修复"(含根因/CDP 结论);
待续列表移除 op7418#4/op7418#5、只留 Session/Stream cluster。
- 决策日志加同日条目:CDP 埋点定位 = 首条消息 accept 布局翻转 remount composer、inputValue
从 sessionStorage 草稿重读;修法 = accept 处清草稿;3401/3401 + CDP 文本/图文首条 800ms 即清。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户在浏览器实测不残留、仅桌面 App 残留 → Claude 协助完整重启 electron:dev(kill 整棵
进程树 + 释放 3000 + 后台重启)→ 用户在重启后真实 App 验证发送即清空 → op7418#4/op7418#5 闭环。
根因:de123df(page.tsx accept 处清首条草稿)一直是对的;用户残留是 Electron dev 没把
page.tsx 改动热更新进 renderer、窗口刷新无效,得整进程重启。这解释了全程「Claude CDP
浏览器清、用户残留」的矛盾——不是 Electron 行为差异,是构建新鲜度差异(Claude 浏览器硬刷
过有修复、用户 Electron 旧构建没有)。
回写:checklist [x](用户真实 App 验证)、进度 note op7418#1op7418#5 全闭环、验收去 ⚠️、决策日志加
闭环条目 + 教训(UI 修复在桌面 App 验证必须整重启 electron:dev)。Codex P1(prefill/
initialValue 回灌)仍是 de123df 的真实独立漏洞、值得单独补,与本次残留无关。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
纯文档同步,无代码改动。目的:让下一个进程打开文档时不从旧状态误判进度。
三处状态表此前已标 Phase 0/1 ✅、决策日志也已确认完成,唯独执行清单 checkbox
与 README 索引、issue-tracker op7418#632 仍停在旧值——三处不一致即状态失真,本次对齐。
README.md:
- v0.56.x 索引行状态列 "📋 待 Phase 0 收束" → "🚧 Phase 0/1 ✅;Phase 2 进行中
(Composer/Context 主链路 op7418#1op7418#5 闭环,Session/Stream cluster op7418#629/op7418#635 待续)",
追上 plan frontmatter 与决策日志。
v0.56.x-stability-trust.md:
- Phase 0 执行清单 8 项 [ ]→[x],逐条带回溯(3360/3360、dd4ead4、b853188/2de9c2b)。
A2 计时器项如实标注:按 keyed-remount 构造性消除 + 截图不可判别记录入 Smoke Ledger,
非逐帧视觉确认(反假数据,不谎称做了视觉确认)。
- Phase 1 执行清单 5 项 [ ]→[x],带回溯(milestone op7418#1 / 9 labels / .github/TRIAGE.md)。
issue-tracker.md:
- op7418#632 状态 "🔴 待修" → "🟡 假%已修,item3 分母对齐待续"。核心显示 bug(假百分比/>100%)
已由 effective-base-URL 写入 gate + 渲染期 trusted gate + clamp 修复并经真实 GLM
会话验证;item3(显示分母对齐压缩阈值)是独立待续阶段,故标部分修复而非已修复。
- 顶部"最后更新"同步到 2026-06-26 + op7418#632 同步说明。
验证:git diff 确认仅 3 文档、16/16 行 checkbox 与状态文字,无代码/意外文件。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
- docs/research/ai-sdk-7-toolloop-parity-gaps.md: 新增「Phase 5 处置」节,全部 gap
收口——P1×3 关闭(op7418#1/op7418#2 补偿由 parity 8/8 复跑锁定;op7418#3 降级论证:Phase 4 已证
approval HMAC 不需要 SDK toolApproval 停机语义,维持 in-execute 路线),
P2/P3 关闭或 backlog(op7418#4/op7418#5 列为替换路线前置条件,op7418#7 归档 tech-debt op7418#49op7418#8 有 Phase 5 新实证)
- scripts/smoke-ai-sdk7-phase5-decision.ts: 新增决策门对照 smoke——prod runAgentLoop
与 POC runToolLoopAgentPoc 用同一 AgentLoopOptions 逐场景对照(长文本 / approval
批准 / approval 拒绝 / abort→continue),机械比较归一化事件序列 + 尾部契约 +
usage 存在性;DB 只读、数据目录隔离、输出全 scrub。探针注意:approval 批准分支
用 printf(echo 命中 permission-checker 自动放行规则不会触发 ask)
- docs/exec-plans/active/_smoke-evidence/ai-sdk7-phase5-decision-smoke.json:
OpenRouter 真实渠道 4/4 场景 contractMatch=true(input_tokens 逐场景完全相同,
tool_result 逐字相同,中断轮双侧 done 收尾、同 session 续发一次通过);
凭据形态 grep=0
- docs/research/ai-sdk-7-adoption-decision.md: 新增采用决策文档——结论 partial
(依赖升级 go / provider 能力 capability-gated go / Phase 4 外围能力 go /
@ai-sdk/mcp 与默认 loop 替换 no-go-现在),四层 rollback plan(能力开关→
wrapper→runtime switch→known-good version),每项结论标注 Phase 1-5 证据来源;
默认 Runtime 切换留人类闸门
- docs/exec-plans/tech-debt-tracker.md: 新增 op7418#49(tool-error part 被两条 loop
一致吞掉的既有 UX 债,独立于采用决策)
- docs/exec-plans/active/ai-sdk-7-runtime-loop-adoption.md: Phase 5 状态回写 +
决策日志 + Smoke Ledger / Loop Ledger 各一行
- docs/research/README.md: 索引新增决策文档条目
验证: npm run test 3598/3598 全绿;smoke 4/4 contractMatch(1 个 fix cycle 收敛,
两处均为脚本层问题非 loop 差异);src/ 零改动(默认 Runtime/聊天路径零变化)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户批准 partial(2026-07-04, run issue op7418#10): 采用 ai@7/@ai-sdk/* 依赖升级、
provider 参数能力 capability-gated、openai-chat image wrapper、timeout 原因码/
approval HMAC/trace 脱敏四件套(默认值经用户确认); @ai-sdk/mcp adapter 与
ToolLoopAgent 默认 loop 替换均不采用(留实验路径)。发版前保留官方一方 key
smoke gate。冲突仅 ai-sdk-7 计划决策日志一处,union 双方条目解决。
五个 phase 全部经 hands-off loop 完成并 Codex accepted(issues op7418#1/op7418#6/op7418#7/op7418#8/op7418#10)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
canblmz1 pushed a commit to canblmz1/CodePilot that referenced this pull request Aug 28, 2026
…lease
prefix-safe-json 0.2.0 -> 0.4.3 (exact). 0.4.3 is a security patch
(GHSA-3xpw-9694-2xxp) fixing three root causes in the AI SDK adapter/gate
this integration depends on:
1. AiSdkStreamAdapter.push() used to silently drop every raw event once
it had already observed its own terminal, so late/contradictory
evidence for a call never reached the coordinator at all.
2. takeDecision() used to read a decision snapshot frozen at finish()
time instead of the coordinator's live diagnostics, so evidence
recorded after finish() but before that call's authority was consumed
was never consulted.
3. A raw event carrying conflicting id/toolCallId used to silently
prefer id instead of failing the stream closed.
No public API change - createAiSdkExecutionGuard()/push()/finish()/
takeDecision() and the ExecuteDecision/NonExecutableDecision shapes this
integration reads (action, toolCallId, reason) are unchanged, confirmed
directly against the installed package's .d.ts, not assumed.
Verified against the real 0.4.3 install (resolved version, and lockfile
integrity hash, both confirmed exactly 0.4.3):
- npx tsc --noEmit (full project): clean, 0 errors.
- src/__tests__/unit/execution-guard.test.ts: 16/16 passing, identical
to the 0.2.0 result.
Adds src/__tests__/unit/execution-guard-post-terminal-authority.test.ts,
answering the actual question this bump exists to answer: does this
integration's own code exercise the fix, not just "does the library
still pass its own tests." resolvePendingExecutions() in
execution-guard.ts reads `decisions` directly off guard.finish()'s own
return value in the same statement - it never calls takeDecision().
A fresh guard is created per step and is never reused once its finish()
is read, so there is no async gap between this integration's own
finish() call and its own decision consumption for GHSA-3xpw-9694-2xxp's
literal finish()-to-takeDecision() window to open in here.
What is live in this integration is root cause op7418#1: whether a
late/contradicting raw event that arrives before a step's own
resolvePendingExecutions() call - anywhere in that step's fullStream -
correctly revokes authority instead of being silently dropped by the
adapter. The new test proves that directly, through this repo's real
execution-guard.ts functions (createStepGuard/registerDeferredExecution/
resolvePendingExecutions - the exact call path agent-loop.ts uses), plus
a control case confirming the fix does not overcorrect a genuinely clean
step. A second test exercises the raw prefix-safe-json library
(createAiSdkExecutionGuard directly, real push/finish/takeDecision, no
synthetic decision object) to confirm the literal advisory scenario is
fixed at the library level.
package-lock.json regenerated with `npm install prefix-safe-json@0.4.3
--save-exact`, not hand-edited.
Sign up for freeto 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.

2 participants

@xuxu777xu@op7418
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat: Windows platform adaptation by xuxu777xu · Pull Request #1 · op7418/CodePilot · GitHub
Skip to content

feat: Windows platform adaptation - #1

Merged
op7418 merged 2 commits into
op7418:mainfrom
xuxu777xu:feat/windows-drive-switcher
Feb 7, 2026
Merged

feat: Windows platform adaptation#1
op7418 merged 2 commits into
op7418:mainfrom
xuxu777xu:feat/windows-drive-switcher

Conversation

@xuxu777xu

@xuxu777xuxuxu777xu commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

Summary

CodePilot 原本仅支持 macOS,本 PR 添加完整的 Windows 平台适配,使其可以在 Windows 上正常构建、运行和使用。

Changes

跨平台基础设施

  • 新增 src/lib/platform.ts:统一的跨平台工具模块,包含 Claude CLI 发现逻辑(Windows .cmd/.bat shell 处理、where/which 回退)、PATH 扩展(AppData/npm 等 Windows 路径)
  • 重构 src/app/api/claude-status/route.ts:移除硬编码的 Unix 路径,改用共享的 platform 工具
  • 重构 src/lib/claude-client.ts:同上,并确保 USERPROFILE 和扩展 PATH 在 SDK 子进程中可用

Electron 主进程

  • electron/main.ts
    • Windows 进程派生使用 windowsHide 防止控制台窗口闪烁
    • PATH 构建适配 Windows 分隔符(;)和目录结构(AppData/npm)
    • 窗口标题栏适配:macOS hiddenInset / Windows hidden + titleBarOverlay
    • 图标适配:Windows 使用 .ico
    • loadUserShellEnv() 跳过非 macOS 平台

构建配置

  • electron-builder.yml:新增 win + nsis 构建目标,支持自定义安装目录、桌面/开始菜单快捷方式
  • package.json:新增 electron:pack:win 脚本,原 electron:pack 改为平台无关
  • build/icon.ico:Windows 应用图标

UI 适配

  • src/components/chat/FolderPicker.tsx:新增盘符下拉切换器,解决 Windows 盘符根目录无法向上导航的问题
  • src/app/api/files/browse/route.ts:API 返回可用 Windows 盘符列表
  • src/components/skills/SkillsManager.tsx:修复 key 重复警告

Test plan

  • Windows 上 npm run electron:pack:win 构建成功
  • 安装后启动,Claude CLI 自动检测并连接
  • 标题栏样式正确(隐藏标题栏 + overlay 控制按钮)
  • FolderPicker 盘符切换正常工作
  • macOS 上 npm run electron:pack:mac 构建无回归

🤖 Generated with Claude Code

xuxu777xuand others added 2 commits February 7, 2026 13:29
When navigating to a drive root on Windows (e.g. C:\), path.dirname
returns itself, disabling the "go up" button and trapping the user on
that drive. This adds a compact dropdown next to the up button that
lists all available drives (auto-detected via fs.accessSync), allowing
quick switching between drives. macOS/Linux are unaffected (empty array,
dropdown not rendered).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add src/lib/platform.ts: cross-platform Claude CLI discovery
(candidate paths, .cmd/.bat shell handling, where/which fallback)
- Refactor claude-status route and claude-client to use shared platform utils
- Electron main: Windows process spawning (windowsHide), PATH construction
with AppData/npm dirs, titleBarOverlay, .ico icon support
- electron-builder.yml: add win/nsis build targets
- package.json: add electron:pack:win script
- FolderPicker: drive switcher dropdown for navigating between drives
- SkillsManager: fix duplicate key warning with filePath fallback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@xuxu777xuxuxu777xu changed the title feat: add Windows drive switcher in FolderPickerfeat: Windows platform adaptationFeb 7, 2026
@op7418
op7418 merged commit b819eb7 into op7418:mainFeb 7, 2026
op7418 added a commit that referenced this pull request Apr 12, 2026
…ion for Native Runtime
Two feature gaps where Native Runtime didn't match SDK Runtime, both
surfaced during post-hermes-upgrade manual testing:
── #1: Compression notification now human-readable ──
Before: chat/route.ts:402 emitted `message: 'context_compressed'` as
a machine string. useSSEStream's notification branch showed this raw
string in the status bar — users saw "context_compressed" flash by.
After: message is now `"Context compressed: N older messages summarized,
~X tokens saved"` with structured `stats: { messagesCompressed, tokensSaved }`
for future rich UI handling. Added `subtype: 'context_compressed'` for
dedicated frontend handlers.
── #3: AskUserQuestion tool for Native Runtime ──
Before: only SDK Runtime had AskUserQuestion (built into Claude Code CLI).
Native Runtime had no such tool, so the model could never ask structured
questions — the existing AskUserQuestionUI in PermissionPrompt.tsx was
unreachable dead UI code for Native Runtime users.
After:
- New builtin tool `src/lib/builtin-tools/ask-user-question.ts`
registered in index.ts, condition 'always'
- Zod schema: 1-6 questions, each with 1-6 options, optional multiSelect
- Execute receives answers from permission flow (injected by frontend)
and formats as Q/A pairs for the model
- permission-checker.ts: new ALWAYS_ASK_TOOLS set ensures AskUserQuestion
(and ExitPlanMode) always show UI even in trust mode — without this,
trust mode would auto-approve and return empty answers
- PermissionPrompt.tsx: NEVER_AUTO_APPROVE set prevents full_access mode
from auto-approving AskUserQuestion — the UI must render so the user
can answer
The data flow:
Model → AskUserQuestion({ questions }) → permission wrapper intercepts
→ SSE permission_request → frontend AskUserQuestionUI renders
→ user picks options → updatedInput({ questions, answers }) → tool
execute formats answers → model gets "Q: ... A: ..." string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KevinYoung-Kw referenced this pull request in KevinYoung-Kw/CodePilot Apr 15, 2026
**补充修复**
在 #1 斜杠命令保留已有文本的修复基础上,进一步确保选择命令后光标自动定位到输入框尾部,而不是默认的首部。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KevinYoung-Kw referenced this pull request in KevinYoung-Kw/CodePilot Apr 15, 2026
**补充修复**
在 #1 斜杠命令保留已有文本的修复基础上,进一步确保选择命令后光标自动定位到输入框尾部,而不是默认的首部。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
v0.56.x 计划 Phase 1:建立稳定性治理入口,并用当前源码重新核验 Notion/issue 列出的
7 个 issue(不采信 issue 自述根因)。
GitHub 侧(已在仓库生效,非本 commit 内容):
- 创建 milestone #1「v0.56.x Stability / Trust」。
- 创建 9 个治理 label:P0-crash-or-interrupt / P0-data-loss-risk / P1-runtime-session /
P1-context / P1-file-reference / P1-installer-update / P1-performance / needs-repro /
v0.57+ parking-lot。
- 给 #626/#628/#629/#632/#633/#634/#635 按复核结论打 milestone + 优先级 label。
本 commit 文件:
- .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml:bug 表单强制必填
版本/OS/runtime/provider-model/可复现/复现步骤/期望vs实际 + 影响面勾选;feature
表单注明 v0.56.x 冻结新功能 → v0.57+ parking-lot;config 关闭空白 issue + 冻结说明
与 Discussions 入口。
- .github/PULL_REQUEST_TEMPLATE.md:Summary / Repro+root cause / Changes / Tests /
Screenshots-logs / 自查清单(链到 CLAUDE.md 与 AGENTS.md,不复制维护)。
- .github/TRIAGE.md:对外冻结说明、label 体系、issue/PR triage 规则、自动化候选。
- v0.56.x-stability-trust.md:标 Phase 0 完成 + 新增「2026-06-19 Claude Code 源码复核」
表(7 issue 逐条 file:line 证据)。关键复核结论:
* #632 ">100%" 确认是未 clamp 的 ratio*100 显示 bug(RunCockpit.tsx:169 等),分母
contextWindow 不可靠;"跨会话串" 源码不成立。
* #629 空 assistant 已防护,残留真实 gap:is_error result 路径不清坏 sdk_session_id
(claude-client.ts:1908 先置 resultEmitted)。
* #635 截图-only,最强候选 = SDK runtime 无自生成 keepalive(claude-client.ts:1956),
慢 proxy 静默 >330s 被 idle abort(B-019)。
* #628 确认真实风险:@file origin path 在 MessageInput.tsx:161 丢失,body.mentions[]
送达但 route.ts 从不消费 → 写 .codepilot-uploads 副本,AI 改副本。
* #634 根因不成立——5 个 notify/schedule 工具均注册(builtin-tools/index.ts:250),
issue 引用的 UI 串不在当前源码(疑旧版);附带 Plan 模式 list_tasks 泄漏。
* #626 polling 排除(8h 间隔),候选 animate-pulse × backdrop-filter 重绘。
* #633 mac 无法复现;NSIS-only + 未签名 + 无 portable + CI 不验安装启动。
- issue-tracker.md:新增「v0.56.x 治理 issue」看板索引表(指向 plan 复核表,不重复分析)。
验证:docs-drift 通过;npm run test(hook)。Phase 1 验收(milestone/labels/模板/冻结
说明就绪)达成。下一步 Phase 2:按复核结论修 chat 主链路(上下文百分比语义、context-cost
不阻断发送、Codex 多模态发送、发送后清草稿)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: issue #632 报"上下文 >100% / 假百分比 / 压缩后跳变";Phase 1 源码复核确认是
真实显示 bug("跨会话串"不成立)。
Triage(当前源码): 用量百分比 = usage.ratio*100,在 RunCockpit.tsx 与
RunCockpitPopoverContent.tsx 两处直接渲染、未封顶;usage.ratio = used / contextWindow,
而 contextWindow 来自 sdkContextWindow ?? latestSdkContextWindow ?? catalogContextWindow
(useContextUsage.ts)。很多第三方 proxy 不上报 context_window → 落到静态 catalog 兜底
(一个猜测值),used 又会在压缩后跳变 → 百分比蹦到 200%/500%。根因是"拿不可信的分母
算百分比",不是上下文真的超了。
Fix:
- useContextUsage.ts: 新增 ContextUsageData.contextWindowTrusted —— 仅当 SDK/上游真实
上报窗口时为 true(catalog 兜底不算)。三个 return 分支(baseline / snapshot / no-baseline)
都按各自来源正确赋值。不可信时不把窗口喂给 buildContextUsageBreakdown,dot-matrix 退回
按已用 token 的构成比例,不编造容量。
- RunCockpit.tsx: hasFullCtx 增加 && usage.contextWindowTrusted —— 不可信时自动落到既有的
绝对已用 token 显示(触发按钮)/ showUnknownCapacityBlock 分支(浮层,已测试的"容量未知"
路径)。百分比文案 clamp ≤100%。
- RunCockpitPopoverContent.tsx: 浮层 header 百分比同样 clamp ≤100%(防可信窗口被 used 短暂
超过时仍蹦 >100%)。
语义验收: 输入框右下角不可信时只显示已用绝对值;浮层不可信时只显示已用 + 不同种类构成
比例(无百分比/remaining/unused/假总量);可信时百分比封顶 100%。
Verify: typecheck 通过;context-window-trusted.test.ts 6 条 source-pin + 既有
run-cockpit-unknown-capacity / context-dot-matrix / context-usage-walk / context-breakdown
全绿;全量单测 3366/3366。未做:真实 untrusted-window provider 会话的 CDP 视觉走查
(fix 把 untrusted 路由到既有已发布的"容量未知"分支,风险低;视觉走查列为后续)。
Guardrail: context-window-trusted.test.ts 钉死 trusted 派生只认 SDK 来源、不可信时不喂窗口、
hasFullCtx 必须 gate trusted、两处显示 clamp ≤100%,防回退到"拿 catalog 当真实分母算百分比"。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: Codex 复核 fix#1(b842628)后发现 P2 残留——文字已改成"只显示已用 token",
但输入框右下角触发按钮旁的 mini dot-bar 仍用 200K 兜底画出"用了多少/还剩多少"的容量
暗示,与"拿不到总长度就不显示容量"及 commit message 的"不编造容量"不一致。
Triage(当前源码): ContextDotMatrix.tsx 有 FALLBACK_CONTEXT_WINDOW=200_000,
minCellsPerKind=0(mini-bar)在窗口未知时用它当分母(:88);RunCockpit.tsx:200 的触发
按钮无条件渲染这个 mini-bar。所以即使 b842628 把文字降级为绝对已用,小条仍画假容量。
minCellsPerKind=0 全仓只有 RunCockpit 触发按钮一个调用方。
Fix:
- RunCockpit.tsx: mini-bar 用 {hasFullCtx && (...)} 包裹——仅在可信窗口下渲染容量小条;
不可信时触发按钮只剩绝对已用 token 文本(贴合"输入框右下角只显示已用数值")。
- ContextDotMatrix.tsx: 删除 FALLBACK_CONTEXT_WINDOW(200K)。窗口未知时两种模式都按
used+pending 分配(构成视图,非容量%),不再编造容量。
Verify: typecheck 通过;context-dot-matrix.test.ts 旧的"unknown mini-bar 用 200K 兜底
(filled<=2)"语义改为新的"used 构成(filled>=8)";context-window-trusted.test.ts 加 2 条
guardrail(mini-bar gate 在 hasFullCtx + 源码无 200K 兜底残留);全量单测 3368/3368。
Guardrail: 两条 source-pin 钉死"触发按钮 mini-bar 必须 gate 在 hasFullCtx"且"ContextDotMatrix
不得再出现 FALLBACK_CONTEXT_WINDOW/200_000",防回退到拿假容量画小条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
用户复核 fix#1 后明确显示格式:输入框右下角的上下文小标,在有可信窗口时显示
"百分比 + 已用上下文"(如 56.6% 452K),没有可信窗口时只显示已用(如 452K),
不单列"剩余"数字。
改动:RunCockpit.tsx 触发按钮 ratioText 的可信分支由 "{pct}%" 改为
"{pct}% {used}"(1 位小数,匹配用户给的 56.6% 示例);不可信/无数据分支不变。
context-window-trusted.test.ts 的 clamp pin 扩为同时断言"百分比 + 已用"格式。
验证:dev 应用热重载干净(✓ Compiled);context-window-trusted 8/8;typecheck(hook)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: 用户在运行的应用里看到 GLM-5-turbo(Claude Code/Native 会话)仍显示总上下文
200K,指出"这并不是我们知道的部分"。fix#1 本应让 catalog 静态值不可信、只显示已用。
Triage(当前源码,用户 review 驱动): agent-loop.ts:641-651(Native)在 token_usage
没有 context_window 时,从静态 catalog 填 totalUsage.context_window = getContextWindow(modelId)
(GLM-5-turbo 在 catalog 是 z.ai 核实的 202752)。而 context-usage-walk 把
token_usage.context_window 当作 SDK 实报窗口读,fix#1 的 contextWindowTrusted 据此判可信
→ catalog 猜测被"洗白"成可信 → Native GLM 显示 200K。即上游 mutator 打败了 helper 修复
(feedback_fix_all_consumers)。claude-client(Claude Code)只从 SDK modelUsage 写,不洗白;
ContextUsageIndicator 是死组件(无人 import)。
Fix: 删掉 agent-loop 的 catalog 洗白。Native 无 runtime 实报时 context_window 留空 →
useContextUsage 回落 catalog 为不可信 → 只显示已用绝对值,不再有假百分比/假总量。
仅对新 turn 生效(历史消息已存的 context_window 不改写,遵守不改用户数据;旧会话发新消息后转为已用-only)。
Verify: typecheck;context-window-trusted.test.ts 新增 pin 断言 agent-loop 不再
`.context_window = catalogWindow`;该文件 9 测 + agent-loop-error-event 全过。运行中 dev 应用
server 重编译干净(Native GLM 需发新消息验证)。
Guardrail: source-pin 防 Native 再把 catalog 洗进 SDK-authoritative 字段。
设计记录(用户批准"先记计划再实现"): v0.56.x 计划写入 context-window 来源优先级修订设计
(runtime 实报 > provider 配置 contextWindow > 压缩阈值 > catalog 不可信)+ 跨 Runtime 用户
配置源(#1,待实现) + 显示分母对齐压缩阈值(#3,待实现)。本提交是设计第一步(去洗白)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
把"为什么 GLM 显示 200K + 窗口来源该怎么改"写成评审稿放进 v0.56.x Phase 2,按
外部事实 / 本地证据(file:line) / 推断与设计三层分写,供 Codex 核实。
要点:
- Agent SDK v0.2.111 的 modelUsage.contextWindow(sdk.d.ts:945)是未文档化字段,来自
SDK 内置模型目录而非 API;第一方可靠、第三方(经 base_url 的 GLM)返回通用默认值;
无 SDK 设置可覆盖;Anthropic 建议自维护窗口表。
- 实测 GLM 会话 token_usage.context_window=200000 ≠ 本地 catalog 202752,证实来自 SDK
默认而非 catalog/Native 洗白;该会话是 Claude Code(故上一提交的 Native 修复不覆盖它)。
- 修订设计:窗口来源优先级 = 用户覆盖 > 已核实 catalog/provider 配置 > SDK(仅第一方) >
只显示已用;第三方忽略 SDK 默认值;跨 Runtime;显示分母对齐压缩阈值(#3)。
- 列出待定决策(已核实优先 vs 纯手动) + 给 Codex 的 5 个核实点。
未改任何产品代码(纯文档)。#1/#3 实现待 Codex 核实后进行。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Codex 复核设计稿后订正(实现 #1/#3 前必须):
- A:原"官方文档不记载 contextWindow/maxOutputTokens"不准 → 改为 SDK TypeScript
reference 有字段定义,是 cost-tracking 指南未解释来源/可信度。
- B/C:原"catalog 202752 比 SDK 200000 更准且 z.ai 核实"站不住 → z.ai 官方写
200K/128K,catalog 该条来源存疑;结论收敛为"SDK 200000 不可作为 provider 实报采信",
不延伸到"catalog 更准";另标记需单独核 model-context.ts:42 的真实来源。
- D + 决策日志:统一优先级(消除冲突,旧决策日志把第三方 SDK 又洗白成可信)→
用户手动覆盖 > provider/model 配置且来源已验证 > 第一方 runtime 实报 > 只显示已用;
第三方 SDK contextWindow 默认不可信、无明确来源 catalog 不当可信%显示。
- "Anthropic 官方建议自维护表"未核到原文 → 降级为工程结论。
- 澄清:用户实际看到 200K 的 GLM 会话是 Claude Code(SDK 默认 200000),非 Native 洗白
路径(681706b 的 Native 修复有效但治另一条路径)。
- E:决策收敛为一条基线 + 剩余一项请用户定(第一方 SDK 实报是否自动显示百分比)。
Codex 核为真的部分(sdk.d.ts:945 字段、代码写入 token_usage、历史 SDK 窗口被当可信、
Native 洗白已去、显示分母 vs 压缩阈值脱节)保留。纯文档,未动产品代码。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
F 段核实点 #1 还残留旧"官方文档未记载(A)",与已订正的 A 段不一致。改为:
sdk.d.ts:945 的 contextWindow/maxOutputTokens 存在,SDK TypeScript reference 已列,
只是 cost-tracking 指南未解释来源/可信度。纯文档。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
… Phase 2 ①)
Signal: 用户 GLM-5-turbo(Claude Code 经代理)显示总上下文 200K,且 Codex 核实 SDK 的
modelUsage.contextWindow 来自 SDK 内置目录、对第三方是通用默认值、无 SDK 设置可覆盖。
Triage: claude-client.ts extractTokenUsage 把 SDK modelUsage.contextWindow 无条件写入
token_usage.context_window;walk + fix#1 据此判可信 → 第三方代理(GLM)的 SDK 默认 200000
被当可信显示。Native 的 catalog 洗白已于 681706b 去掉;本提交补 SDK 路径。
Fix(Codex 统一口径"第一方 runtime 实报可信、第三方不可信"):
- ai-provider.ts 导出 isFirstPartyAnthropicEndpoint(baseUrl)(空/anthropic.com → 第一方)。
- extractTokenUsage 增 trustContextWindow,仅 true 时写 context_window;两个调用点都传
isFirstPartyAnthropicEndpoint(resolved.provider?.base_url)。第三方(自定义 base_url,如 GLM)
→ 不写 context_window → useContextUsage 回落 catalog 为不可信 → 只显示已用。
效果 + 边界: 第一方 Anthropic 继续显示百分比+已用;第三方代理新 turn 起只显示已用。
仅对新写入生效(历史消息已存的 context_window 不改写,遵守不改用户数据);现有 GLM 会话
仍显示旧值,需新会话/新 turn 验证(walk 会读历史,故旧会话需自然滚动出旧窗口或新建)。
Verify: typecheck;extract-token-usage-context-window.test.ts 增 2 pin(gate + 两调用点传
第一方判别);全量 3371/3371。
Guardrail: source-pin 钉死 context_window 写入受 trustContextWindow 门控 + 两调用点必须传
isFirstPartyAnthropicEndpoint,防回退到无条件信任第三方 SDK 窗口。
remaining(Phase 2 ①/③ 未完): provider/model 配置窗口作为最高优先可信源(用户覆盖) + 渲染层
对现有会话按第一方 gate(治旧会话) + #3 显示分母对齐压缩阈值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
计划文档状态审计修正(决策日志准、但概览层过期):
- frontmatter 状态行:📋 待接手 → 🚧 Phase 0/1 已完成、Phase 2 进行中。
- 「状态总览」表:Phase 1 待开始 → ✅ 已完成(2026-06-19);Phase 2 待开始 → 🚧 进行中。
- Phase 2 加进度 note:Composer/Context 主链路 #1#5 全部收口(含 commit + #3 真实
Codex 冒烟回复 circle);Session/Stream cluster #629/#635 + 终态原因码 + 压缩回滚
+ 诊断导出字段待续。
- Phase 2 执行清单 4 项已完成项 [ ]→[x](上下文 UI 语义 / context-cost 去阻断 /
Codex 多模态发送 / 发送后草稿清理)。
CLAUDE.md 执行计划段新增「完成即回写进度(与 Codex 对齐协作)」:任一 Phase/子项做完
必须立即回写三处且一致——执行清单勾选 / 状态总览表+frontmatter / 决策日志(commit
+验证结论);Claude 实施+回写、Codex 审查+维护;三者不一致视为状态失真须先对齐。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
打回上一条状态同步的一处失真:我把 #4/#5「发送后内容残留」标成完成(checklist [x] +
进度 note 列为 done),但同一文档决策日志(2026-06-20 条)已写明用户再次确认"内容已发出
但文本仍残留输入框"、#615 source-pin 不覆盖该症状、不能算闭环——状态表/清单与决策日志
自相矛盾,违反刚加的"三者必须一致"。
修正(与决策日志对齐):
- checklist「复现并修发送后内容残留」[x] → [ ],标注"待复核/待修复(用户 2026-06-20 再报)"。
- Phase 2 进度 note:拆分——#4/#5 仅失败保留有基础修复(#615),发送成功后文本残留待复核;
note 标题从"主链路已收口"改为"#1#3 收口、#4/#5 待复核";待续列表补回 #4/#5(重新打开)。
- #2 context-cost 非阻断保持完成(checklist [x] + note)不变。
后续修 #4/#5 时重点:PromptInput 受控/非受控清空边界、setInputValue('') 与
controller.textInput.clear() 是否同源、成功 accepted 后 remount/local draft 恢复、
badge/confirm/image 分支与普通 Enter 分支是否一致(决策日志已记排查方向)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
按"完成即回写进度"规则同步三处:
- checklist「复现并修发送后内容残留」[ ]→[x],标注已修 + CDP 验证 + 根因/修法(58c7aad)。
- Phase 2 进度 note:#1#5 全部落地;#4/#5 从"待复核"改为"已定位+修复"(含根因/CDP 结论);
待续列表移除 #4/#5、只留 Session/Stream cluster。
- 决策日志加同日条目:CDP 埋点定位 = 首条消息 accept 布局翻转 remount composer、inputValue
从 sessionStorage 草稿重读;修法 = accept 处清草稿;3401/3401 + CDP 文本/图文首条 800ms 即清。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
用户在浏览器实测不残留、仅桌面 App 残留 → Claude 协助完整重启 electron:dev(kill 整棵
进程树 + 释放 3000 + 后台重启)→ 用户在重启后真实 App 验证发送即清空 → #4/#5 闭环。
根因:58c7aad(page.tsx accept 处清首条草稿)一直是对的;用户残留是 Electron dev 没把
page.tsx 改动热更新进 renderer、窗口刷新无效,得整进程重启。这解释了全程「Claude CDP
浏览器清、用户残留」的矛盾——不是 Electron 行为差异,是构建新鲜度差异(Claude 浏览器硬刷
过有修复、用户 Electron 旧构建没有)。
回写:checklist [x](用户真实 App 验证)、进度 note #1#5 全闭环、验收去 ⚠️、决策日志加
闭环条目 + 教训(UI 修复在桌面 App 验证必须整重启 electron:dev)。Codex P1(prefill/
initialValue 回灌)仍是 58c7aad 的真实独立漏洞、值得单独补,与本次残留无关。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
纯文档同步,无代码改动。目的:让下一个进程打开文档时不从旧状态误判进度。
三处状态表此前已标 Phase 0/1 ✅、决策日志也已确认完成,唯独执行清单 checkbox
与 README 索引、issue-tracker #632 仍停在旧值——三处不一致即状态失真,本次对齐。
README.md:
- v0.56.x 索引行状态列 "📋 待 Phase 0 收束" → "🚧 Phase 0/1 ✅;Phase 2 进行中
(Composer/Context 主链路 #1#5 闭环,Session/Stream cluster #629/#635 待续)",
追上 plan frontmatter 与决策日志。
v0.56.x-stability-trust.md:
- Phase 0 执行清单 8 项 [ ]→[x],逐条带回溯(3360/3360、9c6e772、f99edbb/d00449f)。
A2 计时器项如实标注:按 keyed-remount 构造性消除 + 截图不可判别记录入 Smoke Ledger,
非逐帧视觉确认(反假数据,不谎称做了视觉确认)。
- Phase 1 执行清单 5 项 [ ]→[x],带回溯(milestone #1 / 9 labels / .github/TRIAGE.md)。
issue-tracker.md:
- #632 状态 "🔴 待修" → "🟡 假%已修,item3 分母对齐待续"。核心显示 bug(假百分比/>100%)
已由 effective-base-URL 写入 gate + 渲染期 trusted gate + clamp 修复并经真实 GLM
会话验证;item3(显示分母对齐压缩阈值)是独立待续阶段,故标部分修复而非已修复。
- 顶部"最后更新"同步到 2026-06-26 + #632 同步说明。
验证:git diff 确认仅 3 文档、16/16 行 checkbox 与状态文字,无代码/意外文件。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jul 4, 2026
- docs/research/ai-sdk-7-toolloop-parity-gaps.md: 新增「Phase 5 处置」节,全部 gap
收口——P1×3 关闭(#1/#2 补偿由 parity 8/8 复跑锁定;#3 降级论证:Phase 4 已证
approval HMAC 不需要 SDK toolApproval 停机语义,维持 in-execute 路线),
P2/P3 关闭或 backlog(#4/#5 列为替换路线前置条件,#7 归档 tech-debt #49#8 有 Phase 5 新实证)
- scripts/smoke-ai-sdk7-phase5-decision.ts: 新增决策门对照 smoke——prod runAgentLoop
与 POC runToolLoopAgentPoc 用同一 AgentLoopOptions 逐场景对照(长文本 / approval
批准 / approval 拒绝 / abort→continue),机械比较归一化事件序列 + 尾部契约 +
usage 存在性;DB 只读、数据目录隔离、输出全 scrub。探针注意:approval 批准分支
用 printf(echo 命中 permission-checker 自动放行规则不会触发 ask)
- docs/exec-plans/active/_smoke-evidence/ai-sdk7-phase5-decision-smoke.json:
OpenRouter 真实渠道 4/4 场景 contractMatch=true(input_tokens 逐场景完全相同,
tool_result 逐字相同,中断轮双侧 done 收尾、同 session 续发一次通过);
凭据形态 grep=0
- docs/research/ai-sdk-7-adoption-decision.md: 新增采用决策文档——结论 partial
(依赖升级 go / provider 能力 capability-gated go / Phase 4 外围能力 go /
@ai-sdk/mcp 与默认 loop 替换 no-go-现在),四层 rollback plan(能力开关→
wrapper→runtime switch→known-good version),每项结论标注 Phase 1-5 证据来源;
默认 Runtime 切换留人类闸门
- docs/exec-plans/tech-debt-tracker.md: 新增 #49(tool-error part 被两条 loop
一致吞掉的既有 UX 债,独立于采用决策)
- docs/exec-plans/active/ai-sdk-7-runtime-loop-adoption.md: Phase 5 状态回写 +
决策日志 + Smoke Ledger / Loop Ledger 各一行
- docs/research/README.md: 索引新增决策文档条目
验证: npm run test 3598/3598 全绿;smoke 4/4 contractMatch(1 个 fix cycle 收敛,
两处均为脚本层问题非 loop 差异);src/ 零改动(默认 Runtime/聊天路径零变化)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jul 4, 2026
用户批准 partial(2026-07-04, run issue #10): 采用 ai@7/@ai-sdk/* 依赖升级、
provider 参数能力 capability-gated、openai-chat image wrapper、timeout 原因码/
approval HMAC/trace 脱敏四件套(默认值经用户确认); @ai-sdk/mcp adapter 与
ToolLoopAgent 默认 loop 替换均不采用(留实验路径)。发版前保留官方一方 key
smoke gate。冲突仅 ai-sdk-7 计划决策日志一处,union 双方条目解决。
五个 phase 全部经 hands-off loop 完成并 Codex accepted(issues #1/#6/#7/#8/#10)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ion for Native Runtime
Two feature gaps where Native Runtime didn't match SDK Runtime, both
surfaced during post-hermes-upgrade manual testing:
── op7418#1: Compression notification now human-readable ──
Before: chat/route.ts:402 emitted `message: 'context_compressed'` as
a machine string. useSSEStream's notification branch showed this raw
string in the status bar — users saw "context_compressed" flash by.
After: message is now `"Context compressed: N older messages summarized,
~X tokens saved"` with structured `stats: { messagesCompressed, tokensSaved }`
for future rich UI handling. Added `subtype: 'context_compressed'` for
dedicated frontend handlers.
── op7418#3: AskUserQuestion tool for Native Runtime ──
Before: only SDK Runtime had AskUserQuestion (built into Claude Code CLI).
Native Runtime had no such tool, so the model could never ask structured
questions — the existing AskUserQuestionUI in PermissionPrompt.tsx was
unreachable dead UI code for Native Runtime users.
After:
- New builtin tool `src/lib/builtin-tools/ask-user-question.ts`
registered in index.ts, condition 'always'
- Zod schema: 1-6 questions, each with 1-6 options, optional multiSelect
- Execute receives answers from permission flow (injected by frontend)
and formats as Q/A pairs for the model
- permission-checker.ts: new ALWAYS_ASK_TOOLS set ensures AskUserQuestion
(and ExitPlanMode) always show UI even in trust mode — without this,
trust mode would auto-approve and return empty answers
- PermissionPrompt.tsx: NEVER_AUTO_APPROVE set prevents full_access mode
from auto-approving AskUserQuestion — the UI must render so the user
can answer
The data flow:
Model → AskUserQuestion({ questions }) → permission wrapper intercepts
→ SSE permission_request → frontend AskUserQuestionUI renders
→ user picks options → updatedInput({ questions, answers }) → tool
execute formats answers → model gets "Q: ... A: ..." string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ge generation results
GPT-Image-2.0 skill silent failure had two compounding causes both
on the 'tool result' loop:
P0 op7418#1 — function_call_output translated with sentinel toolName
translate-input.ts wrote toolName: '__from_responses_proxy__' for every
tool-result and the comment claimed 'ai-sdk doesn't use this for
routing'. That was wrong. Anthropic and OpenAI Responses both look
up the tool definition by tool-result.toolName when reconciling the
result with the request's tool surface; with a sentinel they can't
correlate and refuse to produce the continuation turn — exactly the
'tool ran, no follow-up text' the user saw.
Fix: walk the input array once first to build call_id → toolName
from function_call items, then look up the real name when translating
function_call_output. Orphan results (no matching function_call) fall
back to a named sentinel '__orphan_function_call_output__' AND emit
console.warn naming the call_id. The divergence stays loud.
P0 op7418#2 — imageGeneration / imageView silently dropped
event-mapper.ts had both item types in CHAT_ONLY_ITEM_TYPES, which
returns null on item/started + item/completed. That set is correct
for agentMessage/plan/reasoning (they have streaming delta channels
so the content arrives separately), but imageGeneration / imageView
have NO delta channel — their final item is the only surface where
the result reaches the user. Silent drop meant 'tool ran' with no
visible image.
Fix: move both types to TOOL_LIKE_ITEM_TYPES, add explicit
translateItemStarted branches with names image_generation /
image_view, and the existing TOOL_LIKE_ITEM_TYPES completion branch
already packs the full item into output — preserving result,
savedPath, revisedPrompt, path for chat-side rendering.
ThreadItemLike grew matching fields so TS doesn't downgrade access
to (item as { path?: string }).path casts.
Tests (8 new)
src/__tests__/unit/codex-proxy-translators.test.ts (+3):
- toolName resolves from matching function_call (gpt_image_2 case)
- toolName resolves correctly with interleaved out-of-order calls
- orphan function_call_output → named sentinel + console.warn
src/__tests__/unit/codex-event-mapper.test.ts (+4):
- imageGeneration item/started → tool_started(name='image_generation')
- imageGeneration item/completed → tool_completed with full
result + savedPath + revisedPrompt payload
- imageView item/started → tool_started(name='image_view') + path
- imageView item/completed → tool_completed with path preserved
src/__tests__/unit/codex-proxy-tool-contract.test.ts (+1):
- End-to-end continuation: function_call → function_call_output →
streamText(messages) — MockLanguageModelV3 must see toolName
'gpt_image_2' in its prompt, NOT '__from_responses_proxy__'.
Continuation text-delta event fires.
The mapper-side translate also removed the chatOnly array's
imageView / imageGeneration entries from the old 'returns null'
parameterised test; replaced with the new lifecycle describe block.
Closeout doc records round 7 ✅ items; remaining must-haves
unchanged (4-family smoke matrix + codex-sdk POC).
All 2416 tests pass (was 2412 + 8 new − 4 obsolete from the chatOnly
table for imageView/imageGeneration).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ce 2a
Direction approved; three sharpenings folded into the existing
Phase 2 plan structure without restructuring.
1. Widget wire-format single source (review revision op7418#1)
slice 7's WIDGET_SYSTEM_PROMPT template-literal-embeds
WIDGET_WIRE_FORMAT_SPEC. With artifactContracts ordered BEFORE
capabilityFragments in the compiler, the wire spec would land in
the final system prompt twice (once from artifactContract, once
from the capability fragment tail). The plan now declares hard
constraints — CANONICAL_SHOW_WIDGET_JSON, the "FINAL OUTPUT
FORMAT" title, and WIDGET_WIRE_FORMAT_SPEC each must appear
exactly once in the compiled system prompt — and assigns slice
2c a small refactor that strips the wire spec from
WIDGET_SYSTEM_PROMPT so artifactContract becomes the sole holder.
Compile-time sanity check (capability fragment text MUST NOT
contain artifactContract.canonicalJson) added as a defence-in-
depth FAIL path.
2. Expected Differences Ledger (review revision op7418#2)
2b's "compiler output === Runtime current prompt" stance
directly conflicted with slice 2d's plan to canonicalize Native
memory / notify / media-import paraphrases. Equivalence reading
strictly would have locked the old drift in. Plan now introduces
`src/lib/harness/expected-differences.ts` with typed entries
(runtimeId, capability, diff kind, justification,
plannedResolution, compilerSource, runtimeSource). 2b harness
reads "compiler vs runtime diff ⊆ ledger"; unregistered
differences fail. Initial ledger seeded with the four known
Phase 5c slice 7b tech-debt items, three earmarked for slice 2d
and one (image_generation MediaBlock shape) earmarked
follow_up. Slice 2d completion = manual ledger entry removal
(deliberate non-automation, preserves audit trail).
3. runtimeHints boundary (review revision op7418#3)
Plan tightens the runtimeHints type declaration so it cannot
become a fourth prompt-assembly point. Allowed: IDs (mcp server
names, tool keys, builtin tool name set), fragmentIds refs into
CompiledContext, adapter options (stopWhen / stepCount /
passthroughToolTypes). Forbidden: any prompt text string, tool
description paraphrase, capability redefinition. Three test
layers — type-level (string fields ≤ 64 chars, no newline / no
markdown), runtime-level (no template-literal-shaped values),
source-grep level (no multi-line template literals in
runtimeHints assignments) — plus a dangling-reference check
that every fragmentId in runtimeHints resolves in
CompiledContext.
Regression test list extended 9 → 12. Decision log records all
three revisions with rationale.
Plan still in 📋 status. No code; awaiting Codex re-review on the
revised draft, then slice 2a opens.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
User mode change: "internal slice order preserved, external single
delivery; stop only after Phase 2 is done; Codex review takes the
batch." This commit lands slices 2a–2e together with all post-
review hardenings (Widget wire-format single source, Expected
Differences Ledger, runtimeHints prose ban).
Internal slice walk
2a — context-compiler.ts (NEW)
Pure function `compileContext(input): CompiledContext`. No IO,
no provider calls. Resolves enabledCapabilities (null = catalog
live default), looks up exposure for the calling runtime, emits
capabilityFragments + artifactContracts + memory + workspace +
toolDescriptors + runtimeHints + budget + systemPromptText +
diagnostics. Hard contracts: artifactContract before capability
in the assembled prompt; fragmentId uniqueness; cross-runtime
fragment text identity; compile-time FAIL if a capability
fragment text contains an artifact contract canonicalJson
(wire-format dedup); compile-time FAIL if load-bearing fragments
exceed budget. runtimeHints types strictly ID/refs/adapter
options — no prose, no template literals.
2b — expected-differences.ts (NEW)
Drift ledger. Initial 4 entries from slice 7b tech-debt. Three
slice_2d entries consumed by this commit (see 2d below); the
one remaining `follow_up` is image_generation MediaBlock shape
(non-prompt, future slice).
2c — ClaudeCode SDK (claude-client.ts) source-pin only
The SDK path has always imported MCP canonicals directly
(memory-search-mcp, notification-mcp, media-import-mcp,
cli-tools-mcp, dashboard-mcp) — no paraphrase ever existed.
Slice 2c codifies this with a contract test: claude-client.ts
must not import capability prompts from builtin-tools/* and
must not declare its own _SYSTEM_PROMPT scalars.
2d — Native Runtime (builtin-tools/*) re-export MCP canonicals
`memory-search.ts` now `export const MEMORY_SEARCH_SYSTEM_PROMPT =
CANONICAL_MEMORY_SEARCH_SYSTEM_PROMPT` (imported from
memory-search-mcp.ts). Same pattern for `notification.ts`
(NOTIFICATION_SYSTEM_PROMPT = NOTIFICATION_MCP_SYSTEM_PROMPT)
and `media.ts` (MEDIA_SYSTEM_PROMPT = MEDIA_MCP_SYSTEM_PROMPT
from media-import-mcp.ts). Three ledger entries removed in
sync.
2e — Codex bridge (builtin-bridge.ts + unified-adapter.ts)
Bridge no longer holds WIDGET_PROMPT / MEDIA_PROMPT /
MEMORY_PROMPT / NOTIFY_PROMPT scalars (all four declarations
deleted). `createCodePilotBuiltinTools().systemPrompt` is
permanently `''`. `unified-adapter.ts` now calls
`compileContext({ runtimeId: 'codex_runtime', ... })` and feeds
`compiled.systemPromptText` to Codex's `instructions`. A new
helper `capabilitiesFromBridgeToolNames` maps the bridge's
mounted tool names back to capability ids so the compiler's
enabledCapabilities aligns with what the bridge actually
exposes (workspace-gated memory tools naturally drop out when
workspacePath is empty).
Slice 2c Widget wire-format single source (review revision op7418#1)
WIDGET_SYSTEM_PROMPT in widget-guidelines.ts no longer
template-literal-embeds `${WIDGET_WIRE_FORMAT_SPEC}`. The
artifactContract is now the sole holder of the wire-format spec
+ canonical JSON. Compiler's `detectWireFormatDuplication` sanity
check throws at compile time if any capability fragment text
contains the artifact contract canonicalJson — that's the forcing
function preventing the spec from being re-injected.
Three regression pins enforce single occurrence in the compiled
prompt: CANONICAL_SHOW_WIDGET_JSON × 1, "FINAL OUTPUT FORMAT —
non-negotiable" × 1, WIDGET_WIRE_FORMAT_SPEC × 1.
runtimeHints boundary (review revision op7418#3)
ClaudeCodeHints / NativeHints / CodexProxyHints types now carry
only IDs (mcp server names, tool keys, builtin tool name set) +
adapter options (stopWhen, stepCount, passthroughToolTypes).
Tests pin: type-level (no string field > 64 chars, no newline,
no Markdown markers), runtime-level (scan all string values for
prose), source-grep (CodexProxyHints type definition can't
contain `promptOverride` / `promptExtra` / `widgetPrompt` / etc).
Tests
New harness-context-compiler.test.ts (23 pins): catalog hygiene,
Widget wire-format single source (op7418#10), ordering, budget
enforcement, cross-runtime fragment identity (op7418#9), tool
descriptors, runtimeHints boundary (op7418#11), Expected Differences
Ledger consistency (op7418#12), JSON parseability of every artifact
contract.
New harness-context-compiler-equivalence.test.ts (9 pins):
compiler source reachability, runtime drift honesty,
ledger/slice ownership correctness, "post-slice-2d: Native
ledger holds only the follow_up MediaBlock entry".
Updated harness-capability-contract.test.ts: drift pins now
check (a) bridge holds no local _PROMPT scalars, (b) Native
builtin-tools re-export MCP canonicals, (c) unified-adapter
imports compileContext + consumes systemPromptText, (d)
claude-client.ts doesn't import from builtin-tools/* and
doesn't declare own _SYSTEM_PROMPT.
Updated codex-widget-format-contract.test.ts: the "WIDGET_SYSTEM_PROMPT
embeds WIDGET_WIRE_FORMAT_SPEC" and "appears inside
WIDGET_SYSTEM_PROMPT" pins are flipped — slice 2c REMOVED the
embed; the new pins verify the compiler-side import line.
Updated codex-builtin-bridge.test.ts: tests previously asserting
`bridge.systemPrompt` contained capability tags now assert it
equals `''` (bridge is no longer the prompt-assembly point).
Verification
CODEX_DISABLED=1 npx tsx --test \
src/__tests__/unit/harness-context-compiler.test.ts \
src/__tests__/unit/harness-context-compiler-equivalence.test.ts \
src/__tests__/unit/harness-capability-contract.test.ts \
src/__tests__/unit/codex-widget-format-contract.test.ts \
src/__tests__/unit/codex-builtin-bridge.test.ts
→ 74/74 pass
npm run test → 2576/2576 pass
Completion criteria check (per user spec)
[x] npm run test all green (2576/2576)
[x] Context Compiler unit tests all green
[x] equivalence / expected-diff harness all green
[x] harness-capability-contract / codex-widget-format /
codex-builtin-bridge tests all green
[x] no new runtime-local prompt duplicates (Native re-exports
canonical; ClaudeCode imports canonical; bridge holds none)
[x] Codex bridge no longer holds WIDGET_PROMPT / MEDIA_PROMPT /
MEMORY_PROMPT / NOTIFY_PROMPT scalars (all four removed,
drift test pins their absence)
[x] all three Runtimes adapt compiler output, none redefine
capability prompts
Docs
- phase-5d-phase-2-context-compiler.md: slice statuses 2a–2e all
✅ 2026-05-17; note the one-shot delivery mode change.
- phase-5d-harness-capability-contract.md: Phase 2 row ✅, awaiting
Codex review.
- handover/harness-capability-contract.md: new "Context Compiler"
section detailing inputs/outputs/constraints, three-runtime
consumption pattern, Expected Differences Ledger contract.
- refactor-closeout.md: new decision-log entry recording the
Phase 2 delivery shape + completion criteria check.
Phase 5d Phase 2 ✅ pending Codex review. Phase 3 (Runtime
Capability Adapter) / Phase 4 (Artifact Contract) / Phase 5
(new-Runtime Playbook) intentionally NOT opened — stopping per
user instruction.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
… to breakdown
## 用户视角
升级前:popover 的"文件与附件 / 本次待加入"两行永远 0 —— 数据通道没接通。即使 composer 里挂了 4 个 mention 和 2 个目录引用,popover breakdown 显示 0。
升级后:MessageInput → ChatView/page → RunCockpit → useContextUsage → buildContextUsageBreakdown 全链路联通。composer 里的 attachment / mention / directory 实时累加到对应类别。trigger 上的迷你点阵 + popover 主条 + 列表行三处同步更新。
发送消息后 pending 归 0;下一轮 history 里的真实 token_usage 接管 used 部分;conversation 类自动吸收。
## 不做什么
- 不改 hook 其他字段(used / ratio / state / source 等不动)
- 不改 trigger 主结构(百分比文字仍在;只有点阵 cells 在分配时反映 pending)
- 不改 composer text 估算(composerTextTokens 仍 0;那是 Phase 3+ 的事)
## 怎么验收
- npm run test → 2921/2921 pass
- composer 里加附件 / @mention / "+" 目录 → trigger 上 pending 部分立刻有虚线 cells
- 发送消息 → pending 归零;下轮 used cells 更新
## 改动(6 文件)
### src/lib/message-input-logic.ts
新增 `PendingContextSubTotals` interface + `computePendingContextSubTotals()` 函数。逻辑 mirror `computePendingContextTokens`(同样的 null 过滤、同样的迭代顺序),但返回 { attachment, mention, directory } 三键。两个函数加起来 = 等于 computePendingContextTokens 总数。
### src/hooks/useContextUsage.ts
options 加可选 `pending?: { attachmentTokens?, mentionTokens?, directoryTokens?, composerTextTokens? }`。三条返回路径(snapshot / walk / noData)都把 options?.pending 转发给 buildContextUsageBreakdown。useMemo deps 数组加 options?.pending。
### src/components/chat/RunCockpit.tsx
RunCockpitProps 加可选 `pendingContextSubTotals?: { attachment, mention, directory }`。组件内部把它转换成 hook options.pending 形态(attachment → attachmentTokens 等)。可选 prop 默认 undefined → 不破坏现有 callsites。
### src/components/chat/MessageInput.tsx
- import 加 computePendingContextSubTotals + PendingContextSubTotals type
- props 加可选 `onPendingContextSubTotalsChange?` callback(跟现有 onPendingContextTokensChange 并列)
- 新增 useMemo 算 pendingContextSubTotals + useEffect emit callback
- 与现有 pendingContextTokens 走同一份 source 数据,逻辑同步无 divergence
### src/components/chat/ChatView.tsx
- 加 state `pendingContextSubTotals` (PendingContextSubTotals | undefined)
- MessageInput 上 wire `onPendingContextSubTotalsChange={setPendingContextSubTotals}`
- RunCockpit 上传 `pendingContextSubTotals={pendingContextSubTotals}`
### src/app/chat/page.tsx
- 跟 ChatView 完全镜像:state + MessageInput callback + RunCockpit prop
- 两个入口独立持有 state(按 StreamSession guardrail 不变量 op7418#1)
## Scope discipline
- 不新增测试(Codex 负责测试覆盖;用户分工已明确)
- 不动 buildContextUsageBreakdown / computePendingContextTokens 既有签名 → 旧调用 zero-risk
- 不改 chat-static-graph 排除清单 → MessageInput / RunCockpit 改动属于增量 prop,没新依赖链
- composerTextTokens 仍未 wire(composer 纯文本估算属于未来扩展,pending_next_turn 行暂时仍 0)
## StreamSession guardrail 合规
- 双入口(page.tsx 首消息 + ChatView 后续)独立 state — 不变量 op7418#1 ✅
- onSend / onCommand 签名不变 — rewind point 不变量 op7418#2 ✅
- 不动 capability cache — 不变量 op7418#3 ✅
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…18#31)
Codex review second round caught two real P1 inconsistencies introduced by
the Dashboard/CLI split slice plus non-blocking contract drift.
P1.1 — Dashboard injection gate ≠ route auth gate.
runtime.ts injected the dashboard read/write MCPs whenever prompt + working
directory + dashboard keyword matched, but the route's `authorize` requires
`sameRealPath(workspacePath, assistant_workspace_path)`. Mismatch → the model
sees the tool and Codex 403s at call time. Fix: dashboard injection mirrors
memory's gate exactly (same sameRealPath check, same `assistantWorkspacePath`
passed as `workspacePath`) so "inject" and "route-authorize" never disagree.
CLI tools don't need this (no workspace scope).
P1.2 — Matrix promoted only for codex_account; runtime injects for ALL
codex_runtime providers.
The runtime didn't gate injection by provider, so under a CodePilot proxy
provider the dashboard/cli MCPs WERE injected (callable), but the matrix
returned `perception_only` for non-codex_account — the opposite drift from
P1.1 ("model says yes, Settings says no"). Fix per Codex's preferred option:
move the promotion into `capabilityMatrixForRuntime` so it applies to ALL
codex_runtime providers; `capabilityMatrixForRuntimeProvider` now only adds
codex_account-specific overrides (native notes + image/media demotion).
`buildCapabilityMatrix` delegates to `capabilityMatrixForRuntime` so every
matrix entry point stays aligned.
Non-blocking op7418#1 — contract text drift.
capability-contract.ts dashboard/cli `deferredReason` + `codex_proxy.notes`
rewritten — explicit that the LEGACY provider-proxy bridge is unsupported
(true), and that the codex_runtime path now ships via the mutation-level MCP
split + matrix-layer promotion. No schema changes (`kind: 'unsupported'`
stays accurate for the legacy bridge surface); the existing matrix invariant
test gets a `MATRIX_LAYER_PROMOTIONS` exception list documenting why the two
promoted cells are allowed to be executable despite `kind: 'unsupported'`.
Schema cleanup (introduce a new `mcp_server_split` kind, drop the exception
list) tracked as tech-debt op7418#33.
Non-blocking op7418#2 — elicitation policy pins.
codex-mcp-events.test.ts now pins all 4 new server names:
codepilot_{dashboard,cli_tools}_read → auto_accept,
codepilot_{dashboard,cli_tools}_write → user_approval.
Also added a regression guard: `codex_runtime + non-codex_account provider`
must STILL show dashboard/cli_tools executable with mixed trust + the right
noteKey. Updated the two pre-existing tests that asserted the OLD behaviour
(dashboard/cli perception_only on codex_runtime) — they now assert the
promoted state. Also synced the static `CAPABILITY_EXECUTABLE_RUNTIMES` map.
Per Codex review's explicit ask: the "待真账号 smoke" wording stays in the
op7418#31 capability table — this commit fixes the inconsistencies, but the
real-account end-to-end smoke for natural-conversation triggering + write
approval card + Deny blocking is still owed by the user.
Full unit suite 3045/3045. Live route: bad workspace still 403 (auth gate
intact); tools/list subsets unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Codex review 认可方向,按 5 条反馈修订(纯文档,无代码):
- Phase A 增"开工前核验"(Opus 4.8 官方 model id / context window / thinking·effort / 1M beta,不臆测)
- Phase A 实现范围增"泛化 Opus 4.7 专属逻辑"(isOpus47Model / OPUS_4_7_PATTERN / applyContext1mBeta /
effort 门控 / claude-client sanitizer,配回归测试)—— catalog 显示 ≠ 请求正确
- OpenRouter Opus 4.8 改 deferred(不臆测 slug),首轮只接 Anthropic direct
- opus 别名 / 默认先不动(仍 4.7),只新增显式 claude-opus-4-8,切换待 smoke 后用户拍板
- Phase D 拆 D0/D:D0 把 apply-discovery-diff 全量 flake + no-verify 事件记入 tech-debt op7418#30(本提交即 D0);
D 建议先于 A/B/C,代码 phase 不再靠 --no-verify
- Open Questions op7418#1/op7418#2 据上述决议收敛
本提交纯文档;pre-commit 同样因 apply-discovery-diff 全量 flake 用 --no-verify,已确认 docs-drift 绿。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
v0.56.x 计划 Phase 1:建立稳定性治理入口,并用当前源码重新核验 Notion/issue 列出的
7 个 issue(不采信 issue 自述根因)。
GitHub 侧(已在仓库生效,非本 commit 内容):
- 创建 milestone op7418#1「v0.56.x Stability / Trust」。
- 创建 9 个治理 label:P0-crash-or-interrupt / P0-data-loss-risk / P1-runtime-session /
P1-context / P1-file-reference / P1-installer-update / P1-performance / needs-repro /
v0.57+ parking-lot。
- 给 op7418#626/op7418#628/op7418#629/op7418#632/op7418#633/op7418#634/op7418#635 按复核结论打 milestone + 优先级 label。
本 commit 文件:
- .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml:bug 表单强制必填
版本/OS/runtime/provider-model/可复现/复现步骤/期望vs实际 + 影响面勾选;feature
表单注明 v0.56.x 冻结新功能 → v0.57+ parking-lot;config 关闭空白 issue + 冻结说明
与 Discussions 入口。
- .github/PULL_REQUEST_TEMPLATE.md:Summary / Repro+root cause / Changes / Tests /
Screenshots-logs / 自查清单(链到 CLAUDE.md 与 AGENTS.md,不复制维护)。
- .github/TRIAGE.md:对外冻结说明、label 体系、issue/PR triage 规则、自动化候选。
- v0.56.x-stability-trust.md:标 Phase 0 完成 + 新增「2026-06-19 Claude Code 源码复核」
表(7 issue 逐条 file:line 证据)。关键复核结论:
* op7418#632 ">100%" 确认是未 clamp 的 ratio*100 显示 bug(RunCockpit.tsx:169 等),分母
contextWindow 不可靠;"跨会话串" 源码不成立。
* op7418#629 空 assistant 已防护,残留真实 gap:is_error result 路径不清坏 sdk_session_id
(claude-client.ts:1908 先置 resultEmitted)。
* op7418#635 截图-only,最强候选 = SDK runtime 无自生成 keepalive(claude-client.ts:1956),
慢 proxy 静默 >330s 被 idle abort(B-019)。
* op7418#628 确认真实风险:@file origin path 在 MessageInput.tsx:161 丢失,body.mentions[]
送达但 route.ts 从不消费 → 写 .codepilot-uploads 副本,AI 改副本。
* op7418#634 根因不成立——5 个 notify/schedule 工具均注册(builtin-tools/index.ts:250),
issue 引用的 UI 串不在当前源码(疑旧版);附带 Plan 模式 list_tasks 泄漏。
* op7418#626 polling 排除(8h 间隔),候选 animate-pulse × backdrop-filter 重绘。
* op7418#633 mac 无法复现;NSIS-only + 未签名 + 无 portable + CI 不验安装启动。
- issue-tracker.md:新增「v0.56.x 治理 issue」看板索引表(指向 plan 复核表,不重复分析)。
验证:docs-drift 通过;npm run test(hook)。Phase 1 验收(milestone/labels/模板/冻结
说明就绪)达成。下一步 Phase 2:按复核结论修 chat 主链路(上下文百分比语义、context-cost
不阻断发送、Codex 多模态发送、发送后清草稿)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…e 2 op7418#1)
Signal: issue op7418#632 报"上下文 >100% / 假百分比 / 压缩后跳变";Phase 1 源码复核确认是
真实显示 bug("跨会话串"不成立)。
Triage(当前源码): 用量百分比 = usage.ratio*100,在 RunCockpit.tsx 与
RunCockpitPopoverContent.tsx 两处直接渲染、未封顶;usage.ratio = used / contextWindow,
而 contextWindow 来自 sdkContextWindow ?? latestSdkContextWindow ?? catalogContextWindow
(useContextUsage.ts)。很多第三方 proxy 不上报 context_window → 落到静态 catalog 兜底
(一个猜测值),used 又会在压缩后跳变 → 百分比蹦到 200%/500%。根因是"拿不可信的分母
算百分比",不是上下文真的超了。
Fix:
- useContextUsage.ts: 新增 ContextUsageData.contextWindowTrusted —— 仅当 SDK/上游真实
上报窗口时为 true(catalog 兜底不算)。三个 return 分支(baseline / snapshot / no-baseline)
都按各自来源正确赋值。不可信时不把窗口喂给 buildContextUsageBreakdown,dot-matrix 退回
按已用 token 的构成比例,不编造容量。
- RunCockpit.tsx: hasFullCtx 增加 && usage.contextWindowTrusted —— 不可信时自动落到既有的
绝对已用 token 显示(触发按钮)/ showUnknownCapacityBlock 分支(浮层,已测试的"容量未知"
路径)。百分比文案 clamp ≤100%。
- RunCockpitPopoverContent.tsx: 浮层 header 百分比同样 clamp ≤100%(防可信窗口被 used 短暂
超过时仍蹦 >100%)。
语义验收: 输入框右下角不可信时只显示已用绝对值;浮层不可信时只显示已用 + 不同种类构成
比例(无百分比/remaining/unused/假总量);可信时百分比封顶 100%。
Verify: typecheck 通过;context-window-trusted.test.ts 6 条 source-pin + 既有
run-cockpit-unknown-capacity / context-dot-matrix / context-usage-walk / context-breakdown
全绿;全量单测 3366/3366。未做:真实 untrusted-window provider 会话的 CDP 视觉走查
(fix 把 untrusted 路由到既有已发布的"容量未知"分支,风险低;视觉走查列为后续)。
Guardrail: context-window-trusted.test.ts 钉死 trusted 派生只认 SDK 来源、不可信时不喂窗口、
hasFullCtx 必须 gate trusted、两处显示 clamp ≤100%,防回退到"拿 catalog 当真实分母算百分比"。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Signal: Codex 复核 fixop7418#1(9ea29a4)后发现 P2 残留——文字已改成"只显示已用 token",
但输入框右下角触发按钮旁的 mini dot-bar 仍用 200K 兜底画出"用了多少/还剩多少"的容量
暗示,与"拿不到总长度就不显示容量"及 commit message 的"不编造容量"不一致。
Triage(当前源码): ContextDotMatrix.tsx 有 FALLBACK_CONTEXT_WINDOW=200_000,
minCellsPerKind=0(mini-bar)在窗口未知时用它当分母(:88);RunCockpit.tsx:200 的触发
按钮无条件渲染这个 mini-bar。所以即使 9ea29a4 把文字降级为绝对已用,小条仍画假容量。
minCellsPerKind=0 全仓只有 RunCockpit 触发按钮一个调用方。
Fix:
- RunCockpit.tsx: mini-bar 用 {hasFullCtx && (...)} 包裹——仅在可信窗口下渲染容量小条;
不可信时触发按钮只剩绝对已用 token 文本(贴合"输入框右下角只显示已用数值")。
- ContextDotMatrix.tsx: 删除 FALLBACK_CONTEXT_WINDOW(200K)。窗口未知时两种模式都按
used+pending 分配(构成视图,非容量%),不再编造容量。
Verify: typecheck 通过;context-dot-matrix.test.ts 旧的"unknown mini-bar 用 200K 兜底
(filled<=2)"语义改为新的"used 构成(filled>=8)";context-window-trusted.test.ts 加 2 条
guardrail(mini-bar gate 在 hasFullCtx + 源码无 200K 兜底残留);全量单测 3368/3368。
Guardrail: 两条 source-pin 钉死"触发按钮 mini-bar 必须 gate 在 hasFullCtx"且"ContextDotMatrix
不得再出现 FALLBACK_CONTEXT_WINDOW/200_000",防回退到拿假容量画小条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户复核 fixop7418#1 后明确显示格式:输入框右下角的上下文小标,在有可信窗口时显示
"百分比 + 已用上下文"(如 56.6% 452K),没有可信窗口时只显示已用(如 452K),
不单列"剩余"数字。
改动:RunCockpit.tsx 触发按钮 ratioText 的可信分支由 "{pct}%" 改为
"{pct}% {used}"(1 位小数,匹配用户给的 56.6% 示例);不可信/无数据分支不变。
context-window-trusted.test.ts 的 clamp pin 扩为同时断言"百分比 + 已用"格式。
验证:dev 应用热重载干净(✓ Compiled);context-window-trusted 8/8;typecheck(hook)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…llow-up)
Signal: 用户在运行的应用里看到 GLM-5-turbo(Claude Code/Native 会话)仍显示总上下文
200K,指出"这并不是我们知道的部分"。fixop7418#1 本应让 catalog 静态值不可信、只显示已用。
Triage(当前源码,用户 review 驱动): agent-loop.ts:641-651(Native)在 token_usage
没有 context_window 时,从静态 catalog 填 totalUsage.context_window = getContextWindow(modelId)
(GLM-5-turbo 在 catalog 是 z.ai 核实的 202752)。而 context-usage-walk 把
token_usage.context_window 当作 SDK 实报窗口读,fixop7418#1 的 contextWindowTrusted 据此判可信
→ catalog 猜测被"洗白"成可信 → Native GLM 显示 200K。即上游 mutator 打败了 helper 修复
(feedback_fix_all_consumers)。claude-client(Claude Code)只从 SDK modelUsage 写,不洗白;
ContextUsageIndicator 是死组件(无人 import)。
Fix: 删掉 agent-loop 的 catalog 洗白。Native 无 runtime 实报时 context_window 留空 →
useContextUsage 回落 catalog 为不可信 → 只显示已用绝对值,不再有假百分比/假总量。
仅对新 turn 生效(历史消息已存的 context_window 不改写,遵守不改用户数据;旧会话发新消息后转为已用-only)。
Verify: typecheck;context-window-trusted.test.ts 新增 pin 断言 agent-loop 不再
`.context_window = catalogWindow`;该文件 9 测 + agent-loop-error-event 全过。运行中 dev 应用
server 重编译干净(Native GLM 需发新消息验证)。
Guardrail: source-pin 防 Native 再把 catalog 洗进 SDK-authoritative 字段。
设计记录(用户批准"先记计划再实现"): v0.56.x 计划写入 context-window 来源优先级修订设计
(runtime 实报 > provider 配置 contextWindow > 压缩阈值 > catalog 不可信)+ 跨 Runtime 用户
配置源(op7418#1,待实现) + 显示分母对齐压缩阈值(op7418#3,待实现)。本提交是设计第一步(去洗白)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
把"为什么 GLM 显示 200K + 窗口来源该怎么改"写成评审稿放进 v0.56.x Phase 2,按
外部事实 / 本地证据(file:line) / 推断与设计三层分写,供 Codex 核实。
要点:
- Agent SDK v0.2.111 的 modelUsage.contextWindow(sdk.d.ts:945)是未文档化字段,来自
SDK 内置模型目录而非 API;第一方可靠、第三方(经 base_url 的 GLM)返回通用默认值;
无 SDK 设置可覆盖;Anthropic 建议自维护窗口表。
- 实测 GLM 会话 token_usage.context_window=200000 ≠ 本地 catalog 202752,证实来自 SDK
默认而非 catalog/Native 洗白;该会话是 Claude Code(故上一提交的 Native 修复不覆盖它)。
- 修订设计:窗口来源优先级 = 用户覆盖 > 已核实 catalog/provider 配置 > SDK(仅第一方) >
只显示已用;第三方忽略 SDK 默认值;跨 Runtime;显示分母对齐压缩阈值(op7418#3)。
- 列出待定决策(已核实优先 vs 纯手动) + 给 Codex 的 5 个核实点。
未改任何产品代码(纯文档)。op7418#1/op7418#3 实现待 Codex 核实后进行。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Codex 复核设计稿后订正(实现 op7418#1/op7418#3 前必须):
- A:原"官方文档不记载 contextWindow/maxOutputTokens"不准 → 改为 SDK TypeScript
reference 有字段定义,是 cost-tracking 指南未解释来源/可信度。
- B/C:原"catalog 202752 比 SDK 200000 更准且 z.ai 核实"站不住 → z.ai 官方写
200K/128K,catalog 该条来源存疑;结论收敛为"SDK 200000 不可作为 provider 实报采信",
不延伸到"catalog 更准";另标记需单独核 model-context.ts:42 的真实来源。
- D + 决策日志:统一优先级(消除冲突,旧决策日志把第三方 SDK 又洗白成可信)→
用户手动覆盖 > provider/model 配置且来源已验证 > 第一方 runtime 实报 > 只显示已用;
第三方 SDK contextWindow 默认不可信、无明确来源 catalog 不当可信%显示。
- "Anthropic 官方建议自维护表"未核到原文 → 降级为工程结论。
- 澄清:用户实际看到 200K 的 GLM 会话是 Claude Code(SDK 默认 200000),非 Native 洗白
路径(f79fd54 的 Native 修复有效但治另一条路径)。
- E:决策收敛为一条基线 + 剩余一项请用户定(第一方 SDK 实报是否自动显示百分比)。
Codex 核为真的部分(sdk.d.ts:945 字段、代码写入 token_usage、历史 SDK 窗口被当可信、
Native 洗白已去、显示分母 vs 压缩阈值脱节)保留。纯文档,未动产品代码。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
F 段核实点 op7418#1 还残留旧"官方文档未记载(A)",与已订正的 A 段不一致。改为:
sdk.d.ts:945 的 contextWindow/maxOutputTokens 存在,SDK TypeScript reference 已列,
只是 cost-tracking 指南未解释来源/可信度。纯文档。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…#632 / Phase 2 ①)
Signal: 用户 GLM-5-turbo(Claude Code 经代理)显示总上下文 200K,且 Codex 核实 SDK 的
modelUsage.contextWindow 来自 SDK 内置目录、对第三方是通用默认值、无 SDK 设置可覆盖。
Triage: claude-client.ts extractTokenUsage 把 SDK modelUsage.contextWindow 无条件写入
token_usage.context_window;walk + fixop7418#1 据此判可信 → 第三方代理(GLM)的 SDK 默认 200000
被当可信显示。Native 的 catalog 洗白已于 f79fd54 去掉;本提交补 SDK 路径。
Fix(Codex 统一口径"第一方 runtime 实报可信、第三方不可信"):
- ai-provider.ts 导出 isFirstPartyAnthropicEndpoint(baseUrl)(空/anthropic.com → 第一方)。
- extractTokenUsage 增 trustContextWindow,仅 true 时写 context_window;两个调用点都传
isFirstPartyAnthropicEndpoint(resolved.provider?.base_url)。第三方(自定义 base_url,如 GLM)
→ 不写 context_window → useContextUsage 回落 catalog 为不可信 → 只显示已用。
效果 + 边界: 第一方 Anthropic 继续显示百分比+已用;第三方代理新 turn 起只显示已用。
仅对新写入生效(历史消息已存的 context_window 不改写,遵守不改用户数据);现有 GLM 会话
仍显示旧值,需新会话/新 turn 验证(walk 会读历史,故旧会话需自然滚动出旧窗口或新建)。
Verify: typecheck;extract-token-usage-context-window.test.ts 增 2 pin(gate + 两调用点传
第一方判别);全量 3371/3371。
Guardrail: source-pin 钉死 context_window 写入受 trustContextWindow 门控 + 两调用点必须传
isFirstPartyAnthropicEndpoint,防回退到无条件信任第三方 SDK 窗口。
remaining(Phase 2 ①/③ 未完): provider/model 配置窗口作为最高优先可信源(用户覆盖) + 渲染层
对现有会话按第一方 gate(治旧会话) + op7418#3 显示分母对齐压缩阈值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
计划文档状态审计修正(决策日志准、但概览层过期):
- frontmatter 状态行:📋 待接手 → 🚧 Phase 0/1 已完成、Phase 2 进行中。
- 「状态总览」表:Phase 1 待开始 → ✅ 已完成(2026-06-19);Phase 2 待开始 → 🚧 进行中。
- Phase 2 加进度 note:Composer/Context 主链路 op7418#1op7418#5 全部收口(含 commit + op7418#3 真实
Codex 冒烟回复 circle);Session/Stream cluster op7418#629/op7418#635 + 终态原因码 + 压缩回滚
+ 诊断导出字段待续。
- Phase 2 执行清单 4 项已完成项 [ ]→[x](上下文 UI 语义 / context-cost 去阻断 /
Codex 多模态发送 / 发送后草稿清理)。
CLAUDE.md 执行计划段新增「完成即回写进度(与 Codex 对齐协作)」:任一 Phase/子项做完
必须立即回写三处且一致——执行清单勾选 / 状态总览表+frontmatter / 决策日志(commit
+验证结论);Claude 实施+回写、Codex 审查+维护;三者不一致视为状态失真须先对齐。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
打回上一条状态同步的一处失真:我把 op7418#4/op7418#5「发送后内容残留」标成完成(checklist [x] +
进度 note 列为 done),但同一文档决策日志(2026-06-20 条)已写明用户再次确认"内容已发出
但文本仍残留输入框"、op7418#615 source-pin 不覆盖该症状、不能算闭环——状态表/清单与决策日志
自相矛盾,违反刚加的"三者必须一致"。
修正(与决策日志对齐):
- checklist「复现并修发送后内容残留」[x] → [ ],标注"待复核/待修复(用户 2026-06-20 再报)"。
- Phase 2 进度 note:拆分——op7418#4/op7418#5 仅失败保留有基础修复(op7418#615),发送成功后文本残留待复核;
note 标题从"主链路已收口"改为"op7418#1op7418#3 收口、op7418#4/op7418#5 待复核";待续列表补回 op7418#4/op7418#5(重新打开)。
- op7418#2 context-cost 非阻断保持完成(checklist [x] + note)不变。
后续修 op7418#4/op7418#5 时重点:PromptInput 受控/非受控清空边界、setInputValue('') 与
controller.textInput.clear() 是否同源、成功 accepted 后 remount/local draft 恢复、
badge/confirm/image 分支与普通 Enter 分支是否一致(决策日志已记排查方向)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
按"完成即回写进度"规则同步三处:
- checklist「复现并修发送后内容残留」[ ]→[x],标注已修 + CDP 验证 + 根因/修法(de123df)。
- Phase 2 进度 note:op7418#1op7418#5 全部落地;op7418#4/op7418#5 从"待复核"改为"已定位+修复"(含根因/CDP 结论);
待续列表移除 op7418#4/op7418#5、只留 Session/Stream cluster。
- 决策日志加同日条目:CDP 埋点定位 = 首条消息 accept 布局翻转 remount composer、inputValue
从 sessionStorage 草稿重读;修法 = accept 处清草稿;3401/3401 + CDP 文本/图文首条 800ms 即清。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户在浏览器实测不残留、仅桌面 App 残留 → Claude 协助完整重启 electron:dev(kill 整棵
进程树 + 释放 3000 + 后台重启)→ 用户在重启后真实 App 验证发送即清空 → op7418#4/op7418#5 闭环。
根因:de123df(page.tsx accept 处清首条草稿)一直是对的;用户残留是 Electron dev 没把
page.tsx 改动热更新进 renderer、窗口刷新无效,得整进程重启。这解释了全程「Claude CDP
浏览器清、用户残留」的矛盾——不是 Electron 行为差异,是构建新鲜度差异(Claude 浏览器硬刷
过有修复、用户 Electron 旧构建没有)。
回写:checklist [x](用户真实 App 验证)、进度 note op7418#1op7418#5 全闭环、验收去 ⚠️、决策日志加
闭环条目 + 教训(UI 修复在桌面 App 验证必须整重启 electron:dev)。Codex P1(prefill/
initialValue 回灌)仍是 de123df 的真实独立漏洞、值得单独补,与本次残留无关。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
纯文档同步,无代码改动。目的:让下一个进程打开文档时不从旧状态误判进度。
三处状态表此前已标 Phase 0/1 ✅、决策日志也已确认完成,唯独执行清单 checkbox
与 README 索引、issue-tracker op7418#632 仍停在旧值——三处不一致即状态失真,本次对齐。
README.md:
- v0.56.x 索引行状态列 "📋 待 Phase 0 收束" → "🚧 Phase 0/1 ✅;Phase 2 进行中
(Composer/Context 主链路 op7418#1op7418#5 闭环,Session/Stream cluster op7418#629/op7418#635 待续)",
追上 plan frontmatter 与决策日志。
v0.56.x-stability-trust.md:
- Phase 0 执行清单 8 项 [ ]→[x],逐条带回溯(3360/3360、dd4ead4、b853188/2de9c2b)。
A2 计时器项如实标注:按 keyed-remount 构造性消除 + 截图不可判别记录入 Smoke Ledger,
非逐帧视觉确认(反假数据,不谎称做了视觉确认)。
- Phase 1 执行清单 5 项 [ ]→[x],带回溯(milestone op7418#1 / 9 labels / .github/TRIAGE.md)。
issue-tracker.md:
- op7418#632 状态 "🔴 待修" → "🟡 假%已修,item3 分母对齐待续"。核心显示 bug(假百分比/>100%)
已由 effective-base-URL 写入 gate + 渲染期 trusted gate + clamp 修复并经真实 GLM
会话验证;item3(显示分母对齐压缩阈值)是独立待续阶段,故标部分修复而非已修复。
- 顶部"最后更新"同步到 2026-06-26 + op7418#632 同步说明。
验证:git diff 确认仅 3 文档、16/16 行 checkbox 与状态文字,无代码/意外文件。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
- docs/research/ai-sdk-7-toolloop-parity-gaps.md: 新增「Phase 5 处置」节,全部 gap
收口——P1×3 关闭(op7418#1/op7418#2 补偿由 parity 8/8 复跑锁定;op7418#3 降级论证:Phase 4 已证
approval HMAC 不需要 SDK toolApproval 停机语义,维持 in-execute 路线),
P2/P3 关闭或 backlog(op7418#4/op7418#5 列为替换路线前置条件,op7418#7 归档 tech-debt op7418#49op7418#8 有 Phase 5 新实证)
- scripts/smoke-ai-sdk7-phase5-decision.ts: 新增决策门对照 smoke——prod runAgentLoop
与 POC runToolLoopAgentPoc 用同一 AgentLoopOptions 逐场景对照(长文本 / approval
批准 / approval 拒绝 / abort→continue),机械比较归一化事件序列 + 尾部契约 +
usage 存在性;DB 只读、数据目录隔离、输出全 scrub。探针注意:approval 批准分支
用 printf(echo 命中 permission-checker 自动放行规则不会触发 ask)
- docs/exec-plans/active/_smoke-evidence/ai-sdk7-phase5-decision-smoke.json:
OpenRouter 真实渠道 4/4 场景 contractMatch=true(input_tokens 逐场景完全相同,
tool_result 逐字相同,中断轮双侧 done 收尾、同 session 续发一次通过);
凭据形态 grep=0
- docs/research/ai-sdk-7-adoption-decision.md: 新增采用决策文档——结论 partial
(依赖升级 go / provider 能力 capability-gated go / Phase 4 外围能力 go /
@ai-sdk/mcp 与默认 loop 替换 no-go-现在),四层 rollback plan(能力开关→
wrapper→runtime switch→known-good version),每项结论标注 Phase 1-5 证据来源;
默认 Runtime 切换留人类闸门
- docs/exec-plans/tech-debt-tracker.md: 新增 op7418#49(tool-error part 被两条 loop
一致吞掉的既有 UX 债,独立于采用决策)
- docs/exec-plans/active/ai-sdk-7-runtime-loop-adoption.md: Phase 5 状态回写 +
决策日志 + Smoke Ledger / Loop Ledger 各一行
- docs/research/README.md: 索引新增决策文档条目
验证: npm run test 3598/3598 全绿;smoke 4/4 contractMatch(1 个 fix cycle 收敛,
两处均为脚本层问题非 loop 差异);src/ 零改动(默认 Runtime/聊天路径零变化)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户批准 partial(2026-07-04, run issue op7418#10): 采用 ai@7/@ai-sdk/* 依赖升级、
provider 参数能力 capability-gated、openai-chat image wrapper、timeout 原因码/
approval HMAC/trace 脱敏四件套(默认值经用户确认); @ai-sdk/mcp adapter 与
ToolLoopAgent 默认 loop 替换均不采用(留实验路径)。发版前保留官方一方 key
smoke gate。冲突仅 ai-sdk-7 计划决策日志一处,union 双方条目解决。
五个 phase 全部经 hands-off loop 完成并 Codex accepted(issues op7418#1/op7418#6/op7418#7/op7418#8/op7418#10)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
canblmz1 pushed a commit to canblmz1/CodePilot that referenced this pull request Aug 28, 2026
…lease
prefix-safe-json 0.2.0 -> 0.4.3 (exact). 0.4.3 is a security patch
(GHSA-3xpw-9694-2xxp) fixing three root causes in the AI SDK adapter/gate
this integration depends on:
1. AiSdkStreamAdapter.push() used to silently drop every raw event once
it had already observed its own terminal, so late/contradictory
evidence for a call never reached the coordinator at all.
2. takeDecision() used to read a decision snapshot frozen at finish()
time instead of the coordinator's live diagnostics, so evidence
recorded after finish() but before that call's authority was consumed
was never consulted.
3. A raw event carrying conflicting id/toolCallId used to silently
prefer id instead of failing the stream closed.
No public API change - createAiSdkExecutionGuard()/push()/finish()/
takeDecision() and the ExecuteDecision/NonExecutableDecision shapes this
integration reads (action, toolCallId, reason) are unchanged, confirmed
directly against the installed package's .d.ts, not assumed.
Verified against the real 0.4.3 install (resolved version, and lockfile
integrity hash, both confirmed exactly 0.4.3):
- npx tsc --noEmit (full project): clean, 0 errors.
- src/__tests__/unit/execution-guard.test.ts: 16/16 passing, identical
to the 0.2.0 result.
Adds src/__tests__/unit/execution-guard-post-terminal-authority.test.ts,
answering the actual question this bump exists to answer: does this
integration's own code exercise the fix, not just "does the library
still pass its own tests." resolvePendingExecutions() in
execution-guard.ts reads `decisions` directly off guard.finish()'s own
return value in the same statement - it never calls takeDecision().
A fresh guard is created per step and is never reused once its finish()
is read, so there is no async gap between this integration's own
finish() call and its own decision consumption for GHSA-3xpw-9694-2xxp's
literal finish()-to-takeDecision() window to open in here.
What is live in this integration is root cause op7418#1: whether a
late/contradicting raw event that arrives before a step's own
resolvePendingExecutions() call - anywhere in that step's fullStream -
correctly revokes authority instead of being silently dropped by the
adapter. The new test proves that directly, through this repo's real
execution-guard.ts functions (createStepGuard/registerDeferredExecution/
resolvePendingExecutions - the exact call path agent-loop.ts uses), plus
a control case confirming the fix does not overcorrect a genuinely clean
step. A second test exercises the raw prefix-safe-json library
(createAiSdkExecutionGuard directly, real push/finish/takeDecision, no
synthetic decision object) to confirm the literal advisory scenario is
fixed at the library level.
package-lock.json regenerated with `npm install prefix-safe-json@0.4.3
--save-exact`, not hand-edited.
Sign up for freeto 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.

2 participants

@xuxu777xu@op7418
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat: Windows platform adaptation by xuxu777xu · Pull Request #1 · op7418/CodePilot · GitHub
Skip to content

feat: Windows platform adaptation - #1

Merged
op7418 merged 2 commits into
op7418:mainfrom
xuxu777xu:feat/windows-drive-switcher
Feb 7, 2026
Merged

feat: Windows platform adaptation#1
op7418 merged 2 commits into
op7418:mainfrom
xuxu777xu:feat/windows-drive-switcher

Conversation

@xuxu777xu

@xuxu777xuxuxu777xu commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

Summary

CodePilot 原本仅支持 macOS,本 PR 添加完整的 Windows 平台适配,使其可以在 Windows 上正常构建、运行和使用。

Changes

跨平台基础设施

  • 新增 src/lib/platform.ts:统一的跨平台工具模块,包含 Claude CLI 发现逻辑(Windows .cmd/.bat shell 处理、where/which 回退)、PATH 扩展(AppData/npm 等 Windows 路径)
  • 重构 src/app/api/claude-status/route.ts:移除硬编码的 Unix 路径,改用共享的 platform 工具
  • 重构 src/lib/claude-client.ts:同上,并确保 USERPROFILE 和扩展 PATH 在 SDK 子进程中可用

Electron 主进程

  • electron/main.ts
    • Windows 进程派生使用 windowsHide 防止控制台窗口闪烁
    • PATH 构建适配 Windows 分隔符(;)和目录结构(AppData/npm)
    • 窗口标题栏适配:macOS hiddenInset / Windows hidden + titleBarOverlay
    • 图标适配:Windows 使用 .ico
    • loadUserShellEnv() 跳过非 macOS 平台

构建配置

  • electron-builder.yml:新增 win + nsis 构建目标,支持自定义安装目录、桌面/开始菜单快捷方式
  • package.json:新增 electron:pack:win 脚本,原 electron:pack 改为平台无关
  • build/icon.ico:Windows 应用图标

UI 适配

  • src/components/chat/FolderPicker.tsx:新增盘符下拉切换器,解决 Windows 盘符根目录无法向上导航的问题
  • src/app/api/files/browse/route.ts:API 返回可用 Windows 盘符列表
  • src/components/skills/SkillsManager.tsx:修复 key 重复警告

Test plan

  • Windows 上 npm run electron:pack:win 构建成功
  • 安装后启动,Claude CLI 自动检测并连接
  • 标题栏样式正确(隐藏标题栏 + overlay 控制按钮)
  • FolderPicker 盘符切换正常工作
  • macOS 上 npm run electron:pack:mac 构建无回归

🤖 Generated with Claude Code

xuxu777xuand others added 2 commits February 7, 2026 13:29
When navigating to a drive root on Windows (e.g. C:\), path.dirname
returns itself, disabling the "go up" button and trapping the user on
that drive. This adds a compact dropdown next to the up button that
lists all available drives (auto-detected via fs.accessSync), allowing
quick switching between drives. macOS/Linux are unaffected (empty array,
dropdown not rendered).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add src/lib/platform.ts: cross-platform Claude CLI discovery
(candidate paths, .cmd/.bat shell handling, where/which fallback)
- Refactor claude-status route and claude-client to use shared platform utils
- Electron main: Windows process spawning (windowsHide), PATH construction
with AppData/npm dirs, titleBarOverlay, .ico icon support
- electron-builder.yml: add win/nsis build targets
- package.json: add electron:pack:win script
- FolderPicker: drive switcher dropdown for navigating between drives
- SkillsManager: fix duplicate key warning with filePath fallback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@xuxu777xuxuxu777xu changed the title feat: add Windows drive switcher in FolderPickerfeat: Windows platform adaptationFeb 7, 2026
@op7418
op7418 merged commit b819eb7 into op7418:mainFeb 7, 2026
op7418 added a commit that referenced this pull request Apr 12, 2026
…ion for Native Runtime
Two feature gaps where Native Runtime didn't match SDK Runtime, both
surfaced during post-hermes-upgrade manual testing:
── #1: Compression notification now human-readable ──
Before: chat/route.ts:402 emitted `message: 'context_compressed'` as
a machine string. useSSEStream's notification branch showed this raw
string in the status bar — users saw "context_compressed" flash by.
After: message is now `"Context compressed: N older messages summarized,
~X tokens saved"` with structured `stats: { messagesCompressed, tokensSaved }`
for future rich UI handling. Added `subtype: 'context_compressed'` for
dedicated frontend handlers.
── #3: AskUserQuestion tool for Native Runtime ──
Before: only SDK Runtime had AskUserQuestion (built into Claude Code CLI).
Native Runtime had no such tool, so the model could never ask structured
questions — the existing AskUserQuestionUI in PermissionPrompt.tsx was
unreachable dead UI code for Native Runtime users.
After:
- New builtin tool `src/lib/builtin-tools/ask-user-question.ts`
registered in index.ts, condition 'always'
- Zod schema: 1-6 questions, each with 1-6 options, optional multiSelect
- Execute receives answers from permission flow (injected by frontend)
and formats as Q/A pairs for the model
- permission-checker.ts: new ALWAYS_ASK_TOOLS set ensures AskUserQuestion
(and ExitPlanMode) always show UI even in trust mode — without this,
trust mode would auto-approve and return empty answers
- PermissionPrompt.tsx: NEVER_AUTO_APPROVE set prevents full_access mode
from auto-approving AskUserQuestion — the UI must render so the user
can answer
The data flow:
Model → AskUserQuestion({ questions }) → permission wrapper intercepts
→ SSE permission_request → frontend AskUserQuestionUI renders
→ user picks options → updatedInput({ questions, answers }) → tool
execute formats answers → model gets "Q: ... A: ..." string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KevinYoung-Kw referenced this pull request in KevinYoung-Kw/CodePilot Apr 15, 2026
**补充修复**
在 #1 斜杠命令保留已有文本的修复基础上,进一步确保选择命令后光标自动定位到输入框尾部,而不是默认的首部。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KevinYoung-Kw referenced this pull request in KevinYoung-Kw/CodePilot Apr 15, 2026
**补充修复**
在 #1 斜杠命令保留已有文本的修复基础上,进一步确保选择命令后光标自动定位到输入框尾部,而不是默认的首部。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
v0.56.x 计划 Phase 1:建立稳定性治理入口,并用当前源码重新核验 Notion/issue 列出的
7 个 issue(不采信 issue 自述根因)。
GitHub 侧(已在仓库生效,非本 commit 内容):
- 创建 milestone #1「v0.56.x Stability / Trust」。
- 创建 9 个治理 label:P0-crash-or-interrupt / P0-data-loss-risk / P1-runtime-session /
P1-context / P1-file-reference / P1-installer-update / P1-performance / needs-repro /
v0.57+ parking-lot。
- 给 #626/#628/#629/#632/#633/#634/#635 按复核结论打 milestone + 优先级 label。
本 commit 文件:
- .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml:bug 表单强制必填
版本/OS/runtime/provider-model/可复现/复现步骤/期望vs实际 + 影响面勾选;feature
表单注明 v0.56.x 冻结新功能 → v0.57+ parking-lot;config 关闭空白 issue + 冻结说明
与 Discussions 入口。
- .github/PULL_REQUEST_TEMPLATE.md:Summary / Repro+root cause / Changes / Tests /
Screenshots-logs / 自查清单(链到 CLAUDE.md 与 AGENTS.md,不复制维护)。
- .github/TRIAGE.md:对外冻结说明、label 体系、issue/PR triage 规则、自动化候选。
- v0.56.x-stability-trust.md:标 Phase 0 完成 + 新增「2026-06-19 Claude Code 源码复核」
表(7 issue 逐条 file:line 证据)。关键复核结论:
* #632 ">100%" 确认是未 clamp 的 ratio*100 显示 bug(RunCockpit.tsx:169 等),分母
contextWindow 不可靠;"跨会话串" 源码不成立。
* #629 空 assistant 已防护,残留真实 gap:is_error result 路径不清坏 sdk_session_id
(claude-client.ts:1908 先置 resultEmitted)。
* #635 截图-only,最强候选 = SDK runtime 无自生成 keepalive(claude-client.ts:1956),
慢 proxy 静默 >330s 被 idle abort(B-019)。
* #628 确认真实风险:@file origin path 在 MessageInput.tsx:161 丢失,body.mentions[]
送达但 route.ts 从不消费 → 写 .codepilot-uploads 副本,AI 改副本。
* #634 根因不成立——5 个 notify/schedule 工具均注册(builtin-tools/index.ts:250),
issue 引用的 UI 串不在当前源码(疑旧版);附带 Plan 模式 list_tasks 泄漏。
* #626 polling 排除(8h 间隔),候选 animate-pulse × backdrop-filter 重绘。
* #633 mac 无法复现;NSIS-only + 未签名 + 无 portable + CI 不验安装启动。
- issue-tracker.md:新增「v0.56.x 治理 issue」看板索引表(指向 plan 复核表,不重复分析)。
验证:docs-drift 通过;npm run test(hook)。Phase 1 验收(milestone/labels/模板/冻结
说明就绪)达成。下一步 Phase 2:按复核结论修 chat 主链路(上下文百分比语义、context-cost
不阻断发送、Codex 多模态发送、发送后清草稿)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: issue #632 报"上下文 >100% / 假百分比 / 压缩后跳变";Phase 1 源码复核确认是
真实显示 bug("跨会话串"不成立)。
Triage(当前源码): 用量百分比 = usage.ratio*100,在 RunCockpit.tsx 与
RunCockpitPopoverContent.tsx 两处直接渲染、未封顶;usage.ratio = used / contextWindow,
而 contextWindow 来自 sdkContextWindow ?? latestSdkContextWindow ?? catalogContextWindow
(useContextUsage.ts)。很多第三方 proxy 不上报 context_window → 落到静态 catalog 兜底
(一个猜测值),used 又会在压缩后跳变 → 百分比蹦到 200%/500%。根因是"拿不可信的分母
算百分比",不是上下文真的超了。
Fix:
- useContextUsage.ts: 新增 ContextUsageData.contextWindowTrusted —— 仅当 SDK/上游真实
上报窗口时为 true(catalog 兜底不算)。三个 return 分支(baseline / snapshot / no-baseline)
都按各自来源正确赋值。不可信时不把窗口喂给 buildContextUsageBreakdown,dot-matrix 退回
按已用 token 的构成比例,不编造容量。
- RunCockpit.tsx: hasFullCtx 增加 && usage.contextWindowTrusted —— 不可信时自动落到既有的
绝对已用 token 显示(触发按钮)/ showUnknownCapacityBlock 分支(浮层,已测试的"容量未知"
路径)。百分比文案 clamp ≤100%。
- RunCockpitPopoverContent.tsx: 浮层 header 百分比同样 clamp ≤100%(防可信窗口被 used 短暂
超过时仍蹦 >100%)。
语义验收: 输入框右下角不可信时只显示已用绝对值;浮层不可信时只显示已用 + 不同种类构成
比例(无百分比/remaining/unused/假总量);可信时百分比封顶 100%。
Verify: typecheck 通过;context-window-trusted.test.ts 6 条 source-pin + 既有
run-cockpit-unknown-capacity / context-dot-matrix / context-usage-walk / context-breakdown
全绿;全量单测 3366/3366。未做:真实 untrusted-window provider 会话的 CDP 视觉走查
(fix 把 untrusted 路由到既有已发布的"容量未知"分支,风险低;视觉走查列为后续)。
Guardrail: context-window-trusted.test.ts 钉死 trusted 派生只认 SDK 来源、不可信时不喂窗口、
hasFullCtx 必须 gate trusted、两处显示 clamp ≤100%,防回退到"拿 catalog 当真实分母算百分比"。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: Codex 复核 fix#1(b842628)后发现 P2 残留——文字已改成"只显示已用 token",
但输入框右下角触发按钮旁的 mini dot-bar 仍用 200K 兜底画出"用了多少/还剩多少"的容量
暗示,与"拿不到总长度就不显示容量"及 commit message 的"不编造容量"不一致。
Triage(当前源码): ContextDotMatrix.tsx 有 FALLBACK_CONTEXT_WINDOW=200_000,
minCellsPerKind=0(mini-bar)在窗口未知时用它当分母(:88);RunCockpit.tsx:200 的触发
按钮无条件渲染这个 mini-bar。所以即使 b842628 把文字降级为绝对已用,小条仍画假容量。
minCellsPerKind=0 全仓只有 RunCockpit 触发按钮一个调用方。
Fix:
- RunCockpit.tsx: mini-bar 用 {hasFullCtx && (...)} 包裹——仅在可信窗口下渲染容量小条;
不可信时触发按钮只剩绝对已用 token 文本(贴合"输入框右下角只显示已用数值")。
- ContextDotMatrix.tsx: 删除 FALLBACK_CONTEXT_WINDOW(200K)。窗口未知时两种模式都按
used+pending 分配(构成视图,非容量%),不再编造容量。
Verify: typecheck 通过;context-dot-matrix.test.ts 旧的"unknown mini-bar 用 200K 兜底
(filled<=2)"语义改为新的"used 构成(filled>=8)";context-window-trusted.test.ts 加 2 条
guardrail(mini-bar gate 在 hasFullCtx + 源码无 200K 兜底残留);全量单测 3368/3368。
Guardrail: 两条 source-pin 钉死"触发按钮 mini-bar 必须 gate 在 hasFullCtx"且"ContextDotMatrix
不得再出现 FALLBACK_CONTEXT_WINDOW/200_000",防回退到拿假容量画小条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
用户复核 fix#1 后明确显示格式:输入框右下角的上下文小标,在有可信窗口时显示
"百分比 + 已用上下文"(如 56.6% 452K),没有可信窗口时只显示已用(如 452K),
不单列"剩余"数字。
改动:RunCockpit.tsx 触发按钮 ratioText 的可信分支由 "{pct}%" 改为
"{pct}% {used}"(1 位小数,匹配用户给的 56.6% 示例);不可信/无数据分支不变。
context-window-trusted.test.ts 的 clamp pin 扩为同时断言"百分比 + 已用"格式。
验证:dev 应用热重载干净(✓ Compiled);context-window-trusted 8/8;typecheck(hook)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: 用户在运行的应用里看到 GLM-5-turbo(Claude Code/Native 会话)仍显示总上下文
200K,指出"这并不是我们知道的部分"。fix#1 本应让 catalog 静态值不可信、只显示已用。
Triage(当前源码,用户 review 驱动): agent-loop.ts:641-651(Native)在 token_usage
没有 context_window 时,从静态 catalog 填 totalUsage.context_window = getContextWindow(modelId)
(GLM-5-turbo 在 catalog 是 z.ai 核实的 202752)。而 context-usage-walk 把
token_usage.context_window 当作 SDK 实报窗口读,fix#1 的 contextWindowTrusted 据此判可信
→ catalog 猜测被"洗白"成可信 → Native GLM 显示 200K。即上游 mutator 打败了 helper 修复
(feedback_fix_all_consumers)。claude-client(Claude Code)只从 SDK modelUsage 写,不洗白;
ContextUsageIndicator 是死组件(无人 import)。
Fix: 删掉 agent-loop 的 catalog 洗白。Native 无 runtime 实报时 context_window 留空 →
useContextUsage 回落 catalog 为不可信 → 只显示已用绝对值,不再有假百分比/假总量。
仅对新 turn 生效(历史消息已存的 context_window 不改写,遵守不改用户数据;旧会话发新消息后转为已用-only)。
Verify: typecheck;context-window-trusted.test.ts 新增 pin 断言 agent-loop 不再
`.context_window = catalogWindow`;该文件 9 测 + agent-loop-error-event 全过。运行中 dev 应用
server 重编译干净(Native GLM 需发新消息验证)。
Guardrail: source-pin 防 Native 再把 catalog 洗进 SDK-authoritative 字段。
设计记录(用户批准"先记计划再实现"): v0.56.x 计划写入 context-window 来源优先级修订设计
(runtime 实报 > provider 配置 contextWindow > 压缩阈值 > catalog 不可信)+ 跨 Runtime 用户
配置源(#1,待实现) + 显示分母对齐压缩阈值(#3,待实现)。本提交是设计第一步(去洗白)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
把"为什么 GLM 显示 200K + 窗口来源该怎么改"写成评审稿放进 v0.56.x Phase 2,按
外部事实 / 本地证据(file:line) / 推断与设计三层分写,供 Codex 核实。
要点:
- Agent SDK v0.2.111 的 modelUsage.contextWindow(sdk.d.ts:945)是未文档化字段,来自
SDK 内置模型目录而非 API;第一方可靠、第三方(经 base_url 的 GLM)返回通用默认值;
无 SDK 设置可覆盖;Anthropic 建议自维护窗口表。
- 实测 GLM 会话 token_usage.context_window=200000 ≠ 本地 catalog 202752,证实来自 SDK
默认而非 catalog/Native 洗白;该会话是 Claude Code(故上一提交的 Native 修复不覆盖它)。
- 修订设计:窗口来源优先级 = 用户覆盖 > 已核实 catalog/provider 配置 > SDK(仅第一方) >
只显示已用;第三方忽略 SDK 默认值;跨 Runtime;显示分母对齐压缩阈值(#3)。
- 列出待定决策(已核实优先 vs 纯手动) + 给 Codex 的 5 个核实点。
未改任何产品代码(纯文档)。#1/#3 实现待 Codex 核实后进行。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Codex 复核设计稿后订正(实现 #1/#3 前必须):
- A:原"官方文档不记载 contextWindow/maxOutputTokens"不准 → 改为 SDK TypeScript
reference 有字段定义,是 cost-tracking 指南未解释来源/可信度。
- B/C:原"catalog 202752 比 SDK 200000 更准且 z.ai 核实"站不住 → z.ai 官方写
200K/128K,catalog 该条来源存疑;结论收敛为"SDK 200000 不可作为 provider 实报采信",
不延伸到"catalog 更准";另标记需单独核 model-context.ts:42 的真实来源。
- D + 决策日志:统一优先级(消除冲突,旧决策日志把第三方 SDK 又洗白成可信)→
用户手动覆盖 > provider/model 配置且来源已验证 > 第一方 runtime 实报 > 只显示已用;
第三方 SDK contextWindow 默认不可信、无明确来源 catalog 不当可信%显示。
- "Anthropic 官方建议自维护表"未核到原文 → 降级为工程结论。
- 澄清:用户实际看到 200K 的 GLM 会话是 Claude Code(SDK 默认 200000),非 Native 洗白
路径(681706b 的 Native 修复有效但治另一条路径)。
- E:决策收敛为一条基线 + 剩余一项请用户定(第一方 SDK 实报是否自动显示百分比)。
Codex 核为真的部分(sdk.d.ts:945 字段、代码写入 token_usage、历史 SDK 窗口被当可信、
Native 洗白已去、显示分母 vs 压缩阈值脱节)保留。纯文档,未动产品代码。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
F 段核实点 #1 还残留旧"官方文档未记载(A)",与已订正的 A 段不一致。改为:
sdk.d.ts:945 的 contextWindow/maxOutputTokens 存在,SDK TypeScript reference 已列,
只是 cost-tracking 指南未解释来源/可信度。纯文档。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
… Phase 2 ①)
Signal: 用户 GLM-5-turbo(Claude Code 经代理)显示总上下文 200K,且 Codex 核实 SDK 的
modelUsage.contextWindow 来自 SDK 内置目录、对第三方是通用默认值、无 SDK 设置可覆盖。
Triage: claude-client.ts extractTokenUsage 把 SDK modelUsage.contextWindow 无条件写入
token_usage.context_window;walk + fix#1 据此判可信 → 第三方代理(GLM)的 SDK 默认 200000
被当可信显示。Native 的 catalog 洗白已于 681706b 去掉;本提交补 SDK 路径。
Fix(Codex 统一口径"第一方 runtime 实报可信、第三方不可信"):
- ai-provider.ts 导出 isFirstPartyAnthropicEndpoint(baseUrl)(空/anthropic.com → 第一方)。
- extractTokenUsage 增 trustContextWindow,仅 true 时写 context_window;两个调用点都传
isFirstPartyAnthropicEndpoint(resolved.provider?.base_url)。第三方(自定义 base_url,如 GLM)
→ 不写 context_window → useContextUsage 回落 catalog 为不可信 → 只显示已用。
效果 + 边界: 第一方 Anthropic 继续显示百分比+已用;第三方代理新 turn 起只显示已用。
仅对新写入生效(历史消息已存的 context_window 不改写,遵守不改用户数据);现有 GLM 会话
仍显示旧值,需新会话/新 turn 验证(walk 会读历史,故旧会话需自然滚动出旧窗口或新建)。
Verify: typecheck;extract-token-usage-context-window.test.ts 增 2 pin(gate + 两调用点传
第一方判别);全量 3371/3371。
Guardrail: source-pin 钉死 context_window 写入受 trustContextWindow 门控 + 两调用点必须传
isFirstPartyAnthropicEndpoint,防回退到无条件信任第三方 SDK 窗口。
remaining(Phase 2 ①/③ 未完): provider/model 配置窗口作为最高优先可信源(用户覆盖) + 渲染层
对现有会话按第一方 gate(治旧会话) + #3 显示分母对齐压缩阈值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
计划文档状态审计修正(决策日志准、但概览层过期):
- frontmatter 状态行:📋 待接手 → 🚧 Phase 0/1 已完成、Phase 2 进行中。
- 「状态总览」表:Phase 1 待开始 → ✅ 已完成(2026-06-19);Phase 2 待开始 → 🚧 进行中。
- Phase 2 加进度 note:Composer/Context 主链路 #1#5 全部收口(含 commit + #3 真实
Codex 冒烟回复 circle);Session/Stream cluster #629/#635 + 终态原因码 + 压缩回滚
+ 诊断导出字段待续。
- Phase 2 执行清单 4 项已完成项 [ ]→[x](上下文 UI 语义 / context-cost 去阻断 /
Codex 多模态发送 / 发送后草稿清理)。
CLAUDE.md 执行计划段新增「完成即回写进度(与 Codex 对齐协作)」:任一 Phase/子项做完
必须立即回写三处且一致——执行清单勾选 / 状态总览表+frontmatter / 决策日志(commit
+验证结论);Claude 实施+回写、Codex 审查+维护;三者不一致视为状态失真须先对齐。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
打回上一条状态同步的一处失真:我把 #4/#5「发送后内容残留」标成完成(checklist [x] +
进度 note 列为 done),但同一文档决策日志(2026-06-20 条)已写明用户再次确认"内容已发出
但文本仍残留输入框"、#615 source-pin 不覆盖该症状、不能算闭环——状态表/清单与决策日志
自相矛盾,违反刚加的"三者必须一致"。
修正(与决策日志对齐):
- checklist「复现并修发送后内容残留」[x] → [ ],标注"待复核/待修复(用户 2026-06-20 再报)"。
- Phase 2 进度 note:拆分——#4/#5 仅失败保留有基础修复(#615),发送成功后文本残留待复核;
note 标题从"主链路已收口"改为"#1#3 收口、#4/#5 待复核";待续列表补回 #4/#5(重新打开)。
- #2 context-cost 非阻断保持完成(checklist [x] + note)不变。
后续修 #4/#5 时重点:PromptInput 受控/非受控清空边界、setInputValue('') 与
controller.textInput.clear() 是否同源、成功 accepted 后 remount/local draft 恢复、
badge/confirm/image 分支与普通 Enter 分支是否一致(决策日志已记排查方向)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
按"完成即回写进度"规则同步三处:
- checklist「复现并修发送后内容残留」[ ]→[x],标注已修 + CDP 验证 + 根因/修法(58c7aad)。
- Phase 2 进度 note:#1#5 全部落地;#4/#5 从"待复核"改为"已定位+修复"(含根因/CDP 结论);
待续列表移除 #4/#5、只留 Session/Stream cluster。
- 决策日志加同日条目:CDP 埋点定位 = 首条消息 accept 布局翻转 remount composer、inputValue
从 sessionStorage 草稿重读;修法 = accept 处清草稿;3401/3401 + CDP 文本/图文首条 800ms 即清。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
用户在浏览器实测不残留、仅桌面 App 残留 → Claude 协助完整重启 electron:dev(kill 整棵
进程树 + 释放 3000 + 后台重启)→ 用户在重启后真实 App 验证发送即清空 → #4/#5 闭环。
根因:58c7aad(page.tsx accept 处清首条草稿)一直是对的;用户残留是 Electron dev 没把
page.tsx 改动热更新进 renderer、窗口刷新无效,得整进程重启。这解释了全程「Claude CDP
浏览器清、用户残留」的矛盾——不是 Electron 行为差异,是构建新鲜度差异(Claude 浏览器硬刷
过有修复、用户 Electron 旧构建没有)。
回写:checklist [x](用户真实 App 验证)、进度 note #1#5 全闭环、验收去 ⚠️、决策日志加
闭环条目 + 教训(UI 修复在桌面 App 验证必须整重启 electron:dev)。Codex P1(prefill/
initialValue 回灌)仍是 58c7aad 的真实独立漏洞、值得单独补,与本次残留无关。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
纯文档同步,无代码改动。目的:让下一个进程打开文档时不从旧状态误判进度。
三处状态表此前已标 Phase 0/1 ✅、决策日志也已确认完成,唯独执行清单 checkbox
与 README 索引、issue-tracker #632 仍停在旧值——三处不一致即状态失真,本次对齐。
README.md:
- v0.56.x 索引行状态列 "📋 待 Phase 0 收束" → "🚧 Phase 0/1 ✅;Phase 2 进行中
(Composer/Context 主链路 #1#5 闭环,Session/Stream cluster #629/#635 待续)",
追上 plan frontmatter 与决策日志。
v0.56.x-stability-trust.md:
- Phase 0 执行清单 8 项 [ ]→[x],逐条带回溯(3360/3360、9c6e772、f99edbb/d00449f)。
A2 计时器项如实标注:按 keyed-remount 构造性消除 + 截图不可判别记录入 Smoke Ledger,
非逐帧视觉确认(反假数据,不谎称做了视觉确认)。
- Phase 1 执行清单 5 项 [ ]→[x],带回溯(milestone #1 / 9 labels / .github/TRIAGE.md)。
issue-tracker.md:
- #632 状态 "🔴 待修" → "🟡 假%已修,item3 分母对齐待续"。核心显示 bug(假百分比/>100%)
已由 effective-base-URL 写入 gate + 渲染期 trusted gate + clamp 修复并经真实 GLM
会话验证;item3(显示分母对齐压缩阈值)是独立待续阶段,故标部分修复而非已修复。
- 顶部"最后更新"同步到 2026-06-26 + #632 同步说明。
验证:git diff 确认仅 3 文档、16/16 行 checkbox 与状态文字,无代码/意外文件。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jul 4, 2026
- docs/research/ai-sdk-7-toolloop-parity-gaps.md: 新增「Phase 5 处置」节,全部 gap
收口——P1×3 关闭(#1/#2 补偿由 parity 8/8 复跑锁定;#3 降级论证:Phase 4 已证
approval HMAC 不需要 SDK toolApproval 停机语义,维持 in-execute 路线),
P2/P3 关闭或 backlog(#4/#5 列为替换路线前置条件,#7 归档 tech-debt #49#8 有 Phase 5 新实证)
- scripts/smoke-ai-sdk7-phase5-decision.ts: 新增决策门对照 smoke——prod runAgentLoop
与 POC runToolLoopAgentPoc 用同一 AgentLoopOptions 逐场景对照(长文本 / approval
批准 / approval 拒绝 / abort→continue),机械比较归一化事件序列 + 尾部契约 +
usage 存在性;DB 只读、数据目录隔离、输出全 scrub。探针注意:approval 批准分支
用 printf(echo 命中 permission-checker 自动放行规则不会触发 ask)
- docs/exec-plans/active/_smoke-evidence/ai-sdk7-phase5-decision-smoke.json:
OpenRouter 真实渠道 4/4 场景 contractMatch=true(input_tokens 逐场景完全相同,
tool_result 逐字相同,中断轮双侧 done 收尾、同 session 续发一次通过);
凭据形态 grep=0
- docs/research/ai-sdk-7-adoption-decision.md: 新增采用决策文档——结论 partial
(依赖升级 go / provider 能力 capability-gated go / Phase 4 外围能力 go /
@ai-sdk/mcp 与默认 loop 替换 no-go-现在),四层 rollback plan(能力开关→
wrapper→runtime switch→known-good version),每项结论标注 Phase 1-5 证据来源;
默认 Runtime 切换留人类闸门
- docs/exec-plans/tech-debt-tracker.md: 新增 #49(tool-error part 被两条 loop
一致吞掉的既有 UX 债,独立于采用决策)
- docs/exec-plans/active/ai-sdk-7-runtime-loop-adoption.md: Phase 5 状态回写 +
决策日志 + Smoke Ledger / Loop Ledger 各一行
- docs/research/README.md: 索引新增决策文档条目
验证: npm run test 3598/3598 全绿;smoke 4/4 contractMatch(1 个 fix cycle 收敛,
两处均为脚本层问题非 loop 差异);src/ 零改动(默认 Runtime/聊天路径零变化)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jul 4, 2026
用户批准 partial(2026-07-04, run issue #10): 采用 ai@7/@ai-sdk/* 依赖升级、
provider 参数能力 capability-gated、openai-chat image wrapper、timeout 原因码/
approval HMAC/trace 脱敏四件套(默认值经用户确认); @ai-sdk/mcp adapter 与
ToolLoopAgent 默认 loop 替换均不采用(留实验路径)。发版前保留官方一方 key
smoke gate。冲突仅 ai-sdk-7 计划决策日志一处,union 双方条目解决。
五个 phase 全部经 hands-off loop 完成并 Codex accepted(issues #1/#6/#7/#8/#10)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ion for Native Runtime
Two feature gaps where Native Runtime didn't match SDK Runtime, both
surfaced during post-hermes-upgrade manual testing:
── op7418#1: Compression notification now human-readable ──
Before: chat/route.ts:402 emitted `message: 'context_compressed'` as
a machine string. useSSEStream's notification branch showed this raw
string in the status bar — users saw "context_compressed" flash by.
After: message is now `"Context compressed: N older messages summarized,
~X tokens saved"` with structured `stats: { messagesCompressed, tokensSaved }`
for future rich UI handling. Added `subtype: 'context_compressed'` for
dedicated frontend handlers.
── op7418#3: AskUserQuestion tool for Native Runtime ──
Before: only SDK Runtime had AskUserQuestion (built into Claude Code CLI).
Native Runtime had no such tool, so the model could never ask structured
questions — the existing AskUserQuestionUI in PermissionPrompt.tsx was
unreachable dead UI code for Native Runtime users.
After:
- New builtin tool `src/lib/builtin-tools/ask-user-question.ts`
registered in index.ts, condition 'always'
- Zod schema: 1-6 questions, each with 1-6 options, optional multiSelect
- Execute receives answers from permission flow (injected by frontend)
and formats as Q/A pairs for the model
- permission-checker.ts: new ALWAYS_ASK_TOOLS set ensures AskUserQuestion
(and ExitPlanMode) always show UI even in trust mode — without this,
trust mode would auto-approve and return empty answers
- PermissionPrompt.tsx: NEVER_AUTO_APPROVE set prevents full_access mode
from auto-approving AskUserQuestion — the UI must render so the user
can answer
The data flow:
Model → AskUserQuestion({ questions }) → permission wrapper intercepts
→ SSE permission_request → frontend AskUserQuestionUI renders
→ user picks options → updatedInput({ questions, answers }) → tool
execute formats answers → model gets "Q: ... A: ..." string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ge generation results
GPT-Image-2.0 skill silent failure had two compounding causes both
on the 'tool result' loop:
P0 op7418#1 — function_call_output translated with sentinel toolName
translate-input.ts wrote toolName: '__from_responses_proxy__' for every
tool-result and the comment claimed 'ai-sdk doesn't use this for
routing'. That was wrong. Anthropic and OpenAI Responses both look
up the tool definition by tool-result.toolName when reconciling the
result with the request's tool surface; with a sentinel they can't
correlate and refuse to produce the continuation turn — exactly the
'tool ran, no follow-up text' the user saw.
Fix: walk the input array once first to build call_id → toolName
from function_call items, then look up the real name when translating
function_call_output. Orphan results (no matching function_call) fall
back to a named sentinel '__orphan_function_call_output__' AND emit
console.warn naming the call_id. The divergence stays loud.
P0 op7418#2 — imageGeneration / imageView silently dropped
event-mapper.ts had both item types in CHAT_ONLY_ITEM_TYPES, which
returns null on item/started + item/completed. That set is correct
for agentMessage/plan/reasoning (they have streaming delta channels
so the content arrives separately), but imageGeneration / imageView
have NO delta channel — their final item is the only surface where
the result reaches the user. Silent drop meant 'tool ran' with no
visible image.
Fix: move both types to TOOL_LIKE_ITEM_TYPES, add explicit
translateItemStarted branches with names image_generation /
image_view, and the existing TOOL_LIKE_ITEM_TYPES completion branch
already packs the full item into output — preserving result,
savedPath, revisedPrompt, path for chat-side rendering.
ThreadItemLike grew matching fields so TS doesn't downgrade access
to (item as { path?: string }).path casts.
Tests (8 new)
src/__tests__/unit/codex-proxy-translators.test.ts (+3):
- toolName resolves from matching function_call (gpt_image_2 case)
- toolName resolves correctly with interleaved out-of-order calls
- orphan function_call_output → named sentinel + console.warn
src/__tests__/unit/codex-event-mapper.test.ts (+4):
- imageGeneration item/started → tool_started(name='image_generation')
- imageGeneration item/completed → tool_completed with full
result + savedPath + revisedPrompt payload
- imageView item/started → tool_started(name='image_view') + path
- imageView item/completed → tool_completed with path preserved
src/__tests__/unit/codex-proxy-tool-contract.test.ts (+1):
- End-to-end continuation: function_call → function_call_output →
streamText(messages) — MockLanguageModelV3 must see toolName
'gpt_image_2' in its prompt, NOT '__from_responses_proxy__'.
Continuation text-delta event fires.
The mapper-side translate also removed the chatOnly array's
imageView / imageGeneration entries from the old 'returns null'
parameterised test; replaced with the new lifecycle describe block.
Closeout doc records round 7 ✅ items; remaining must-haves
unchanged (4-family smoke matrix + codex-sdk POC).
All 2416 tests pass (was 2412 + 8 new − 4 obsolete from the chatOnly
table for imageView/imageGeneration).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ce 2a
Direction approved; three sharpenings folded into the existing
Phase 2 plan structure without restructuring.
1. Widget wire-format single source (review revision op7418#1)
slice 7's WIDGET_SYSTEM_PROMPT template-literal-embeds
WIDGET_WIRE_FORMAT_SPEC. With artifactContracts ordered BEFORE
capabilityFragments in the compiler, the wire spec would land in
the final system prompt twice (once from artifactContract, once
from the capability fragment tail). The plan now declares hard
constraints — CANONICAL_SHOW_WIDGET_JSON, the "FINAL OUTPUT
FORMAT" title, and WIDGET_WIRE_FORMAT_SPEC each must appear
exactly once in the compiled system prompt — and assigns slice
2c a small refactor that strips the wire spec from
WIDGET_SYSTEM_PROMPT so artifactContract becomes the sole holder.
Compile-time sanity check (capability fragment text MUST NOT
contain artifactContract.canonicalJson) added as a defence-in-
depth FAIL path.
2. Expected Differences Ledger (review revision op7418#2)
2b's "compiler output === Runtime current prompt" stance
directly conflicted with slice 2d's plan to canonicalize Native
memory / notify / media-import paraphrases. Equivalence reading
strictly would have locked the old drift in. Plan now introduces
`src/lib/harness/expected-differences.ts` with typed entries
(runtimeId, capability, diff kind, justification,
plannedResolution, compilerSource, runtimeSource). 2b harness
reads "compiler vs runtime diff ⊆ ledger"; unregistered
differences fail. Initial ledger seeded with the four known
Phase 5c slice 7b tech-debt items, three earmarked for slice 2d
and one (image_generation MediaBlock shape) earmarked
follow_up. Slice 2d completion = manual ledger entry removal
(deliberate non-automation, preserves audit trail).
3. runtimeHints boundary (review revision op7418#3)
Plan tightens the runtimeHints type declaration so it cannot
become a fourth prompt-assembly point. Allowed: IDs (mcp server
names, tool keys, builtin tool name set), fragmentIds refs into
CompiledContext, adapter options (stopWhen / stepCount /
passthroughToolTypes). Forbidden: any prompt text string, tool
description paraphrase, capability redefinition. Three test
layers — type-level (string fields ≤ 64 chars, no newline / no
markdown), runtime-level (no template-literal-shaped values),
source-grep level (no multi-line template literals in
runtimeHints assignments) — plus a dangling-reference check
that every fragmentId in runtimeHints resolves in
CompiledContext.
Regression test list extended 9 → 12. Decision log records all
three revisions with rationale.
Plan still in 📋 status. No code; awaiting Codex re-review on the
revised draft, then slice 2a opens.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
User mode change: "internal slice order preserved, external single
delivery; stop only after Phase 2 is done; Codex review takes the
batch." This commit lands slices 2a–2e together with all post-
review hardenings (Widget wire-format single source, Expected
Differences Ledger, runtimeHints prose ban).
Internal slice walk
2a — context-compiler.ts (NEW)
Pure function `compileContext(input): CompiledContext`. No IO,
no provider calls. Resolves enabledCapabilities (null = catalog
live default), looks up exposure for the calling runtime, emits
capabilityFragments + artifactContracts + memory + workspace +
toolDescriptors + runtimeHints + budget + systemPromptText +
diagnostics. Hard contracts: artifactContract before capability
in the assembled prompt; fragmentId uniqueness; cross-runtime
fragment text identity; compile-time FAIL if a capability
fragment text contains an artifact contract canonicalJson
(wire-format dedup); compile-time FAIL if load-bearing fragments
exceed budget. runtimeHints types strictly ID/refs/adapter
options — no prose, no template literals.
2b — expected-differences.ts (NEW)
Drift ledger. Initial 4 entries from slice 7b tech-debt. Three
slice_2d entries consumed by this commit (see 2d below); the
one remaining `follow_up` is image_generation MediaBlock shape
(non-prompt, future slice).
2c — ClaudeCode SDK (claude-client.ts) source-pin only
The SDK path has always imported MCP canonicals directly
(memory-search-mcp, notification-mcp, media-import-mcp,
cli-tools-mcp, dashboard-mcp) — no paraphrase ever existed.
Slice 2c codifies this with a contract test: claude-client.ts
must not import capability prompts from builtin-tools/* and
must not declare its own _SYSTEM_PROMPT scalars.
2d — Native Runtime (builtin-tools/*) re-export MCP canonicals
`memory-search.ts` now `export const MEMORY_SEARCH_SYSTEM_PROMPT =
CANONICAL_MEMORY_SEARCH_SYSTEM_PROMPT` (imported from
memory-search-mcp.ts). Same pattern for `notification.ts`
(NOTIFICATION_SYSTEM_PROMPT = NOTIFICATION_MCP_SYSTEM_PROMPT)
and `media.ts` (MEDIA_SYSTEM_PROMPT = MEDIA_MCP_SYSTEM_PROMPT
from media-import-mcp.ts). Three ledger entries removed in
sync.
2e — Codex bridge (builtin-bridge.ts + unified-adapter.ts)
Bridge no longer holds WIDGET_PROMPT / MEDIA_PROMPT /
MEMORY_PROMPT / NOTIFY_PROMPT scalars (all four declarations
deleted). `createCodePilotBuiltinTools().systemPrompt` is
permanently `''`. `unified-adapter.ts` now calls
`compileContext({ runtimeId: 'codex_runtime', ... })` and feeds
`compiled.systemPromptText` to Codex's `instructions`. A new
helper `capabilitiesFromBridgeToolNames` maps the bridge's
mounted tool names back to capability ids so the compiler's
enabledCapabilities aligns with what the bridge actually
exposes (workspace-gated memory tools naturally drop out when
workspacePath is empty).
Slice 2c Widget wire-format single source (review revision op7418#1)
WIDGET_SYSTEM_PROMPT in widget-guidelines.ts no longer
template-literal-embeds `${WIDGET_WIRE_FORMAT_SPEC}`. The
artifactContract is now the sole holder of the wire-format spec
+ canonical JSON. Compiler's `detectWireFormatDuplication` sanity
check throws at compile time if any capability fragment text
contains the artifact contract canonicalJson — that's the forcing
function preventing the spec from being re-injected.
Three regression pins enforce single occurrence in the compiled
prompt: CANONICAL_SHOW_WIDGET_JSON × 1, "FINAL OUTPUT FORMAT —
non-negotiable" × 1, WIDGET_WIRE_FORMAT_SPEC × 1.
runtimeHints boundary (review revision op7418#3)
ClaudeCodeHints / NativeHints / CodexProxyHints types now carry
only IDs (mcp server names, tool keys, builtin tool name set) +
adapter options (stopWhen, stepCount, passthroughToolTypes).
Tests pin: type-level (no string field > 64 chars, no newline,
no Markdown markers), runtime-level (scan all string values for
prose), source-grep (CodexProxyHints type definition can't
contain `promptOverride` / `promptExtra` / `widgetPrompt` / etc).
Tests
New harness-context-compiler.test.ts (23 pins): catalog hygiene,
Widget wire-format single source (op7418#10), ordering, budget
enforcement, cross-runtime fragment identity (op7418#9), tool
descriptors, runtimeHints boundary (op7418#11), Expected Differences
Ledger consistency (op7418#12), JSON parseability of every artifact
contract.
New harness-context-compiler-equivalence.test.ts (9 pins):
compiler source reachability, runtime drift honesty,
ledger/slice ownership correctness, "post-slice-2d: Native
ledger holds only the follow_up MediaBlock entry".
Updated harness-capability-contract.test.ts: drift pins now
check (a) bridge holds no local _PROMPT scalars, (b) Native
builtin-tools re-export MCP canonicals, (c) unified-adapter
imports compileContext + consumes systemPromptText, (d)
claude-client.ts doesn't import from builtin-tools/* and
doesn't declare own _SYSTEM_PROMPT.
Updated codex-widget-format-contract.test.ts: the "WIDGET_SYSTEM_PROMPT
embeds WIDGET_WIRE_FORMAT_SPEC" and "appears inside
WIDGET_SYSTEM_PROMPT" pins are flipped — slice 2c REMOVED the
embed; the new pins verify the compiler-side import line.
Updated codex-builtin-bridge.test.ts: tests previously asserting
`bridge.systemPrompt` contained capability tags now assert it
equals `''` (bridge is no longer the prompt-assembly point).
Verification
CODEX_DISABLED=1 npx tsx --test \
src/__tests__/unit/harness-context-compiler.test.ts \
src/__tests__/unit/harness-context-compiler-equivalence.test.ts \
src/__tests__/unit/harness-capability-contract.test.ts \
src/__tests__/unit/codex-widget-format-contract.test.ts \
src/__tests__/unit/codex-builtin-bridge.test.ts
→ 74/74 pass
npm run test → 2576/2576 pass
Completion criteria check (per user spec)
[x] npm run test all green (2576/2576)
[x] Context Compiler unit tests all green
[x] equivalence / expected-diff harness all green
[x] harness-capability-contract / codex-widget-format /
codex-builtin-bridge tests all green
[x] no new runtime-local prompt duplicates (Native re-exports
canonical; ClaudeCode imports canonical; bridge holds none)
[x] Codex bridge no longer holds WIDGET_PROMPT / MEDIA_PROMPT /
MEMORY_PROMPT / NOTIFY_PROMPT scalars (all four removed,
drift test pins their absence)
[x] all three Runtimes adapt compiler output, none redefine
capability prompts
Docs
- phase-5d-phase-2-context-compiler.md: slice statuses 2a–2e all
✅ 2026-05-17; note the one-shot delivery mode change.
- phase-5d-harness-capability-contract.md: Phase 2 row ✅, awaiting
Codex review.
- handover/harness-capability-contract.md: new "Context Compiler"
section detailing inputs/outputs/constraints, three-runtime
consumption pattern, Expected Differences Ledger contract.
- refactor-closeout.md: new decision-log entry recording the
Phase 2 delivery shape + completion criteria check.
Phase 5d Phase 2 ✅ pending Codex review. Phase 3 (Runtime
Capability Adapter) / Phase 4 (Artifact Contract) / Phase 5
(new-Runtime Playbook) intentionally NOT opened — stopping per
user instruction.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
… to breakdown
## 用户视角
升级前:popover 的"文件与附件 / 本次待加入"两行永远 0 —— 数据通道没接通。即使 composer 里挂了 4 个 mention 和 2 个目录引用,popover breakdown 显示 0。
升级后:MessageInput → ChatView/page → RunCockpit → useContextUsage → buildContextUsageBreakdown 全链路联通。composer 里的 attachment / mention / directory 实时累加到对应类别。trigger 上的迷你点阵 + popover 主条 + 列表行三处同步更新。
发送消息后 pending 归 0;下一轮 history 里的真实 token_usage 接管 used 部分;conversation 类自动吸收。
## 不做什么
- 不改 hook 其他字段(used / ratio / state / source 等不动)
- 不改 trigger 主结构(百分比文字仍在;只有点阵 cells 在分配时反映 pending)
- 不改 composer text 估算(composerTextTokens 仍 0;那是 Phase 3+ 的事)
## 怎么验收
- npm run test → 2921/2921 pass
- composer 里加附件 / @mention / "+" 目录 → trigger 上 pending 部分立刻有虚线 cells
- 发送消息 → pending 归零;下轮 used cells 更新
## 改动(6 文件)
### src/lib/message-input-logic.ts
新增 `PendingContextSubTotals` interface + `computePendingContextSubTotals()` 函数。逻辑 mirror `computePendingContextTokens`(同样的 null 过滤、同样的迭代顺序),但返回 { attachment, mention, directory } 三键。两个函数加起来 = 等于 computePendingContextTokens 总数。
### src/hooks/useContextUsage.ts
options 加可选 `pending?: { attachmentTokens?, mentionTokens?, directoryTokens?, composerTextTokens? }`。三条返回路径(snapshot / walk / noData)都把 options?.pending 转发给 buildContextUsageBreakdown。useMemo deps 数组加 options?.pending。
### src/components/chat/RunCockpit.tsx
RunCockpitProps 加可选 `pendingContextSubTotals?: { attachment, mention, directory }`。组件内部把它转换成 hook options.pending 形态(attachment → attachmentTokens 等)。可选 prop 默认 undefined → 不破坏现有 callsites。
### src/components/chat/MessageInput.tsx
- import 加 computePendingContextSubTotals + PendingContextSubTotals type
- props 加可选 `onPendingContextSubTotalsChange?` callback(跟现有 onPendingContextTokensChange 并列)
- 新增 useMemo 算 pendingContextSubTotals + useEffect emit callback
- 与现有 pendingContextTokens 走同一份 source 数据,逻辑同步无 divergence
### src/components/chat/ChatView.tsx
- 加 state `pendingContextSubTotals` (PendingContextSubTotals | undefined)
- MessageInput 上 wire `onPendingContextSubTotalsChange={setPendingContextSubTotals}`
- RunCockpit 上传 `pendingContextSubTotals={pendingContextSubTotals}`
### src/app/chat/page.tsx
- 跟 ChatView 完全镜像:state + MessageInput callback + RunCockpit prop
- 两个入口独立持有 state(按 StreamSession guardrail 不变量 op7418#1)
## Scope discipline
- 不新增测试(Codex 负责测试覆盖;用户分工已明确)
- 不动 buildContextUsageBreakdown / computePendingContextTokens 既有签名 → 旧调用 zero-risk
- 不改 chat-static-graph 排除清单 → MessageInput / RunCockpit 改动属于增量 prop,没新依赖链
- composerTextTokens 仍未 wire(composer 纯文本估算属于未来扩展,pending_next_turn 行暂时仍 0)
## StreamSession guardrail 合规
- 双入口(page.tsx 首消息 + ChatView 后续)独立 state — 不变量 op7418#1 ✅
- onSend / onCommand 签名不变 — rewind point 不变量 op7418#2 ✅
- 不动 capability cache — 不变量 op7418#3 ✅
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…18#31)
Codex review second round caught two real P1 inconsistencies introduced by
the Dashboard/CLI split slice plus non-blocking contract drift.
P1.1 — Dashboard injection gate ≠ route auth gate.
runtime.ts injected the dashboard read/write MCPs whenever prompt + working
directory + dashboard keyword matched, but the route's `authorize` requires
`sameRealPath(workspacePath, assistant_workspace_path)`. Mismatch → the model
sees the tool and Codex 403s at call time. Fix: dashboard injection mirrors
memory's gate exactly (same sameRealPath check, same `assistantWorkspacePath`
passed as `workspacePath`) so "inject" and "route-authorize" never disagree.
CLI tools don't need this (no workspace scope).
P1.2 — Matrix promoted only for codex_account; runtime injects for ALL
codex_runtime providers.
The runtime didn't gate injection by provider, so under a CodePilot proxy
provider the dashboard/cli MCPs WERE injected (callable), but the matrix
returned `perception_only` for non-codex_account — the opposite drift from
P1.1 ("model says yes, Settings says no"). Fix per Codex's preferred option:
move the promotion into `capabilityMatrixForRuntime` so it applies to ALL
codex_runtime providers; `capabilityMatrixForRuntimeProvider` now only adds
codex_account-specific overrides (native notes + image/media demotion).
`buildCapabilityMatrix` delegates to `capabilityMatrixForRuntime` so every
matrix entry point stays aligned.
Non-blocking op7418#1 — contract text drift.
capability-contract.ts dashboard/cli `deferredReason` + `codex_proxy.notes`
rewritten — explicit that the LEGACY provider-proxy bridge is unsupported
(true), and that the codex_runtime path now ships via the mutation-level MCP
split + matrix-layer promotion. No schema changes (`kind: 'unsupported'`
stays accurate for the legacy bridge surface); the existing matrix invariant
test gets a `MATRIX_LAYER_PROMOTIONS` exception list documenting why the two
promoted cells are allowed to be executable despite `kind: 'unsupported'`.
Schema cleanup (introduce a new `mcp_server_split` kind, drop the exception
list) tracked as tech-debt op7418#33.
Non-blocking op7418#2 — elicitation policy pins.
codex-mcp-events.test.ts now pins all 4 new server names:
codepilot_{dashboard,cli_tools}_read → auto_accept,
codepilot_{dashboard,cli_tools}_write → user_approval.
Also added a regression guard: `codex_runtime + non-codex_account provider`
must STILL show dashboard/cli_tools executable with mixed trust + the right
noteKey. Updated the two pre-existing tests that asserted the OLD behaviour
(dashboard/cli perception_only on codex_runtime) — they now assert the
promoted state. Also synced the static `CAPABILITY_EXECUTABLE_RUNTIMES` map.
Per Codex review's explicit ask: the "待真账号 smoke" wording stays in the
op7418#31 capability table — this commit fixes the inconsistencies, but the
real-account end-to-end smoke for natural-conversation triggering + write
approval card + Deny blocking is still owed by the user.
Full unit suite 3045/3045. Live route: bad workspace still 403 (auth gate
intact); tools/list subsets unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Codex review 认可方向,按 5 条反馈修订(纯文档,无代码):
- Phase A 增"开工前核验"(Opus 4.8 官方 model id / context window / thinking·effort / 1M beta,不臆测)
- Phase A 实现范围增"泛化 Opus 4.7 专属逻辑"(isOpus47Model / OPUS_4_7_PATTERN / applyContext1mBeta /
effort 门控 / claude-client sanitizer,配回归测试)—— catalog 显示 ≠ 请求正确
- OpenRouter Opus 4.8 改 deferred(不臆测 slug),首轮只接 Anthropic direct
- opus 别名 / 默认先不动(仍 4.7),只新增显式 claude-opus-4-8,切换待 smoke 后用户拍板
- Phase D 拆 D0/D:D0 把 apply-discovery-diff 全量 flake + no-verify 事件记入 tech-debt op7418#30(本提交即 D0);
D 建议先于 A/B/C,代码 phase 不再靠 --no-verify
- Open Questions op7418#1/op7418#2 据上述决议收敛
本提交纯文档;pre-commit 同样因 apply-discovery-diff 全量 flake 用 --no-verify,已确认 docs-drift 绿。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
v0.56.x 计划 Phase 1:建立稳定性治理入口,并用当前源码重新核验 Notion/issue 列出的
7 个 issue(不采信 issue 自述根因)。
GitHub 侧(已在仓库生效,非本 commit 内容):
- 创建 milestone op7418#1「v0.56.x Stability / Trust」。
- 创建 9 个治理 label:P0-crash-or-interrupt / P0-data-loss-risk / P1-runtime-session /
P1-context / P1-file-reference / P1-installer-update / P1-performance / needs-repro /
v0.57+ parking-lot。
- 给 op7418#626/op7418#628/op7418#629/op7418#632/op7418#633/op7418#634/op7418#635 按复核结论打 milestone + 优先级 label。
本 commit 文件:
- .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml:bug 表单强制必填
版本/OS/runtime/provider-model/可复现/复现步骤/期望vs实际 + 影响面勾选;feature
表单注明 v0.56.x 冻结新功能 → v0.57+ parking-lot;config 关闭空白 issue + 冻结说明
与 Discussions 入口。
- .github/PULL_REQUEST_TEMPLATE.md:Summary / Repro+root cause / Changes / Tests /
Screenshots-logs / 自查清单(链到 CLAUDE.md 与 AGENTS.md,不复制维护)。
- .github/TRIAGE.md:对外冻结说明、label 体系、issue/PR triage 规则、自动化候选。
- v0.56.x-stability-trust.md:标 Phase 0 完成 + 新增「2026-06-19 Claude Code 源码复核」
表(7 issue 逐条 file:line 证据)。关键复核结论:
* op7418#632 ">100%" 确认是未 clamp 的 ratio*100 显示 bug(RunCockpit.tsx:169 等),分母
contextWindow 不可靠;"跨会话串" 源码不成立。
* op7418#629 空 assistant 已防护,残留真实 gap:is_error result 路径不清坏 sdk_session_id
(claude-client.ts:1908 先置 resultEmitted)。
* op7418#635 截图-only,最强候选 = SDK runtime 无自生成 keepalive(claude-client.ts:1956),
慢 proxy 静默 >330s 被 idle abort(B-019)。
* op7418#628 确认真实风险:@file origin path 在 MessageInput.tsx:161 丢失,body.mentions[]
送达但 route.ts 从不消费 → 写 .codepilot-uploads 副本,AI 改副本。
* op7418#634 根因不成立——5 个 notify/schedule 工具均注册(builtin-tools/index.ts:250),
issue 引用的 UI 串不在当前源码(疑旧版);附带 Plan 模式 list_tasks 泄漏。
* op7418#626 polling 排除(8h 间隔),候选 animate-pulse × backdrop-filter 重绘。
* op7418#633 mac 无法复现;NSIS-only + 未签名 + 无 portable + CI 不验安装启动。
- issue-tracker.md:新增「v0.56.x 治理 issue」看板索引表(指向 plan 复核表,不重复分析)。
验证:docs-drift 通过;npm run test(hook)。Phase 1 验收(milestone/labels/模板/冻结
说明就绪)达成。下一步 Phase 2:按复核结论修 chat 主链路(上下文百分比语义、context-cost
不阻断发送、Codex 多模态发送、发送后清草稿)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…e 2 op7418#1)
Signal: issue op7418#632 报"上下文 >100% / 假百分比 / 压缩后跳变";Phase 1 源码复核确认是
真实显示 bug("跨会话串"不成立)。
Triage(当前源码): 用量百分比 = usage.ratio*100,在 RunCockpit.tsx 与
RunCockpitPopoverContent.tsx 两处直接渲染、未封顶;usage.ratio = used / contextWindow,
而 contextWindow 来自 sdkContextWindow ?? latestSdkContextWindow ?? catalogContextWindow
(useContextUsage.ts)。很多第三方 proxy 不上报 context_window → 落到静态 catalog 兜底
(一个猜测值),used 又会在压缩后跳变 → 百分比蹦到 200%/500%。根因是"拿不可信的分母
算百分比",不是上下文真的超了。
Fix:
- useContextUsage.ts: 新增 ContextUsageData.contextWindowTrusted —— 仅当 SDK/上游真实
上报窗口时为 true(catalog 兜底不算)。三个 return 分支(baseline / snapshot / no-baseline)
都按各自来源正确赋值。不可信时不把窗口喂给 buildContextUsageBreakdown,dot-matrix 退回
按已用 token 的构成比例,不编造容量。
- RunCockpit.tsx: hasFullCtx 增加 && usage.contextWindowTrusted —— 不可信时自动落到既有的
绝对已用 token 显示(触发按钮)/ showUnknownCapacityBlock 分支(浮层,已测试的"容量未知"
路径)。百分比文案 clamp ≤100%。
- RunCockpitPopoverContent.tsx: 浮层 header 百分比同样 clamp ≤100%(防可信窗口被 used 短暂
超过时仍蹦 >100%)。
语义验收: 输入框右下角不可信时只显示已用绝对值;浮层不可信时只显示已用 + 不同种类构成
比例(无百分比/remaining/unused/假总量);可信时百分比封顶 100%。
Verify: typecheck 通过;context-window-trusted.test.ts 6 条 source-pin + 既有
run-cockpit-unknown-capacity / context-dot-matrix / context-usage-walk / context-breakdown
全绿;全量单测 3366/3366。未做:真实 untrusted-window provider 会话的 CDP 视觉走查
(fix 把 untrusted 路由到既有已发布的"容量未知"分支,风险低;视觉走查列为后续)。
Guardrail: context-window-trusted.test.ts 钉死 trusted 派生只认 SDK 来源、不可信时不喂窗口、
hasFullCtx 必须 gate trusted、两处显示 clamp ≤100%,防回退到"拿 catalog 当真实分母算百分比"。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Signal: Codex 复核 fixop7418#1(9ea29a4)后发现 P2 残留——文字已改成"只显示已用 token",
但输入框右下角触发按钮旁的 mini dot-bar 仍用 200K 兜底画出"用了多少/还剩多少"的容量
暗示,与"拿不到总长度就不显示容量"及 commit message 的"不编造容量"不一致。
Triage(当前源码): ContextDotMatrix.tsx 有 FALLBACK_CONTEXT_WINDOW=200_000,
minCellsPerKind=0(mini-bar)在窗口未知时用它当分母(:88);RunCockpit.tsx:200 的触发
按钮无条件渲染这个 mini-bar。所以即使 9ea29a4 把文字降级为绝对已用,小条仍画假容量。
minCellsPerKind=0 全仓只有 RunCockpit 触发按钮一个调用方。
Fix:
- RunCockpit.tsx: mini-bar 用 {hasFullCtx && (...)} 包裹——仅在可信窗口下渲染容量小条;
不可信时触发按钮只剩绝对已用 token 文本(贴合"输入框右下角只显示已用数值")。
- ContextDotMatrix.tsx: 删除 FALLBACK_CONTEXT_WINDOW(200K)。窗口未知时两种模式都按
used+pending 分配(构成视图,非容量%),不再编造容量。
Verify: typecheck 通过;context-dot-matrix.test.ts 旧的"unknown mini-bar 用 200K 兜底
(filled<=2)"语义改为新的"used 构成(filled>=8)";context-window-trusted.test.ts 加 2 条
guardrail(mini-bar gate 在 hasFullCtx + 源码无 200K 兜底残留);全量单测 3368/3368。
Guardrail: 两条 source-pin 钉死"触发按钮 mini-bar 必须 gate 在 hasFullCtx"且"ContextDotMatrix
不得再出现 FALLBACK_CONTEXT_WINDOW/200_000",防回退到拿假容量画小条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户复核 fixop7418#1 后明确显示格式:输入框右下角的上下文小标,在有可信窗口时显示
"百分比 + 已用上下文"(如 56.6% 452K),没有可信窗口时只显示已用(如 452K),
不单列"剩余"数字。
改动:RunCockpit.tsx 触发按钮 ratioText 的可信分支由 "{pct}%" 改为
"{pct}% {used}"(1 位小数,匹配用户给的 56.6% 示例);不可信/无数据分支不变。
context-window-trusted.test.ts 的 clamp pin 扩为同时断言"百分比 + 已用"格式。
验证:dev 应用热重载干净(✓ Compiled);context-window-trusted 8/8;typecheck(hook)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…llow-up)
Signal: 用户在运行的应用里看到 GLM-5-turbo(Claude Code/Native 会话)仍显示总上下文
200K,指出"这并不是我们知道的部分"。fixop7418#1 本应让 catalog 静态值不可信、只显示已用。
Triage(当前源码,用户 review 驱动): agent-loop.ts:641-651(Native)在 token_usage
没有 context_window 时,从静态 catalog 填 totalUsage.context_window = getContextWindow(modelId)
(GLM-5-turbo 在 catalog 是 z.ai 核实的 202752)。而 context-usage-walk 把
token_usage.context_window 当作 SDK 实报窗口读,fixop7418#1 的 contextWindowTrusted 据此判可信
→ catalog 猜测被"洗白"成可信 → Native GLM 显示 200K。即上游 mutator 打败了 helper 修复
(feedback_fix_all_consumers)。claude-client(Claude Code)只从 SDK modelUsage 写,不洗白;
ContextUsageIndicator 是死组件(无人 import)。
Fix: 删掉 agent-loop 的 catalog 洗白。Native 无 runtime 实报时 context_window 留空 →
useContextUsage 回落 catalog 为不可信 → 只显示已用绝对值,不再有假百分比/假总量。
仅对新 turn 生效(历史消息已存的 context_window 不改写,遵守不改用户数据;旧会话发新消息后转为已用-only)。
Verify: typecheck;context-window-trusted.test.ts 新增 pin 断言 agent-loop 不再
`.context_window = catalogWindow`;该文件 9 测 + agent-loop-error-event 全过。运行中 dev 应用
server 重编译干净(Native GLM 需发新消息验证)。
Guardrail: source-pin 防 Native 再把 catalog 洗进 SDK-authoritative 字段。
设计记录(用户批准"先记计划再实现"): v0.56.x 计划写入 context-window 来源优先级修订设计
(runtime 实报 > provider 配置 contextWindow > 压缩阈值 > catalog 不可信)+ 跨 Runtime 用户
配置源(op7418#1,待实现) + 显示分母对齐压缩阈值(op7418#3,待实现)。本提交是设计第一步(去洗白)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
把"为什么 GLM 显示 200K + 窗口来源该怎么改"写成评审稿放进 v0.56.x Phase 2,按
外部事实 / 本地证据(file:line) / 推断与设计三层分写,供 Codex 核实。
要点:
- Agent SDK v0.2.111 的 modelUsage.contextWindow(sdk.d.ts:945)是未文档化字段,来自
SDK 内置模型目录而非 API;第一方可靠、第三方(经 base_url 的 GLM)返回通用默认值;
无 SDK 设置可覆盖;Anthropic 建议自维护窗口表。
- 实测 GLM 会话 token_usage.context_window=200000 ≠ 本地 catalog 202752,证实来自 SDK
默认而非 catalog/Native 洗白;该会话是 Claude Code(故上一提交的 Native 修复不覆盖它)。
- 修订设计:窗口来源优先级 = 用户覆盖 > 已核实 catalog/provider 配置 > SDK(仅第一方) >
只显示已用;第三方忽略 SDK 默认值;跨 Runtime;显示分母对齐压缩阈值(op7418#3)。
- 列出待定决策(已核实优先 vs 纯手动) + 给 Codex 的 5 个核实点。
未改任何产品代码(纯文档)。op7418#1/op7418#3 实现待 Codex 核实后进行。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Codex 复核设计稿后订正(实现 op7418#1/op7418#3 前必须):
- A:原"官方文档不记载 contextWindow/maxOutputTokens"不准 → 改为 SDK TypeScript
reference 有字段定义,是 cost-tracking 指南未解释来源/可信度。
- B/C:原"catalog 202752 比 SDK 200000 更准且 z.ai 核实"站不住 → z.ai 官方写
200K/128K,catalog 该条来源存疑;结论收敛为"SDK 200000 不可作为 provider 实报采信",
不延伸到"catalog 更准";另标记需单独核 model-context.ts:42 的真实来源。
- D + 决策日志:统一优先级(消除冲突,旧决策日志把第三方 SDK 又洗白成可信)→
用户手动覆盖 > provider/model 配置且来源已验证 > 第一方 runtime 实报 > 只显示已用;
第三方 SDK contextWindow 默认不可信、无明确来源 catalog 不当可信%显示。
- "Anthropic 官方建议自维护表"未核到原文 → 降级为工程结论。
- 澄清:用户实际看到 200K 的 GLM 会话是 Claude Code(SDK 默认 200000),非 Native 洗白
路径(f79fd54 的 Native 修复有效但治另一条路径)。
- E:决策收敛为一条基线 + 剩余一项请用户定(第一方 SDK 实报是否自动显示百分比)。
Codex 核为真的部分(sdk.d.ts:945 字段、代码写入 token_usage、历史 SDK 窗口被当可信、
Native 洗白已去、显示分母 vs 压缩阈值脱节)保留。纯文档,未动产品代码。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
F 段核实点 op7418#1 还残留旧"官方文档未记载(A)",与已订正的 A 段不一致。改为:
sdk.d.ts:945 的 contextWindow/maxOutputTokens 存在,SDK TypeScript reference 已列,
只是 cost-tracking 指南未解释来源/可信度。纯文档。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…#632 / Phase 2 ①)
Signal: 用户 GLM-5-turbo(Claude Code 经代理)显示总上下文 200K,且 Codex 核实 SDK 的
modelUsage.contextWindow 来自 SDK 内置目录、对第三方是通用默认值、无 SDK 设置可覆盖。
Triage: claude-client.ts extractTokenUsage 把 SDK modelUsage.contextWindow 无条件写入
token_usage.context_window;walk + fixop7418#1 据此判可信 → 第三方代理(GLM)的 SDK 默认 200000
被当可信显示。Native 的 catalog 洗白已于 f79fd54 去掉;本提交补 SDK 路径。
Fix(Codex 统一口径"第一方 runtime 实报可信、第三方不可信"):
- ai-provider.ts 导出 isFirstPartyAnthropicEndpoint(baseUrl)(空/anthropic.com → 第一方)。
- extractTokenUsage 增 trustContextWindow,仅 true 时写 context_window;两个调用点都传
isFirstPartyAnthropicEndpoint(resolved.provider?.base_url)。第三方(自定义 base_url,如 GLM)
→ 不写 context_window → useContextUsage 回落 catalog 为不可信 → 只显示已用。
效果 + 边界: 第一方 Anthropic 继续显示百分比+已用;第三方代理新 turn 起只显示已用。
仅对新写入生效(历史消息已存的 context_window 不改写,遵守不改用户数据);现有 GLM 会话
仍显示旧值,需新会话/新 turn 验证(walk 会读历史,故旧会话需自然滚动出旧窗口或新建)。
Verify: typecheck;extract-token-usage-context-window.test.ts 增 2 pin(gate + 两调用点传
第一方判别);全量 3371/3371。
Guardrail: source-pin 钉死 context_window 写入受 trustContextWindow 门控 + 两调用点必须传
isFirstPartyAnthropicEndpoint,防回退到无条件信任第三方 SDK 窗口。
remaining(Phase 2 ①/③ 未完): provider/model 配置窗口作为最高优先可信源(用户覆盖) + 渲染层
对现有会话按第一方 gate(治旧会话) + op7418#3 显示分母对齐压缩阈值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
计划文档状态审计修正(决策日志准、但概览层过期):
- frontmatter 状态行:📋 待接手 → 🚧 Phase 0/1 已完成、Phase 2 进行中。
- 「状态总览」表:Phase 1 待开始 → ✅ 已完成(2026-06-19);Phase 2 待开始 → 🚧 进行中。
- Phase 2 加进度 note:Composer/Context 主链路 op7418#1op7418#5 全部收口(含 commit + op7418#3 真实
Codex 冒烟回复 circle);Session/Stream cluster op7418#629/op7418#635 + 终态原因码 + 压缩回滚
+ 诊断导出字段待续。
- Phase 2 执行清单 4 项已完成项 [ ]→[x](上下文 UI 语义 / context-cost 去阻断 /
Codex 多模态发送 / 发送后草稿清理)。
CLAUDE.md 执行计划段新增「完成即回写进度(与 Codex 对齐协作)」:任一 Phase/子项做完
必须立即回写三处且一致——执行清单勾选 / 状态总览表+frontmatter / 决策日志(commit
+验证结论);Claude 实施+回写、Codex 审查+维护;三者不一致视为状态失真须先对齐。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
打回上一条状态同步的一处失真:我把 op7418#4/op7418#5「发送后内容残留」标成完成(checklist [x] +
进度 note 列为 done),但同一文档决策日志(2026-06-20 条)已写明用户再次确认"内容已发出
但文本仍残留输入框"、op7418#615 source-pin 不覆盖该症状、不能算闭环——状态表/清单与决策日志
自相矛盾,违反刚加的"三者必须一致"。
修正(与决策日志对齐):
- checklist「复现并修发送后内容残留」[x] → [ ],标注"待复核/待修复(用户 2026-06-20 再报)"。
- Phase 2 进度 note:拆分——op7418#4/op7418#5 仅失败保留有基础修复(op7418#615),发送成功后文本残留待复核;
note 标题从"主链路已收口"改为"op7418#1op7418#3 收口、op7418#4/op7418#5 待复核";待续列表补回 op7418#4/op7418#5(重新打开)。
- op7418#2 context-cost 非阻断保持完成(checklist [x] + note)不变。
后续修 op7418#4/op7418#5 时重点:PromptInput 受控/非受控清空边界、setInputValue('') 与
controller.textInput.clear() 是否同源、成功 accepted 后 remount/local draft 恢复、
badge/confirm/image 分支与普通 Enter 分支是否一致(决策日志已记排查方向)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
按"完成即回写进度"规则同步三处:
- checklist「复现并修发送后内容残留」[ ]→[x],标注已修 + CDP 验证 + 根因/修法(de123df)。
- Phase 2 进度 note:op7418#1op7418#5 全部落地;op7418#4/op7418#5 从"待复核"改为"已定位+修复"(含根因/CDP 结论);
待续列表移除 op7418#4/op7418#5、只留 Session/Stream cluster。
- 决策日志加同日条目:CDP 埋点定位 = 首条消息 accept 布局翻转 remount composer、inputValue
从 sessionStorage 草稿重读;修法 = accept 处清草稿;3401/3401 + CDP 文本/图文首条 800ms 即清。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户在浏览器实测不残留、仅桌面 App 残留 → Claude 协助完整重启 electron:dev(kill 整棵
进程树 + 释放 3000 + 后台重启)→ 用户在重启后真实 App 验证发送即清空 → op7418#4/op7418#5 闭环。
根因:de123df(page.tsx accept 处清首条草稿)一直是对的;用户残留是 Electron dev 没把
page.tsx 改动热更新进 renderer、窗口刷新无效,得整进程重启。这解释了全程「Claude CDP
浏览器清、用户残留」的矛盾——不是 Electron 行为差异,是构建新鲜度差异(Claude 浏览器硬刷
过有修复、用户 Electron 旧构建没有)。
回写:checklist [x](用户真实 App 验证)、进度 note op7418#1op7418#5 全闭环、验收去 ⚠️、决策日志加
闭环条目 + 教训(UI 修复在桌面 App 验证必须整重启 electron:dev)。Codex P1(prefill/
initialValue 回灌)仍是 de123df 的真实独立漏洞、值得单独补,与本次残留无关。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
纯文档同步,无代码改动。目的:让下一个进程打开文档时不从旧状态误判进度。
三处状态表此前已标 Phase 0/1 ✅、决策日志也已确认完成,唯独执行清单 checkbox
与 README 索引、issue-tracker op7418#632 仍停在旧值——三处不一致即状态失真,本次对齐。
README.md:
- v0.56.x 索引行状态列 "📋 待 Phase 0 收束" → "🚧 Phase 0/1 ✅;Phase 2 进行中
(Composer/Context 主链路 op7418#1op7418#5 闭环,Session/Stream cluster op7418#629/op7418#635 待续)",
追上 plan frontmatter 与决策日志。
v0.56.x-stability-trust.md:
- Phase 0 执行清单 8 项 [ ]→[x],逐条带回溯(3360/3360、dd4ead4、b853188/2de9c2b)。
A2 计时器项如实标注:按 keyed-remount 构造性消除 + 截图不可判别记录入 Smoke Ledger,
非逐帧视觉确认(反假数据,不谎称做了视觉确认)。
- Phase 1 执行清单 5 项 [ ]→[x],带回溯(milestone op7418#1 / 9 labels / .github/TRIAGE.md)。
issue-tracker.md:
- op7418#632 状态 "🔴 待修" → "🟡 假%已修,item3 分母对齐待续"。核心显示 bug(假百分比/>100%)
已由 effective-base-URL 写入 gate + 渲染期 trusted gate + clamp 修复并经真实 GLM
会话验证;item3(显示分母对齐压缩阈值)是独立待续阶段,故标部分修复而非已修复。
- 顶部"最后更新"同步到 2026-06-26 + op7418#632 同步说明。
验证:git diff 确认仅 3 文档、16/16 行 checkbox 与状态文字,无代码/意外文件。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
- docs/research/ai-sdk-7-toolloop-parity-gaps.md: 新增「Phase 5 处置」节,全部 gap
收口——P1×3 关闭(op7418#1/op7418#2 补偿由 parity 8/8 复跑锁定;op7418#3 降级论证:Phase 4 已证
approval HMAC 不需要 SDK toolApproval 停机语义,维持 in-execute 路线),
P2/P3 关闭或 backlog(op7418#4/op7418#5 列为替换路线前置条件,op7418#7 归档 tech-debt op7418#49op7418#8 有 Phase 5 新实证)
- scripts/smoke-ai-sdk7-phase5-decision.ts: 新增决策门对照 smoke——prod runAgentLoop
与 POC runToolLoopAgentPoc 用同一 AgentLoopOptions 逐场景对照(长文本 / approval
批准 / approval 拒绝 / abort→continue),机械比较归一化事件序列 + 尾部契约 +
usage 存在性;DB 只读、数据目录隔离、输出全 scrub。探针注意:approval 批准分支
用 printf(echo 命中 permission-checker 自动放行规则不会触发 ask)
- docs/exec-plans/active/_smoke-evidence/ai-sdk7-phase5-decision-smoke.json:
OpenRouter 真实渠道 4/4 场景 contractMatch=true(input_tokens 逐场景完全相同,
tool_result 逐字相同,中断轮双侧 done 收尾、同 session 续发一次通过);
凭据形态 grep=0
- docs/research/ai-sdk-7-adoption-decision.md: 新增采用决策文档——结论 partial
(依赖升级 go / provider 能力 capability-gated go / Phase 4 外围能力 go /
@ai-sdk/mcp 与默认 loop 替换 no-go-现在),四层 rollback plan(能力开关→
wrapper→runtime switch→known-good version),每项结论标注 Phase 1-5 证据来源;
默认 Runtime 切换留人类闸门
- docs/exec-plans/tech-debt-tracker.md: 新增 op7418#49(tool-error part 被两条 loop
一致吞掉的既有 UX 债,独立于采用决策)
- docs/exec-plans/active/ai-sdk-7-runtime-loop-adoption.md: Phase 5 状态回写 +
决策日志 + Smoke Ledger / Loop Ledger 各一行
- docs/research/README.md: 索引新增决策文档条目
验证: npm run test 3598/3598 全绿;smoke 4/4 contractMatch(1 个 fix cycle 收敛,
两处均为脚本层问题非 loop 差异);src/ 零改动(默认 Runtime/聊天路径零变化)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户批准 partial(2026-07-04, run issue op7418#10): 采用 ai@7/@ai-sdk/* 依赖升级、
provider 参数能力 capability-gated、openai-chat image wrapper、timeout 原因码/
approval HMAC/trace 脱敏四件套(默认值经用户确认); @ai-sdk/mcp adapter 与
ToolLoopAgent 默认 loop 替换均不采用(留实验路径)。发版前保留官方一方 key
smoke gate。冲突仅 ai-sdk-7 计划决策日志一处,union 双方条目解决。
五个 phase 全部经 hands-off loop 完成并 Codex accepted(issues op7418#1/op7418#6/op7418#7/op7418#8/op7418#10)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
canblmz1 pushed a commit to canblmz1/CodePilot that referenced this pull request Aug 28, 2026
…lease
prefix-safe-json 0.2.0 -> 0.4.3 (exact). 0.4.3 is a security patch
(GHSA-3xpw-9694-2xxp) fixing three root causes in the AI SDK adapter/gate
this integration depends on:
1. AiSdkStreamAdapter.push() used to silently drop every raw event once
it had already observed its own terminal, so late/contradictory
evidence for a call never reached the coordinator at all.
2. takeDecision() used to read a decision snapshot frozen at finish()
time instead of the coordinator's live diagnostics, so evidence
recorded after finish() but before that call's authority was consumed
was never consulted.
3. A raw event carrying conflicting id/toolCallId used to silently
prefer id instead of failing the stream closed.
No public API change - createAiSdkExecutionGuard()/push()/finish()/
takeDecision() and the ExecuteDecision/NonExecutableDecision shapes this
integration reads (action, toolCallId, reason) are unchanged, confirmed
directly against the installed package's .d.ts, not assumed.
Verified against the real 0.4.3 install (resolved version, and lockfile
integrity hash, both confirmed exactly 0.4.3):
- npx tsc --noEmit (full project): clean, 0 errors.
- src/__tests__/unit/execution-guard.test.ts: 16/16 passing, identical
to the 0.2.0 result.
Adds src/__tests__/unit/execution-guard-post-terminal-authority.test.ts,
answering the actual question this bump exists to answer: does this
integration's own code exercise the fix, not just "does the library
still pass its own tests." resolvePendingExecutions() in
execution-guard.ts reads `decisions` directly off guard.finish()'s own
return value in the same statement - it never calls takeDecision().
A fresh guard is created per step and is never reused once its finish()
is read, so there is no async gap between this integration's own
finish() call and its own decision consumption for GHSA-3xpw-9694-2xxp's
literal finish()-to-takeDecision() window to open in here.
What is live in this integration is root cause op7418#1: whether a
late/contradicting raw event that arrives before a step's own
resolvePendingExecutions() call - anywhere in that step's fullStream -
correctly revokes authority instead of being silently dropped by the
adapter. The new test proves that directly, through this repo's real
execution-guard.ts functions (createStepGuard/registerDeferredExecution/
resolvePendingExecutions - the exact call path agent-loop.ts uses), plus
a control case confirming the fix does not overcorrect a genuinely clean
step. A second test exercises the raw prefix-safe-json library
(createAiSdkExecutionGuard directly, real push/finish/takeDecision, no
synthetic decision object) to confirm the literal advisory scenario is
fixed at the library level.
package-lock.json regenerated with `npm install prefix-safe-json@0.4.3
--save-exact`, not hand-edited.
Sign up for freeto 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.

2 participants

@xuxu777xu@op7418
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' feat: Windows platform adaptation by xuxu777xu · Pull Request #1 · op7418/CodePilot · GitHub
Skip to content

feat: Windows platform adaptation - #1

Merged
op7418 merged 2 commits into
op7418:mainfrom
xuxu777xu:feat/windows-drive-switcher
Feb 7, 2026
Merged

feat: Windows platform adaptation#1
op7418 merged 2 commits into
op7418:mainfrom
xuxu777xu:feat/windows-drive-switcher

Conversation

@xuxu777xu

@xuxu777xuxuxu777xu commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

Summary

CodePilot 原本仅支持 macOS,本 PR 添加完整的 Windows 平台适配,使其可以在 Windows 上正常构建、运行和使用。

Changes

跨平台基础设施

  • 新增 src/lib/platform.ts:统一的跨平台工具模块,包含 Claude CLI 发现逻辑(Windows .cmd/.bat shell 处理、where/which 回退)、PATH 扩展(AppData/npm 等 Windows 路径)
  • 重构 src/app/api/claude-status/route.ts:移除硬编码的 Unix 路径,改用共享的 platform 工具
  • 重构 src/lib/claude-client.ts:同上,并确保 USERPROFILE 和扩展 PATH 在 SDK 子进程中可用

Electron 主进程

  • electron/main.ts
    • Windows 进程派生使用 windowsHide 防止控制台窗口闪烁
    • PATH 构建适配 Windows 分隔符(;)和目录结构(AppData/npm)
    • 窗口标题栏适配:macOS hiddenInset / Windows hidden + titleBarOverlay
    • 图标适配:Windows 使用 .ico
    • loadUserShellEnv() 跳过非 macOS 平台

构建配置

  • electron-builder.yml:新增 win + nsis 构建目标,支持自定义安装目录、桌面/开始菜单快捷方式
  • package.json:新增 electron:pack:win 脚本,原 electron:pack 改为平台无关
  • build/icon.ico:Windows 应用图标

UI 适配

  • src/components/chat/FolderPicker.tsx:新增盘符下拉切换器,解决 Windows 盘符根目录无法向上导航的问题
  • src/app/api/files/browse/route.ts:API 返回可用 Windows 盘符列表
  • src/components/skills/SkillsManager.tsx:修复 key 重复警告

Test plan

  • Windows 上 npm run electron:pack:win 构建成功
  • 安装后启动,Claude CLI 自动检测并连接
  • 标题栏样式正确(隐藏标题栏 + overlay 控制按钮)
  • FolderPicker 盘符切换正常工作
  • macOS 上 npm run electron:pack:mac 构建无回归

🤖 Generated with Claude Code

xuxu777xuand others added 2 commits February 7, 2026 13:29
When navigating to a drive root on Windows (e.g. C:\), path.dirname
returns itself, disabling the "go up" button and trapping the user on
that drive. This adds a compact dropdown next to the up button that
lists all available drives (auto-detected via fs.accessSync), allowing
quick switching between drives. macOS/Linux are unaffected (empty array,
dropdown not rendered).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add src/lib/platform.ts: cross-platform Claude CLI discovery
(candidate paths, .cmd/.bat shell handling, where/which fallback)
- Refactor claude-status route and claude-client to use shared platform utils
- Electron main: Windows process spawning (windowsHide), PATH construction
with AppData/npm dirs, titleBarOverlay, .ico icon support
- electron-builder.yml: add win/nsis build targets
- package.json: add electron:pack:win script
- FolderPicker: drive switcher dropdown for navigating between drives
- SkillsManager: fix duplicate key warning with filePath fallback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@xuxu777xuxuxu777xu changed the title feat: add Windows drive switcher in FolderPickerfeat: Windows platform adaptationFeb 7, 2026
@op7418
op7418 merged commit b819eb7 into op7418:mainFeb 7, 2026
op7418 added a commit that referenced this pull request Apr 12, 2026
…ion for Native Runtime
Two feature gaps where Native Runtime didn't match SDK Runtime, both
surfaced during post-hermes-upgrade manual testing:
── #1: Compression notification now human-readable ──
Before: chat/route.ts:402 emitted `message: 'context_compressed'` as
a machine string. useSSEStream's notification branch showed this raw
string in the status bar — users saw "context_compressed" flash by.
After: message is now `"Context compressed: N older messages summarized,
~X tokens saved"` with structured `stats: { messagesCompressed, tokensSaved }`
for future rich UI handling. Added `subtype: 'context_compressed'` for
dedicated frontend handlers.
── #3: AskUserQuestion tool for Native Runtime ──
Before: only SDK Runtime had AskUserQuestion (built into Claude Code CLI).
Native Runtime had no such tool, so the model could never ask structured
questions — the existing AskUserQuestionUI in PermissionPrompt.tsx was
unreachable dead UI code for Native Runtime users.
After:
- New builtin tool `src/lib/builtin-tools/ask-user-question.ts`
registered in index.ts, condition 'always'
- Zod schema: 1-6 questions, each with 1-6 options, optional multiSelect
- Execute receives answers from permission flow (injected by frontend)
and formats as Q/A pairs for the model
- permission-checker.ts: new ALWAYS_ASK_TOOLS set ensures AskUserQuestion
(and ExitPlanMode) always show UI even in trust mode — without this,
trust mode would auto-approve and return empty answers
- PermissionPrompt.tsx: NEVER_AUTO_APPROVE set prevents full_access mode
from auto-approving AskUserQuestion — the UI must render so the user
can answer
The data flow:
Model → AskUserQuestion({ questions }) → permission wrapper intercepts
→ SSE permission_request → frontend AskUserQuestionUI renders
→ user picks options → updatedInput({ questions, answers }) → tool
execute formats answers → model gets "Q: ... A: ..." string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KevinYoung-Kw referenced this pull request in KevinYoung-Kw/CodePilot Apr 15, 2026
**补充修复**
在 #1 斜杠命令保留已有文本的修复基础上,进一步确保选择命令后光标自动定位到输入框尾部,而不是默认的首部。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KevinYoung-Kw referenced this pull request in KevinYoung-Kw/CodePilot Apr 15, 2026
**补充修复**
在 #1 斜杠命令保留已有文本的修复基础上,进一步确保选择命令后光标自动定位到输入框尾部,而不是默认的首部。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
v0.56.x 计划 Phase 1:建立稳定性治理入口,并用当前源码重新核验 Notion/issue 列出的
7 个 issue(不采信 issue 自述根因)。
GitHub 侧(已在仓库生效,非本 commit 内容):
- 创建 milestone #1「v0.56.x Stability / Trust」。
- 创建 9 个治理 label:P0-crash-or-interrupt / P0-data-loss-risk / P1-runtime-session /
P1-context / P1-file-reference / P1-installer-update / P1-performance / needs-repro /
v0.57+ parking-lot。
- 给 #626/#628/#629/#632/#633/#634/#635 按复核结论打 milestone + 优先级 label。
本 commit 文件:
- .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml:bug 表单强制必填
版本/OS/runtime/provider-model/可复现/复现步骤/期望vs实际 + 影响面勾选;feature
表单注明 v0.56.x 冻结新功能 → v0.57+ parking-lot;config 关闭空白 issue + 冻结说明
与 Discussions 入口。
- .github/PULL_REQUEST_TEMPLATE.md:Summary / Repro+root cause / Changes / Tests /
Screenshots-logs / 自查清单(链到 CLAUDE.md 与 AGENTS.md,不复制维护)。
- .github/TRIAGE.md:对外冻结说明、label 体系、issue/PR triage 规则、自动化候选。
- v0.56.x-stability-trust.md:标 Phase 0 完成 + 新增「2026-06-19 Claude Code 源码复核」
表(7 issue 逐条 file:line 证据)。关键复核结论:
* #632 ">100%" 确认是未 clamp 的 ratio*100 显示 bug(RunCockpit.tsx:169 等),分母
contextWindow 不可靠;"跨会话串" 源码不成立。
* #629 空 assistant 已防护,残留真实 gap:is_error result 路径不清坏 sdk_session_id
(claude-client.ts:1908 先置 resultEmitted)。
* #635 截图-only,最强候选 = SDK runtime 无自生成 keepalive(claude-client.ts:1956),
慢 proxy 静默 >330s 被 idle abort(B-019)。
* #628 确认真实风险:@file origin path 在 MessageInput.tsx:161 丢失,body.mentions[]
送达但 route.ts 从不消费 → 写 .codepilot-uploads 副本,AI 改副本。
* #634 根因不成立——5 个 notify/schedule 工具均注册(builtin-tools/index.ts:250),
issue 引用的 UI 串不在当前源码(疑旧版);附带 Plan 模式 list_tasks 泄漏。
* #626 polling 排除(8h 间隔),候选 animate-pulse × backdrop-filter 重绘。
* #633 mac 无法复现;NSIS-only + 未签名 + 无 portable + CI 不验安装启动。
- issue-tracker.md:新增「v0.56.x 治理 issue」看板索引表(指向 plan 复核表,不重复分析)。
验证:docs-drift 通过;npm run test(hook)。Phase 1 验收(milestone/labels/模板/冻结
说明就绪)达成。下一步 Phase 2:按复核结论修 chat 主链路(上下文百分比语义、context-cost
不阻断发送、Codex 多模态发送、发送后清草稿)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: issue #632 报"上下文 >100% / 假百分比 / 压缩后跳变";Phase 1 源码复核确认是
真实显示 bug("跨会话串"不成立)。
Triage(当前源码): 用量百分比 = usage.ratio*100,在 RunCockpit.tsx 与
RunCockpitPopoverContent.tsx 两处直接渲染、未封顶;usage.ratio = used / contextWindow,
而 contextWindow 来自 sdkContextWindow ?? latestSdkContextWindow ?? catalogContextWindow
(useContextUsage.ts)。很多第三方 proxy 不上报 context_window → 落到静态 catalog 兜底
(一个猜测值),used 又会在压缩后跳变 → 百分比蹦到 200%/500%。根因是"拿不可信的分母
算百分比",不是上下文真的超了。
Fix:
- useContextUsage.ts: 新增 ContextUsageData.contextWindowTrusted —— 仅当 SDK/上游真实
上报窗口时为 true(catalog 兜底不算)。三个 return 分支(baseline / snapshot / no-baseline)
都按各自来源正确赋值。不可信时不把窗口喂给 buildContextUsageBreakdown,dot-matrix 退回
按已用 token 的构成比例,不编造容量。
- RunCockpit.tsx: hasFullCtx 增加 && usage.contextWindowTrusted —— 不可信时自动落到既有的
绝对已用 token 显示(触发按钮)/ showUnknownCapacityBlock 分支(浮层,已测试的"容量未知"
路径)。百分比文案 clamp ≤100%。
- RunCockpitPopoverContent.tsx: 浮层 header 百分比同样 clamp ≤100%(防可信窗口被 used 短暂
超过时仍蹦 >100%)。
语义验收: 输入框右下角不可信时只显示已用绝对值;浮层不可信时只显示已用 + 不同种类构成
比例(无百分比/remaining/unused/假总量);可信时百分比封顶 100%。
Verify: typecheck 通过;context-window-trusted.test.ts 6 条 source-pin + 既有
run-cockpit-unknown-capacity / context-dot-matrix / context-usage-walk / context-breakdown
全绿;全量单测 3366/3366。未做:真实 untrusted-window provider 会话的 CDP 视觉走查
(fix 把 untrusted 路由到既有已发布的"容量未知"分支,风险低;视觉走查列为后续)。
Guardrail: context-window-trusted.test.ts 钉死 trusted 派生只认 SDK 来源、不可信时不喂窗口、
hasFullCtx 必须 gate trusted、两处显示 clamp ≤100%,防回退到"拿 catalog 当真实分母算百分比"。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: Codex 复核 fix#1(b842628)后发现 P2 残留——文字已改成"只显示已用 token",
但输入框右下角触发按钮旁的 mini dot-bar 仍用 200K 兜底画出"用了多少/还剩多少"的容量
暗示,与"拿不到总长度就不显示容量"及 commit message 的"不编造容量"不一致。
Triage(当前源码): ContextDotMatrix.tsx 有 FALLBACK_CONTEXT_WINDOW=200_000,
minCellsPerKind=0(mini-bar)在窗口未知时用它当分母(:88);RunCockpit.tsx:200 的触发
按钮无条件渲染这个 mini-bar。所以即使 b842628 把文字降级为绝对已用,小条仍画假容量。
minCellsPerKind=0 全仓只有 RunCockpit 触发按钮一个调用方。
Fix:
- RunCockpit.tsx: mini-bar 用 {hasFullCtx && (...)} 包裹——仅在可信窗口下渲染容量小条;
不可信时触发按钮只剩绝对已用 token 文本(贴合"输入框右下角只显示已用数值")。
- ContextDotMatrix.tsx: 删除 FALLBACK_CONTEXT_WINDOW(200K)。窗口未知时两种模式都按
used+pending 分配(构成视图,非容量%),不再编造容量。
Verify: typecheck 通过;context-dot-matrix.test.ts 旧的"unknown mini-bar 用 200K 兜底
(filled<=2)"语义改为新的"used 构成(filled>=8)";context-window-trusted.test.ts 加 2 条
guardrail(mini-bar gate 在 hasFullCtx + 源码无 200K 兜底残留);全量单测 3368/3368。
Guardrail: 两条 source-pin 钉死"触发按钮 mini-bar 必须 gate 在 hasFullCtx"且"ContextDotMatrix
不得再出现 FALLBACK_CONTEXT_WINDOW/200_000",防回退到拿假容量画小条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
用户复核 fix#1 后明确显示格式:输入框右下角的上下文小标,在有可信窗口时显示
"百分比 + 已用上下文"(如 56.6% 452K),没有可信窗口时只显示已用(如 452K),
不单列"剩余"数字。
改动:RunCockpit.tsx 触发按钮 ratioText 的可信分支由 "{pct}%" 改为
"{pct}% {used}"(1 位小数,匹配用户给的 56.6% 示例);不可信/无数据分支不变。
context-window-trusted.test.ts 的 clamp pin 扩为同时断言"百分比 + 已用"格式。
验证:dev 应用热重载干净(✓ Compiled);context-window-trusted 8/8;typecheck(hook)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: 用户在运行的应用里看到 GLM-5-turbo(Claude Code/Native 会话)仍显示总上下文
200K,指出"这并不是我们知道的部分"。fix#1 本应让 catalog 静态值不可信、只显示已用。
Triage(当前源码,用户 review 驱动): agent-loop.ts:641-651(Native)在 token_usage
没有 context_window 时,从静态 catalog 填 totalUsage.context_window = getContextWindow(modelId)
(GLM-5-turbo 在 catalog 是 z.ai 核实的 202752)。而 context-usage-walk 把
token_usage.context_window 当作 SDK 实报窗口读,fix#1 的 contextWindowTrusted 据此判可信
→ catalog 猜测被"洗白"成可信 → Native GLM 显示 200K。即上游 mutator 打败了 helper 修复
(feedback_fix_all_consumers)。claude-client(Claude Code)只从 SDK modelUsage 写,不洗白;
ContextUsageIndicator 是死组件(无人 import)。
Fix: 删掉 agent-loop 的 catalog 洗白。Native 无 runtime 实报时 context_window 留空 →
useContextUsage 回落 catalog 为不可信 → 只显示已用绝对值,不再有假百分比/假总量。
仅对新 turn 生效(历史消息已存的 context_window 不改写,遵守不改用户数据;旧会话发新消息后转为已用-only)。
Verify: typecheck;context-window-trusted.test.ts 新增 pin 断言 agent-loop 不再
`.context_window = catalogWindow`;该文件 9 测 + agent-loop-error-event 全过。运行中 dev 应用
server 重编译干净(Native GLM 需发新消息验证)。
Guardrail: source-pin 防 Native 再把 catalog 洗进 SDK-authoritative 字段。
设计记录(用户批准"先记计划再实现"): v0.56.x 计划写入 context-window 来源优先级修订设计
(runtime 实报 > provider 配置 contextWindow > 压缩阈值 > catalog 不可信)+ 跨 Runtime 用户
配置源(#1,待实现) + 显示分母对齐压缩阈值(#3,待实现)。本提交是设计第一步(去洗白)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
把"为什么 GLM 显示 200K + 窗口来源该怎么改"写成评审稿放进 v0.56.x Phase 2,按
外部事实 / 本地证据(file:line) / 推断与设计三层分写,供 Codex 核实。
要点:
- Agent SDK v0.2.111 的 modelUsage.contextWindow(sdk.d.ts:945)是未文档化字段,来自
SDK 内置模型目录而非 API;第一方可靠、第三方(经 base_url 的 GLM)返回通用默认值;
无 SDK 设置可覆盖;Anthropic 建议自维护窗口表。
- 实测 GLM 会话 token_usage.context_window=200000 ≠ 本地 catalog 202752,证实来自 SDK
默认而非 catalog/Native 洗白;该会话是 Claude Code(故上一提交的 Native 修复不覆盖它)。
- 修订设计:窗口来源优先级 = 用户覆盖 > 已核实 catalog/provider 配置 > SDK(仅第一方) >
只显示已用;第三方忽略 SDK 默认值;跨 Runtime;显示分母对齐压缩阈值(#3)。
- 列出待定决策(已核实优先 vs 纯手动) + 给 Codex 的 5 个核实点。
未改任何产品代码(纯文档)。#1/#3 实现待 Codex 核实后进行。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Codex 复核设计稿后订正(实现 #1/#3 前必须):
- A:原"官方文档不记载 contextWindow/maxOutputTokens"不准 → 改为 SDK TypeScript
reference 有字段定义,是 cost-tracking 指南未解释来源/可信度。
- B/C:原"catalog 202752 比 SDK 200000 更准且 z.ai 核实"站不住 → z.ai 官方写
200K/128K,catalog 该条来源存疑;结论收敛为"SDK 200000 不可作为 provider 实报采信",
不延伸到"catalog 更准";另标记需单独核 model-context.ts:42 的真实来源。
- D + 决策日志:统一优先级(消除冲突,旧决策日志把第三方 SDK 又洗白成可信)→
用户手动覆盖 > provider/model 配置且来源已验证 > 第一方 runtime 实报 > 只显示已用;
第三方 SDK contextWindow 默认不可信、无明确来源 catalog 不当可信%显示。
- "Anthropic 官方建议自维护表"未核到原文 → 降级为工程结论。
- 澄清:用户实际看到 200K 的 GLM 会话是 Claude Code(SDK 默认 200000),非 Native 洗白
路径(681706b 的 Native 修复有效但治另一条路径)。
- E:决策收敛为一条基线 + 剩余一项请用户定(第一方 SDK 实报是否自动显示百分比)。
Codex 核为真的部分(sdk.d.ts:945 字段、代码写入 token_usage、历史 SDK 窗口被当可信、
Native 洗白已去、显示分母 vs 压缩阈值脱节)保留。纯文档,未动产品代码。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
F 段核实点 #1 还残留旧"官方文档未记载(A)",与已订正的 A 段不一致。改为:
sdk.d.ts:945 的 contextWindow/maxOutputTokens 存在,SDK TypeScript reference 已列,
只是 cost-tracking 指南未解释来源/可信度。纯文档。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
… Phase 2 ①)
Signal: 用户 GLM-5-turbo(Claude Code 经代理)显示总上下文 200K,且 Codex 核实 SDK 的
modelUsage.contextWindow 来自 SDK 内置目录、对第三方是通用默认值、无 SDK 设置可覆盖。
Triage: claude-client.ts extractTokenUsage 把 SDK modelUsage.contextWindow 无条件写入
token_usage.context_window;walk + fix#1 据此判可信 → 第三方代理(GLM)的 SDK 默认 200000
被当可信显示。Native 的 catalog 洗白已于 681706b 去掉;本提交补 SDK 路径。
Fix(Codex 统一口径"第一方 runtime 实报可信、第三方不可信"):
- ai-provider.ts 导出 isFirstPartyAnthropicEndpoint(baseUrl)(空/anthropic.com → 第一方)。
- extractTokenUsage 增 trustContextWindow,仅 true 时写 context_window;两个调用点都传
isFirstPartyAnthropicEndpoint(resolved.provider?.base_url)。第三方(自定义 base_url,如 GLM)
→ 不写 context_window → useContextUsage 回落 catalog 为不可信 → 只显示已用。
效果 + 边界: 第一方 Anthropic 继续显示百分比+已用;第三方代理新 turn 起只显示已用。
仅对新写入生效(历史消息已存的 context_window 不改写,遵守不改用户数据);现有 GLM 会话
仍显示旧值,需新会话/新 turn 验证(walk 会读历史,故旧会话需自然滚动出旧窗口或新建)。
Verify: typecheck;extract-token-usage-context-window.test.ts 增 2 pin(gate + 两调用点传
第一方判别);全量 3371/3371。
Guardrail: source-pin 钉死 context_window 写入受 trustContextWindow 门控 + 两调用点必须传
isFirstPartyAnthropicEndpoint,防回退到无条件信任第三方 SDK 窗口。
remaining(Phase 2 ①/③ 未完): provider/model 配置窗口作为最高优先可信源(用户覆盖) + 渲染层
对现有会话按第一方 gate(治旧会话) + #3 显示分母对齐压缩阈值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
计划文档状态审计修正(决策日志准、但概览层过期):
- frontmatter 状态行:📋 待接手 → 🚧 Phase 0/1 已完成、Phase 2 进行中。
- 「状态总览」表:Phase 1 待开始 → ✅ 已完成(2026-06-19);Phase 2 待开始 → 🚧 进行中。
- Phase 2 加进度 note:Composer/Context 主链路 #1#5 全部收口(含 commit + #3 真实
Codex 冒烟回复 circle);Session/Stream cluster #629/#635 + 终态原因码 + 压缩回滚
+ 诊断导出字段待续。
- Phase 2 执行清单 4 项已完成项 [ ]→[x](上下文 UI 语义 / context-cost 去阻断 /
Codex 多模态发送 / 发送后草稿清理)。
CLAUDE.md 执行计划段新增「完成即回写进度(与 Codex 对齐协作)」:任一 Phase/子项做完
必须立即回写三处且一致——执行清单勾选 / 状态总览表+frontmatter / 决策日志(commit
+验证结论);Claude 实施+回写、Codex 审查+维护;三者不一致视为状态失真须先对齐。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
打回上一条状态同步的一处失真:我把 #4/#5「发送后内容残留」标成完成(checklist [x] +
进度 note 列为 done),但同一文档决策日志(2026-06-20 条)已写明用户再次确认"内容已发出
但文本仍残留输入框"、#615 source-pin 不覆盖该症状、不能算闭环——状态表/清单与决策日志
自相矛盾,违反刚加的"三者必须一致"。
修正(与决策日志对齐):
- checklist「复现并修发送后内容残留」[x] → [ ],标注"待复核/待修复(用户 2026-06-20 再报)"。
- Phase 2 进度 note:拆分——#4/#5 仅失败保留有基础修复(#615),发送成功后文本残留待复核;
note 标题从"主链路已收口"改为"#1#3 收口、#4/#5 待复核";待续列表补回 #4/#5(重新打开)。
- #2 context-cost 非阻断保持完成(checklist [x] + note)不变。
后续修 #4/#5 时重点:PromptInput 受控/非受控清空边界、setInputValue('') 与
controller.textInput.clear() 是否同源、成功 accepted 后 remount/local draft 恢复、
badge/confirm/image 分支与普通 Enter 分支是否一致(决策日志已记排查方向)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
按"完成即回写进度"规则同步三处:
- checklist「复现并修发送后内容残留」[ ]→[x],标注已修 + CDP 验证 + 根因/修法(58c7aad)。
- Phase 2 进度 note:#1#5 全部落地;#4/#5 从"待复核"改为"已定位+修复"(含根因/CDP 结论);
待续列表移除 #4/#5、只留 Session/Stream cluster。
- 决策日志加同日条目:CDP 埋点定位 = 首条消息 accept 布局翻转 remount composer、inputValue
从 sessionStorage 草稿重读;修法 = accept 处清草稿;3401/3401 + CDP 文本/图文首条 800ms 即清。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
用户在浏览器实测不残留、仅桌面 App 残留 → Claude 协助完整重启 electron:dev(kill 整棵
进程树 + 释放 3000 + 后台重启)→ 用户在重启后真实 App 验证发送即清空 → #4/#5 闭环。
根因:58c7aad(page.tsx accept 处清首条草稿)一直是对的;用户残留是 Electron dev 没把
page.tsx 改动热更新进 renderer、窗口刷新无效,得整进程重启。这解释了全程「Claude CDP
浏览器清、用户残留」的矛盾——不是 Electron 行为差异,是构建新鲜度差异(Claude 浏览器硬刷
过有修复、用户 Electron 旧构建没有)。
回写:checklist [x](用户真实 App 验证)、进度 note #1#5 全闭环、验收去 ⚠️、决策日志加
闭环条目 + 教训(UI 修复在桌面 App 验证必须整重启 electron:dev)。Codex P1(prefill/
initialValue 回灌)仍是 58c7aad 的真实独立漏洞、值得单独补,与本次残留无关。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
纯文档同步,无代码改动。目的:让下一个进程打开文档时不从旧状态误判进度。
三处状态表此前已标 Phase 0/1 ✅、决策日志也已确认完成,唯独执行清单 checkbox
与 README 索引、issue-tracker #632 仍停在旧值——三处不一致即状态失真,本次对齐。
README.md:
- v0.56.x 索引行状态列 "📋 待 Phase 0 收束" → "🚧 Phase 0/1 ✅;Phase 2 进行中
(Composer/Context 主链路 #1#5 闭环,Session/Stream cluster #629/#635 待续)",
追上 plan frontmatter 与决策日志。
v0.56.x-stability-trust.md:
- Phase 0 执行清单 8 项 [ ]→[x],逐条带回溯(3360/3360、9c6e772、f99edbb/d00449f)。
A2 计时器项如实标注:按 keyed-remount 构造性消除 + 截图不可判别记录入 Smoke Ledger,
非逐帧视觉确认(反假数据,不谎称做了视觉确认)。
- Phase 1 执行清单 5 项 [ ]→[x],带回溯(milestone #1 / 9 labels / .github/TRIAGE.md)。
issue-tracker.md:
- #632 状态 "🔴 待修" → "🟡 假%已修,item3 分母对齐待续"。核心显示 bug(假百分比/>100%)
已由 effective-base-URL 写入 gate + 渲染期 trusted gate + clamp 修复并经真实 GLM
会话验证;item3(显示分母对齐压缩阈值)是独立待续阶段,故标部分修复而非已修复。
- 顶部"最后更新"同步到 2026-06-26 + #632 同步说明。
验证:git diff 确认仅 3 文档、16/16 行 checkbox 与状态文字,无代码/意外文件。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jul 4, 2026
- docs/research/ai-sdk-7-toolloop-parity-gaps.md: 新增「Phase 5 处置」节,全部 gap
收口——P1×3 关闭(#1/#2 补偿由 parity 8/8 复跑锁定;#3 降级论证:Phase 4 已证
approval HMAC 不需要 SDK toolApproval 停机语义,维持 in-execute 路线),
P2/P3 关闭或 backlog(#4/#5 列为替换路线前置条件,#7 归档 tech-debt #49#8 有 Phase 5 新实证)
- scripts/smoke-ai-sdk7-phase5-decision.ts: 新增决策门对照 smoke——prod runAgentLoop
与 POC runToolLoopAgentPoc 用同一 AgentLoopOptions 逐场景对照(长文本 / approval
批准 / approval 拒绝 / abort→continue),机械比较归一化事件序列 + 尾部契约 +
usage 存在性;DB 只读、数据目录隔离、输出全 scrub。探针注意:approval 批准分支
用 printf(echo 命中 permission-checker 自动放行规则不会触发 ask)
- docs/exec-plans/active/_smoke-evidence/ai-sdk7-phase5-decision-smoke.json:
OpenRouter 真实渠道 4/4 场景 contractMatch=true(input_tokens 逐场景完全相同,
tool_result 逐字相同,中断轮双侧 done 收尾、同 session 续发一次通过);
凭据形态 grep=0
- docs/research/ai-sdk-7-adoption-decision.md: 新增采用决策文档——结论 partial
(依赖升级 go / provider 能力 capability-gated go / Phase 4 外围能力 go /
@ai-sdk/mcp 与默认 loop 替换 no-go-现在),四层 rollback plan(能力开关→
wrapper→runtime switch→known-good version),每项结论标注 Phase 1-5 证据来源;
默认 Runtime 切换留人类闸门
- docs/exec-plans/tech-debt-tracker.md: 新增 #49(tool-error part 被两条 loop
一致吞掉的既有 UX 债,独立于采用决策)
- docs/exec-plans/active/ai-sdk-7-runtime-loop-adoption.md: Phase 5 状态回写 +
决策日志 + Smoke Ledger / Loop Ledger 各一行
- docs/research/README.md: 索引新增决策文档条目
验证: npm run test 3598/3598 全绿;smoke 4/4 contractMatch(1 个 fix cycle 收敛,
两处均为脚本层问题非 loop 差异);src/ 零改动(默认 Runtime/聊天路径零变化)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jul 4, 2026
用户批准 partial(2026-07-04, run issue #10): 采用 ai@7/@ai-sdk/* 依赖升级、
provider 参数能力 capability-gated、openai-chat image wrapper、timeout 原因码/
approval HMAC/trace 脱敏四件套(默认值经用户确认); @ai-sdk/mcp adapter 与
ToolLoopAgent 默认 loop 替换均不采用(留实验路径)。发版前保留官方一方 key
smoke gate。冲突仅 ai-sdk-7 计划决策日志一处,union 双方条目解决。
五个 phase 全部经 hands-off loop 完成并 Codex accepted(issues #1/#6/#7/#8/#10)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ion for Native Runtime
Two feature gaps where Native Runtime didn't match SDK Runtime, both
surfaced during post-hermes-upgrade manual testing:
── op7418#1: Compression notification now human-readable ──
Before: chat/route.ts:402 emitted `message: 'context_compressed'` as
a machine string. useSSEStream's notification branch showed this raw
string in the status bar — users saw "context_compressed" flash by.
After: message is now `"Context compressed: N older messages summarized,
~X tokens saved"` with structured `stats: { messagesCompressed, tokensSaved }`
for future rich UI handling. Added `subtype: 'context_compressed'` for
dedicated frontend handlers.
── op7418#3: AskUserQuestion tool for Native Runtime ──
Before: only SDK Runtime had AskUserQuestion (built into Claude Code CLI).
Native Runtime had no such tool, so the model could never ask structured
questions — the existing AskUserQuestionUI in PermissionPrompt.tsx was
unreachable dead UI code for Native Runtime users.
After:
- New builtin tool `src/lib/builtin-tools/ask-user-question.ts`
registered in index.ts, condition 'always'
- Zod schema: 1-6 questions, each with 1-6 options, optional multiSelect
- Execute receives answers from permission flow (injected by frontend)
and formats as Q/A pairs for the model
- permission-checker.ts: new ALWAYS_ASK_TOOLS set ensures AskUserQuestion
(and ExitPlanMode) always show UI even in trust mode — without this,
trust mode would auto-approve and return empty answers
- PermissionPrompt.tsx: NEVER_AUTO_APPROVE set prevents full_access mode
from auto-approving AskUserQuestion — the UI must render so the user
can answer
The data flow:
Model → AskUserQuestion({ questions }) → permission wrapper intercepts
→ SSE permission_request → frontend AskUserQuestionUI renders
→ user picks options → updatedInput({ questions, answers }) → tool
execute formats answers → model gets "Q: ... A: ..." string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ge generation results
GPT-Image-2.0 skill silent failure had two compounding causes both
on the 'tool result' loop:
P0 op7418#1 — function_call_output translated with sentinel toolName
translate-input.ts wrote toolName: '__from_responses_proxy__' for every
tool-result and the comment claimed 'ai-sdk doesn't use this for
routing'. That was wrong. Anthropic and OpenAI Responses both look
up the tool definition by tool-result.toolName when reconciling the
result with the request's tool surface; with a sentinel they can't
correlate and refuse to produce the continuation turn — exactly the
'tool ran, no follow-up text' the user saw.
Fix: walk the input array once first to build call_id → toolName
from function_call items, then look up the real name when translating
function_call_output. Orphan results (no matching function_call) fall
back to a named sentinel '__orphan_function_call_output__' AND emit
console.warn naming the call_id. The divergence stays loud.
P0 op7418#2 — imageGeneration / imageView silently dropped
event-mapper.ts had both item types in CHAT_ONLY_ITEM_TYPES, which
returns null on item/started + item/completed. That set is correct
for agentMessage/plan/reasoning (they have streaming delta channels
so the content arrives separately), but imageGeneration / imageView
have NO delta channel — their final item is the only surface where
the result reaches the user. Silent drop meant 'tool ran' with no
visible image.
Fix: move both types to TOOL_LIKE_ITEM_TYPES, add explicit
translateItemStarted branches with names image_generation /
image_view, and the existing TOOL_LIKE_ITEM_TYPES completion branch
already packs the full item into output — preserving result,
savedPath, revisedPrompt, path for chat-side rendering.
ThreadItemLike grew matching fields so TS doesn't downgrade access
to (item as { path?: string }).path casts.
Tests (8 new)
src/__tests__/unit/codex-proxy-translators.test.ts (+3):
- toolName resolves from matching function_call (gpt_image_2 case)
- toolName resolves correctly with interleaved out-of-order calls
- orphan function_call_output → named sentinel + console.warn
src/__tests__/unit/codex-event-mapper.test.ts (+4):
- imageGeneration item/started → tool_started(name='image_generation')
- imageGeneration item/completed → tool_completed with full
result + savedPath + revisedPrompt payload
- imageView item/started → tool_started(name='image_view') + path
- imageView item/completed → tool_completed with path preserved
src/__tests__/unit/codex-proxy-tool-contract.test.ts (+1):
- End-to-end continuation: function_call → function_call_output →
streamText(messages) — MockLanguageModelV3 must see toolName
'gpt_image_2' in its prompt, NOT '__from_responses_proxy__'.
Continuation text-delta event fires.
The mapper-side translate also removed the chatOnly array's
imageView / imageGeneration entries from the old 'returns null'
parameterised test; replaced with the new lifecycle describe block.
Closeout doc records round 7 ✅ items; remaining must-haves
unchanged (4-family smoke matrix + codex-sdk POC).
All 2416 tests pass (was 2412 + 8 new − 4 obsolete from the chatOnly
table for imageView/imageGeneration).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ce 2a
Direction approved; three sharpenings folded into the existing
Phase 2 plan structure without restructuring.
1. Widget wire-format single source (review revision op7418#1)
slice 7's WIDGET_SYSTEM_PROMPT template-literal-embeds
WIDGET_WIRE_FORMAT_SPEC. With artifactContracts ordered BEFORE
capabilityFragments in the compiler, the wire spec would land in
the final system prompt twice (once from artifactContract, once
from the capability fragment tail). The plan now declares hard
constraints — CANONICAL_SHOW_WIDGET_JSON, the "FINAL OUTPUT
FORMAT" title, and WIDGET_WIRE_FORMAT_SPEC each must appear
exactly once in the compiled system prompt — and assigns slice
2c a small refactor that strips the wire spec from
WIDGET_SYSTEM_PROMPT so artifactContract becomes the sole holder.
Compile-time sanity check (capability fragment text MUST NOT
contain artifactContract.canonicalJson) added as a defence-in-
depth FAIL path.
2. Expected Differences Ledger (review revision op7418#2)
2b's "compiler output === Runtime current prompt" stance
directly conflicted with slice 2d's plan to canonicalize Native
memory / notify / media-import paraphrases. Equivalence reading
strictly would have locked the old drift in. Plan now introduces
`src/lib/harness/expected-differences.ts` with typed entries
(runtimeId, capability, diff kind, justification,
plannedResolution, compilerSource, runtimeSource). 2b harness
reads "compiler vs runtime diff ⊆ ledger"; unregistered
differences fail. Initial ledger seeded with the four known
Phase 5c slice 7b tech-debt items, three earmarked for slice 2d
and one (image_generation MediaBlock shape) earmarked
follow_up. Slice 2d completion = manual ledger entry removal
(deliberate non-automation, preserves audit trail).
3. runtimeHints boundary (review revision op7418#3)
Plan tightens the runtimeHints type declaration so it cannot
become a fourth prompt-assembly point. Allowed: IDs (mcp server
names, tool keys, builtin tool name set), fragmentIds refs into
CompiledContext, adapter options (stopWhen / stepCount /
passthroughToolTypes). Forbidden: any prompt text string, tool
description paraphrase, capability redefinition. Three test
layers — type-level (string fields ≤ 64 chars, no newline / no
markdown), runtime-level (no template-literal-shaped values),
source-grep level (no multi-line template literals in
runtimeHints assignments) — plus a dangling-reference check
that every fragmentId in runtimeHints resolves in
CompiledContext.
Regression test list extended 9 → 12. Decision log records all
three revisions with rationale.
Plan still in 📋 status. No code; awaiting Codex re-review on the
revised draft, then slice 2a opens.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
User mode change: "internal slice order preserved, external single
delivery; stop only after Phase 2 is done; Codex review takes the
batch." This commit lands slices 2a–2e together with all post-
review hardenings (Widget wire-format single source, Expected
Differences Ledger, runtimeHints prose ban).
Internal slice walk
2a — context-compiler.ts (NEW)
Pure function `compileContext(input): CompiledContext`. No IO,
no provider calls. Resolves enabledCapabilities (null = catalog
live default), looks up exposure for the calling runtime, emits
capabilityFragments + artifactContracts + memory + workspace +
toolDescriptors + runtimeHints + budget + systemPromptText +
diagnostics. Hard contracts: artifactContract before capability
in the assembled prompt; fragmentId uniqueness; cross-runtime
fragment text identity; compile-time FAIL if a capability
fragment text contains an artifact contract canonicalJson
(wire-format dedup); compile-time FAIL if load-bearing fragments
exceed budget. runtimeHints types strictly ID/refs/adapter
options — no prose, no template literals.
2b — expected-differences.ts (NEW)
Drift ledger. Initial 4 entries from slice 7b tech-debt. Three
slice_2d entries consumed by this commit (see 2d below); the
one remaining `follow_up` is image_generation MediaBlock shape
(non-prompt, future slice).
2c — ClaudeCode SDK (claude-client.ts) source-pin only
The SDK path has always imported MCP canonicals directly
(memory-search-mcp, notification-mcp, media-import-mcp,
cli-tools-mcp, dashboard-mcp) — no paraphrase ever existed.
Slice 2c codifies this with a contract test: claude-client.ts
must not import capability prompts from builtin-tools/* and
must not declare its own _SYSTEM_PROMPT scalars.
2d — Native Runtime (builtin-tools/*) re-export MCP canonicals
`memory-search.ts` now `export const MEMORY_SEARCH_SYSTEM_PROMPT =
CANONICAL_MEMORY_SEARCH_SYSTEM_PROMPT` (imported from
memory-search-mcp.ts). Same pattern for `notification.ts`
(NOTIFICATION_SYSTEM_PROMPT = NOTIFICATION_MCP_SYSTEM_PROMPT)
and `media.ts` (MEDIA_SYSTEM_PROMPT = MEDIA_MCP_SYSTEM_PROMPT
from media-import-mcp.ts). Three ledger entries removed in
sync.
2e — Codex bridge (builtin-bridge.ts + unified-adapter.ts)
Bridge no longer holds WIDGET_PROMPT / MEDIA_PROMPT /
MEMORY_PROMPT / NOTIFY_PROMPT scalars (all four declarations
deleted). `createCodePilotBuiltinTools().systemPrompt` is
permanently `''`. `unified-adapter.ts` now calls
`compileContext({ runtimeId: 'codex_runtime', ... })` and feeds
`compiled.systemPromptText` to Codex's `instructions`. A new
helper `capabilitiesFromBridgeToolNames` maps the bridge's
mounted tool names back to capability ids so the compiler's
enabledCapabilities aligns with what the bridge actually
exposes (workspace-gated memory tools naturally drop out when
workspacePath is empty).
Slice 2c Widget wire-format single source (review revision op7418#1)
WIDGET_SYSTEM_PROMPT in widget-guidelines.ts no longer
template-literal-embeds `${WIDGET_WIRE_FORMAT_SPEC}`. The
artifactContract is now the sole holder of the wire-format spec
+ canonical JSON. Compiler's `detectWireFormatDuplication` sanity
check throws at compile time if any capability fragment text
contains the artifact contract canonicalJson — that's the forcing
function preventing the spec from being re-injected.
Three regression pins enforce single occurrence in the compiled
prompt: CANONICAL_SHOW_WIDGET_JSON × 1, "FINAL OUTPUT FORMAT —
non-negotiable" × 1, WIDGET_WIRE_FORMAT_SPEC × 1.
runtimeHints boundary (review revision op7418#3)
ClaudeCodeHints / NativeHints / CodexProxyHints types now carry
only IDs (mcp server names, tool keys, builtin tool name set) +
adapter options (stopWhen, stepCount, passthroughToolTypes).
Tests pin: type-level (no string field > 64 chars, no newline,
no Markdown markers), runtime-level (scan all string values for
prose), source-grep (CodexProxyHints type definition can't
contain `promptOverride` / `promptExtra` / `widgetPrompt` / etc).
Tests
New harness-context-compiler.test.ts (23 pins): catalog hygiene,
Widget wire-format single source (op7418#10), ordering, budget
enforcement, cross-runtime fragment identity (op7418#9), tool
descriptors, runtimeHints boundary (op7418#11), Expected Differences
Ledger consistency (op7418#12), JSON parseability of every artifact
contract.
New harness-context-compiler-equivalence.test.ts (9 pins):
compiler source reachability, runtime drift honesty,
ledger/slice ownership correctness, "post-slice-2d: Native
ledger holds only the follow_up MediaBlock entry".
Updated harness-capability-contract.test.ts: drift pins now
check (a) bridge holds no local _PROMPT scalars, (b) Native
builtin-tools re-export MCP canonicals, (c) unified-adapter
imports compileContext + consumes systemPromptText, (d)
claude-client.ts doesn't import from builtin-tools/* and
doesn't declare own _SYSTEM_PROMPT.
Updated codex-widget-format-contract.test.ts: the "WIDGET_SYSTEM_PROMPT
embeds WIDGET_WIRE_FORMAT_SPEC" and "appears inside
WIDGET_SYSTEM_PROMPT" pins are flipped — slice 2c REMOVED the
embed; the new pins verify the compiler-side import line.
Updated codex-builtin-bridge.test.ts: tests previously asserting
`bridge.systemPrompt` contained capability tags now assert it
equals `''` (bridge is no longer the prompt-assembly point).
Verification
CODEX_DISABLED=1 npx tsx --test \
src/__tests__/unit/harness-context-compiler.test.ts \
src/__tests__/unit/harness-context-compiler-equivalence.test.ts \
src/__tests__/unit/harness-capability-contract.test.ts \
src/__tests__/unit/codex-widget-format-contract.test.ts \
src/__tests__/unit/codex-builtin-bridge.test.ts
→ 74/74 pass
npm run test → 2576/2576 pass
Completion criteria check (per user spec)
[x] npm run test all green (2576/2576)
[x] Context Compiler unit tests all green
[x] equivalence / expected-diff harness all green
[x] harness-capability-contract / codex-widget-format /
codex-builtin-bridge tests all green
[x] no new runtime-local prompt duplicates (Native re-exports
canonical; ClaudeCode imports canonical; bridge holds none)
[x] Codex bridge no longer holds WIDGET_PROMPT / MEDIA_PROMPT /
MEMORY_PROMPT / NOTIFY_PROMPT scalars (all four removed,
drift test pins their absence)
[x] all three Runtimes adapt compiler output, none redefine
capability prompts
Docs
- phase-5d-phase-2-context-compiler.md: slice statuses 2a–2e all
✅ 2026-05-17; note the one-shot delivery mode change.
- phase-5d-harness-capability-contract.md: Phase 2 row ✅, awaiting
Codex review.
- handover/harness-capability-contract.md: new "Context Compiler"
section detailing inputs/outputs/constraints, three-runtime
consumption pattern, Expected Differences Ledger contract.
- refactor-closeout.md: new decision-log entry recording the
Phase 2 delivery shape + completion criteria check.
Phase 5d Phase 2 ✅ pending Codex review. Phase 3 (Runtime
Capability Adapter) / Phase 4 (Artifact Contract) / Phase 5
(new-Runtime Playbook) intentionally NOT opened — stopping per
user instruction.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
… to breakdown
## 用户视角
升级前:popover 的"文件与附件 / 本次待加入"两行永远 0 —— 数据通道没接通。即使 composer 里挂了 4 个 mention 和 2 个目录引用,popover breakdown 显示 0。
升级后:MessageInput → ChatView/page → RunCockpit → useContextUsage → buildContextUsageBreakdown 全链路联通。composer 里的 attachment / mention / directory 实时累加到对应类别。trigger 上的迷你点阵 + popover 主条 + 列表行三处同步更新。
发送消息后 pending 归 0;下一轮 history 里的真实 token_usage 接管 used 部分;conversation 类自动吸收。
## 不做什么
- 不改 hook 其他字段(used / ratio / state / source 等不动)
- 不改 trigger 主结构(百分比文字仍在;只有点阵 cells 在分配时反映 pending)
- 不改 composer text 估算(composerTextTokens 仍 0;那是 Phase 3+ 的事)
## 怎么验收
- npm run test → 2921/2921 pass
- composer 里加附件 / @mention / "+" 目录 → trigger 上 pending 部分立刻有虚线 cells
- 发送消息 → pending 归零;下轮 used cells 更新
## 改动(6 文件)
### src/lib/message-input-logic.ts
新增 `PendingContextSubTotals` interface + `computePendingContextSubTotals()` 函数。逻辑 mirror `computePendingContextTokens`(同样的 null 过滤、同样的迭代顺序),但返回 { attachment, mention, directory } 三键。两个函数加起来 = 等于 computePendingContextTokens 总数。
### src/hooks/useContextUsage.ts
options 加可选 `pending?: { attachmentTokens?, mentionTokens?, directoryTokens?, composerTextTokens? }`。三条返回路径(snapshot / walk / noData)都把 options?.pending 转发给 buildContextUsageBreakdown。useMemo deps 数组加 options?.pending。
### src/components/chat/RunCockpit.tsx
RunCockpitProps 加可选 `pendingContextSubTotals?: { attachment, mention, directory }`。组件内部把它转换成 hook options.pending 形态(attachment → attachmentTokens 等)。可选 prop 默认 undefined → 不破坏现有 callsites。
### src/components/chat/MessageInput.tsx
- import 加 computePendingContextSubTotals + PendingContextSubTotals type
- props 加可选 `onPendingContextSubTotalsChange?` callback(跟现有 onPendingContextTokensChange 并列)
- 新增 useMemo 算 pendingContextSubTotals + useEffect emit callback
- 与现有 pendingContextTokens 走同一份 source 数据,逻辑同步无 divergence
### src/components/chat/ChatView.tsx
- 加 state `pendingContextSubTotals` (PendingContextSubTotals | undefined)
- MessageInput 上 wire `onPendingContextSubTotalsChange={setPendingContextSubTotals}`
- RunCockpit 上传 `pendingContextSubTotals={pendingContextSubTotals}`
### src/app/chat/page.tsx
- 跟 ChatView 完全镜像:state + MessageInput callback + RunCockpit prop
- 两个入口独立持有 state(按 StreamSession guardrail 不变量 op7418#1)
## Scope discipline
- 不新增测试(Codex 负责测试覆盖;用户分工已明确)
- 不动 buildContextUsageBreakdown / computePendingContextTokens 既有签名 → 旧调用 zero-risk
- 不改 chat-static-graph 排除清单 → MessageInput / RunCockpit 改动属于增量 prop,没新依赖链
- composerTextTokens 仍未 wire(composer 纯文本估算属于未来扩展,pending_next_turn 行暂时仍 0)
## StreamSession guardrail 合规
- 双入口(page.tsx 首消息 + ChatView 后续)独立 state — 不变量 op7418#1 ✅
- onSend / onCommand 签名不变 — rewind point 不变量 op7418#2 ✅
- 不动 capability cache — 不变量 op7418#3 ✅
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…18#31)
Codex review second round caught two real P1 inconsistencies introduced by
the Dashboard/CLI split slice plus non-blocking contract drift.
P1.1 — Dashboard injection gate ≠ route auth gate.
runtime.ts injected the dashboard read/write MCPs whenever prompt + working
directory + dashboard keyword matched, but the route's `authorize` requires
`sameRealPath(workspacePath, assistant_workspace_path)`. Mismatch → the model
sees the tool and Codex 403s at call time. Fix: dashboard injection mirrors
memory's gate exactly (same sameRealPath check, same `assistantWorkspacePath`
passed as `workspacePath`) so "inject" and "route-authorize" never disagree.
CLI tools don't need this (no workspace scope).
P1.2 — Matrix promoted only for codex_account; runtime injects for ALL
codex_runtime providers.
The runtime didn't gate injection by provider, so under a CodePilot proxy
provider the dashboard/cli MCPs WERE injected (callable), but the matrix
returned `perception_only` for non-codex_account — the opposite drift from
P1.1 ("model says yes, Settings says no"). Fix per Codex's preferred option:
move the promotion into `capabilityMatrixForRuntime` so it applies to ALL
codex_runtime providers; `capabilityMatrixForRuntimeProvider` now only adds
codex_account-specific overrides (native notes + image/media demotion).
`buildCapabilityMatrix` delegates to `capabilityMatrixForRuntime` so every
matrix entry point stays aligned.
Non-blocking op7418#1 — contract text drift.
capability-contract.ts dashboard/cli `deferredReason` + `codex_proxy.notes`
rewritten — explicit that the LEGACY provider-proxy bridge is unsupported
(true), and that the codex_runtime path now ships via the mutation-level MCP
split + matrix-layer promotion. No schema changes (`kind: 'unsupported'`
stays accurate for the legacy bridge surface); the existing matrix invariant
test gets a `MATRIX_LAYER_PROMOTIONS` exception list documenting why the two
promoted cells are allowed to be executable despite `kind: 'unsupported'`.
Schema cleanup (introduce a new `mcp_server_split` kind, drop the exception
list) tracked as tech-debt op7418#33.
Non-blocking op7418#2 — elicitation policy pins.
codex-mcp-events.test.ts now pins all 4 new server names:
codepilot_{dashboard,cli_tools}_read → auto_accept,
codepilot_{dashboard,cli_tools}_write → user_approval.
Also added a regression guard: `codex_runtime + non-codex_account provider`
must STILL show dashboard/cli_tools executable with mixed trust + the right
noteKey. Updated the two pre-existing tests that asserted the OLD behaviour
(dashboard/cli perception_only on codex_runtime) — they now assert the
promoted state. Also synced the static `CAPABILITY_EXECUTABLE_RUNTIMES` map.
Per Codex review's explicit ask: the "待真账号 smoke" wording stays in the
op7418#31 capability table — this commit fixes the inconsistencies, but the
real-account end-to-end smoke for natural-conversation triggering + write
approval card + Deny blocking is still owed by the user.
Full unit suite 3045/3045. Live route: bad workspace still 403 (auth gate
intact); tools/list subsets unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Codex review 认可方向,按 5 条反馈修订(纯文档,无代码):
- Phase A 增"开工前核验"(Opus 4.8 官方 model id / context window / thinking·effort / 1M beta,不臆测)
- Phase A 实现范围增"泛化 Opus 4.7 专属逻辑"(isOpus47Model / OPUS_4_7_PATTERN / applyContext1mBeta /
effort 门控 / claude-client sanitizer,配回归测试)—— catalog 显示 ≠ 请求正确
- OpenRouter Opus 4.8 改 deferred(不臆测 slug),首轮只接 Anthropic direct
- opus 别名 / 默认先不动(仍 4.7),只新增显式 claude-opus-4-8,切换待 smoke 后用户拍板
- Phase D 拆 D0/D:D0 把 apply-discovery-diff 全量 flake + no-verify 事件记入 tech-debt op7418#30(本提交即 D0);
D 建议先于 A/B/C,代码 phase 不再靠 --no-verify
- Open Questions op7418#1/op7418#2 据上述决议收敛
本提交纯文档;pre-commit 同样因 apply-discovery-diff 全量 flake 用 --no-verify,已确认 docs-drift 绿。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
v0.56.x 计划 Phase 1:建立稳定性治理入口,并用当前源码重新核验 Notion/issue 列出的
7 个 issue(不采信 issue 自述根因)。
GitHub 侧(已在仓库生效,非本 commit 内容):
- 创建 milestone op7418#1「v0.56.x Stability / Trust」。
- 创建 9 个治理 label:P0-crash-or-interrupt / P0-data-loss-risk / P1-runtime-session /
P1-context / P1-file-reference / P1-installer-update / P1-performance / needs-repro /
v0.57+ parking-lot。
- 给 op7418#626/op7418#628/op7418#629/op7418#632/op7418#633/op7418#634/op7418#635 按复核结论打 milestone + 优先级 label。
本 commit 文件:
- .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml:bug 表单强制必填
版本/OS/runtime/provider-model/可复现/复现步骤/期望vs实际 + 影响面勾选;feature
表单注明 v0.56.x 冻结新功能 → v0.57+ parking-lot;config 关闭空白 issue + 冻结说明
与 Discussions 入口。
- .github/PULL_REQUEST_TEMPLATE.md:Summary / Repro+root cause / Changes / Tests /
Screenshots-logs / 自查清单(链到 CLAUDE.md 与 AGENTS.md,不复制维护)。
- .github/TRIAGE.md:对外冻结说明、label 体系、issue/PR triage 规则、自动化候选。
- v0.56.x-stability-trust.md:标 Phase 0 完成 + 新增「2026-06-19 Claude Code 源码复核」
表(7 issue 逐条 file:line 证据)。关键复核结论:
* op7418#632 ">100%" 确认是未 clamp 的 ratio*100 显示 bug(RunCockpit.tsx:169 等),分母
contextWindow 不可靠;"跨会话串" 源码不成立。
* op7418#629 空 assistant 已防护,残留真实 gap:is_error result 路径不清坏 sdk_session_id
(claude-client.ts:1908 先置 resultEmitted)。
* op7418#635 截图-only,最强候选 = SDK runtime 无自生成 keepalive(claude-client.ts:1956),
慢 proxy 静默 >330s 被 idle abort(B-019)。
* op7418#628 确认真实风险:@file origin path 在 MessageInput.tsx:161 丢失,body.mentions[]
送达但 route.ts 从不消费 → 写 .codepilot-uploads 副本,AI 改副本。
* op7418#634 根因不成立——5 个 notify/schedule 工具均注册(builtin-tools/index.ts:250),
issue 引用的 UI 串不在当前源码(疑旧版);附带 Plan 模式 list_tasks 泄漏。
* op7418#626 polling 排除(8h 间隔),候选 animate-pulse × backdrop-filter 重绘。
* op7418#633 mac 无法复现;NSIS-only + 未签名 + 无 portable + CI 不验安装启动。
- issue-tracker.md:新增「v0.56.x 治理 issue」看板索引表(指向 plan 复核表,不重复分析)。
验证:docs-drift 通过;npm run test(hook)。Phase 1 验收(milestone/labels/模板/冻结
说明就绪)达成。下一步 Phase 2:按复核结论修 chat 主链路(上下文百分比语义、context-cost
不阻断发送、Codex 多模态发送、发送后清草稿)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…e 2 op7418#1)
Signal: issue op7418#632 报"上下文 >100% / 假百分比 / 压缩后跳变";Phase 1 源码复核确认是
真实显示 bug("跨会话串"不成立)。
Triage(当前源码): 用量百分比 = usage.ratio*100,在 RunCockpit.tsx 与
RunCockpitPopoverContent.tsx 两处直接渲染、未封顶;usage.ratio = used / contextWindow,
而 contextWindow 来自 sdkContextWindow ?? latestSdkContextWindow ?? catalogContextWindow
(useContextUsage.ts)。很多第三方 proxy 不上报 context_window → 落到静态 catalog 兜底
(一个猜测值),used 又会在压缩后跳变 → 百分比蹦到 200%/500%。根因是"拿不可信的分母
算百分比",不是上下文真的超了。
Fix:
- useContextUsage.ts: 新增 ContextUsageData.contextWindowTrusted —— 仅当 SDK/上游真实
上报窗口时为 true(catalog 兜底不算)。三个 return 分支(baseline / snapshot / no-baseline)
都按各自来源正确赋值。不可信时不把窗口喂给 buildContextUsageBreakdown,dot-matrix 退回
按已用 token 的构成比例,不编造容量。
- RunCockpit.tsx: hasFullCtx 增加 && usage.contextWindowTrusted —— 不可信时自动落到既有的
绝对已用 token 显示(触发按钮)/ showUnknownCapacityBlock 分支(浮层,已测试的"容量未知"
路径)。百分比文案 clamp ≤100%。
- RunCockpitPopoverContent.tsx: 浮层 header 百分比同样 clamp ≤100%(防可信窗口被 used 短暂
超过时仍蹦 >100%)。
语义验收: 输入框右下角不可信时只显示已用绝对值;浮层不可信时只显示已用 + 不同种类构成
比例(无百分比/remaining/unused/假总量);可信时百分比封顶 100%。
Verify: typecheck 通过;context-window-trusted.test.ts 6 条 source-pin + 既有
run-cockpit-unknown-capacity / context-dot-matrix / context-usage-walk / context-breakdown
全绿;全量单测 3366/3366。未做:真实 untrusted-window provider 会话的 CDP 视觉走查
(fix 把 untrusted 路由到既有已发布的"容量未知"分支,风险低;视觉走查列为后续)。
Guardrail: context-window-trusted.test.ts 钉死 trusted 派生只认 SDK 来源、不可信时不喂窗口、
hasFullCtx 必须 gate trusted、两处显示 clamp ≤100%,防回退到"拿 catalog 当真实分母算百分比"。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Signal: Codex 复核 fixop7418#1(9ea29a4)后发现 P2 残留——文字已改成"只显示已用 token",
但输入框右下角触发按钮旁的 mini dot-bar 仍用 200K 兜底画出"用了多少/还剩多少"的容量
暗示,与"拿不到总长度就不显示容量"及 commit message 的"不编造容量"不一致。
Triage(当前源码): ContextDotMatrix.tsx 有 FALLBACK_CONTEXT_WINDOW=200_000,
minCellsPerKind=0(mini-bar)在窗口未知时用它当分母(:88);RunCockpit.tsx:200 的触发
按钮无条件渲染这个 mini-bar。所以即使 9ea29a4 把文字降级为绝对已用,小条仍画假容量。
minCellsPerKind=0 全仓只有 RunCockpit 触发按钮一个调用方。
Fix:
- RunCockpit.tsx: mini-bar 用 {hasFullCtx && (...)} 包裹——仅在可信窗口下渲染容量小条;
不可信时触发按钮只剩绝对已用 token 文本(贴合"输入框右下角只显示已用数值")。
- ContextDotMatrix.tsx: 删除 FALLBACK_CONTEXT_WINDOW(200K)。窗口未知时两种模式都按
used+pending 分配(构成视图,非容量%),不再编造容量。
Verify: typecheck 通过;context-dot-matrix.test.ts 旧的"unknown mini-bar 用 200K 兜底
(filled<=2)"语义改为新的"used 构成(filled>=8)";context-window-trusted.test.ts 加 2 条
guardrail(mini-bar gate 在 hasFullCtx + 源码无 200K 兜底残留);全量单测 3368/3368。
Guardrail: 两条 source-pin 钉死"触发按钮 mini-bar 必须 gate 在 hasFullCtx"且"ContextDotMatrix
不得再出现 FALLBACK_CONTEXT_WINDOW/200_000",防回退到拿假容量画小条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户复核 fixop7418#1 后明确显示格式:输入框右下角的上下文小标,在有可信窗口时显示
"百分比 + 已用上下文"(如 56.6% 452K),没有可信窗口时只显示已用(如 452K),
不单列"剩余"数字。
改动:RunCockpit.tsx 触发按钮 ratioText 的可信分支由 "{pct}%" 改为
"{pct}% {used}"(1 位小数,匹配用户给的 56.6% 示例);不可信/无数据分支不变。
context-window-trusted.test.ts 的 clamp pin 扩为同时断言"百分比 + 已用"格式。
验证:dev 应用热重载干净(✓ Compiled);context-window-trusted 8/8;typecheck(hook)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…llow-up)
Signal: 用户在运行的应用里看到 GLM-5-turbo(Claude Code/Native 会话)仍显示总上下文
200K,指出"这并不是我们知道的部分"。fixop7418#1 本应让 catalog 静态值不可信、只显示已用。
Triage(当前源码,用户 review 驱动): agent-loop.ts:641-651(Native)在 token_usage
没有 context_window 时,从静态 catalog 填 totalUsage.context_window = getContextWindow(modelId)
(GLM-5-turbo 在 catalog 是 z.ai 核实的 202752)。而 context-usage-walk 把
token_usage.context_window 当作 SDK 实报窗口读,fixop7418#1 的 contextWindowTrusted 据此判可信
→ catalog 猜测被"洗白"成可信 → Native GLM 显示 200K。即上游 mutator 打败了 helper 修复
(feedback_fix_all_consumers)。claude-client(Claude Code)只从 SDK modelUsage 写,不洗白;
ContextUsageIndicator 是死组件(无人 import)。
Fix: 删掉 agent-loop 的 catalog 洗白。Native 无 runtime 实报时 context_window 留空 →
useContextUsage 回落 catalog 为不可信 → 只显示已用绝对值,不再有假百分比/假总量。
仅对新 turn 生效(历史消息已存的 context_window 不改写,遵守不改用户数据;旧会话发新消息后转为已用-only)。
Verify: typecheck;context-window-trusted.test.ts 新增 pin 断言 agent-loop 不再
`.context_window = catalogWindow`;该文件 9 测 + agent-loop-error-event 全过。运行中 dev 应用
server 重编译干净(Native GLM 需发新消息验证)。
Guardrail: source-pin 防 Native 再把 catalog 洗进 SDK-authoritative 字段。
设计记录(用户批准"先记计划再实现"): v0.56.x 计划写入 context-window 来源优先级修订设计
(runtime 实报 > provider 配置 contextWindow > 压缩阈值 > catalog 不可信)+ 跨 Runtime 用户
配置源(op7418#1,待实现) + 显示分母对齐压缩阈值(op7418#3,待实现)。本提交是设计第一步(去洗白)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
把"为什么 GLM 显示 200K + 窗口来源该怎么改"写成评审稿放进 v0.56.x Phase 2,按
外部事实 / 本地证据(file:line) / 推断与设计三层分写,供 Codex 核实。
要点:
- Agent SDK v0.2.111 的 modelUsage.contextWindow(sdk.d.ts:945)是未文档化字段,来自
SDK 内置模型目录而非 API;第一方可靠、第三方(经 base_url 的 GLM)返回通用默认值;
无 SDK 设置可覆盖;Anthropic 建议自维护窗口表。
- 实测 GLM 会话 token_usage.context_window=200000 ≠ 本地 catalog 202752,证实来自 SDK
默认而非 catalog/Native 洗白;该会话是 Claude Code(故上一提交的 Native 修复不覆盖它)。
- 修订设计:窗口来源优先级 = 用户覆盖 > 已核实 catalog/provider 配置 > SDK(仅第一方) >
只显示已用;第三方忽略 SDK 默认值;跨 Runtime;显示分母对齐压缩阈值(op7418#3)。
- 列出待定决策(已核实优先 vs 纯手动) + 给 Codex 的 5 个核实点。
未改任何产品代码(纯文档)。op7418#1/op7418#3 实现待 Codex 核实后进行。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Codex 复核设计稿后订正(实现 op7418#1/op7418#3 前必须):
- A:原"官方文档不记载 contextWindow/maxOutputTokens"不准 → 改为 SDK TypeScript
reference 有字段定义,是 cost-tracking 指南未解释来源/可信度。
- B/C:原"catalog 202752 比 SDK 200000 更准且 z.ai 核实"站不住 → z.ai 官方写
200K/128K,catalog 该条来源存疑;结论收敛为"SDK 200000 不可作为 provider 实报采信",
不延伸到"catalog 更准";另标记需单独核 model-context.ts:42 的真实来源。
- D + 决策日志:统一优先级(消除冲突,旧决策日志把第三方 SDK 又洗白成可信)→
用户手动覆盖 > provider/model 配置且来源已验证 > 第一方 runtime 实报 > 只显示已用;
第三方 SDK contextWindow 默认不可信、无明确来源 catalog 不当可信%显示。
- "Anthropic 官方建议自维护表"未核到原文 → 降级为工程结论。
- 澄清:用户实际看到 200K 的 GLM 会话是 Claude Code(SDK 默认 200000),非 Native 洗白
路径(f79fd54 的 Native 修复有效但治另一条路径)。
- E:决策收敛为一条基线 + 剩余一项请用户定(第一方 SDK 实报是否自动显示百分比)。
Codex 核为真的部分(sdk.d.ts:945 字段、代码写入 token_usage、历史 SDK 窗口被当可信、
Native 洗白已去、显示分母 vs 压缩阈值脱节)保留。纯文档,未动产品代码。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
F 段核实点 op7418#1 还残留旧"官方文档未记载(A)",与已订正的 A 段不一致。改为:
sdk.d.ts:945 的 contextWindow/maxOutputTokens 存在,SDK TypeScript reference 已列,
只是 cost-tracking 指南未解释来源/可信度。纯文档。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…#632 / Phase 2 ①)
Signal: 用户 GLM-5-turbo(Claude Code 经代理)显示总上下文 200K,且 Codex 核实 SDK 的
modelUsage.contextWindow 来自 SDK 内置目录、对第三方是通用默认值、无 SDK 设置可覆盖。
Triage: claude-client.ts extractTokenUsage 把 SDK modelUsage.contextWindow 无条件写入
token_usage.context_window;walk + fixop7418#1 据此判可信 → 第三方代理(GLM)的 SDK 默认 200000
被当可信显示。Native 的 catalog 洗白已于 f79fd54 去掉;本提交补 SDK 路径。
Fix(Codex 统一口径"第一方 runtime 实报可信、第三方不可信"):
- ai-provider.ts 导出 isFirstPartyAnthropicEndpoint(baseUrl)(空/anthropic.com → 第一方)。
- extractTokenUsage 增 trustContextWindow,仅 true 时写 context_window;两个调用点都传
isFirstPartyAnthropicEndpoint(resolved.provider?.base_url)。第三方(自定义 base_url,如 GLM)
→ 不写 context_window → useContextUsage 回落 catalog 为不可信 → 只显示已用。
效果 + 边界: 第一方 Anthropic 继续显示百分比+已用;第三方代理新 turn 起只显示已用。
仅对新写入生效(历史消息已存的 context_window 不改写,遵守不改用户数据);现有 GLM 会话
仍显示旧值,需新会话/新 turn 验证(walk 会读历史,故旧会话需自然滚动出旧窗口或新建)。
Verify: typecheck;extract-token-usage-context-window.test.ts 增 2 pin(gate + 两调用点传
第一方判别);全量 3371/3371。
Guardrail: source-pin 钉死 context_window 写入受 trustContextWindow 门控 + 两调用点必须传
isFirstPartyAnthropicEndpoint,防回退到无条件信任第三方 SDK 窗口。
remaining(Phase 2 ①/③ 未完): provider/model 配置窗口作为最高优先可信源(用户覆盖) + 渲染层
对现有会话按第一方 gate(治旧会话) + op7418#3 显示分母对齐压缩阈值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
计划文档状态审计修正(决策日志准、但概览层过期):
- frontmatter 状态行:📋 待接手 → 🚧 Phase 0/1 已完成、Phase 2 进行中。
- 「状态总览」表:Phase 1 待开始 → ✅ 已完成(2026-06-19);Phase 2 待开始 → 🚧 进行中。
- Phase 2 加进度 note:Composer/Context 主链路 op7418#1op7418#5 全部收口(含 commit + op7418#3 真实
Codex 冒烟回复 circle);Session/Stream cluster op7418#629/op7418#635 + 终态原因码 + 压缩回滚
+ 诊断导出字段待续。
- Phase 2 执行清单 4 项已完成项 [ ]→[x](上下文 UI 语义 / context-cost 去阻断 /
Codex 多模态发送 / 发送后草稿清理)。
CLAUDE.md 执行计划段新增「完成即回写进度(与 Codex 对齐协作)」:任一 Phase/子项做完
必须立即回写三处且一致——执行清单勾选 / 状态总览表+frontmatter / 决策日志(commit
+验证结论);Claude 实施+回写、Codex 审查+维护;三者不一致视为状态失真须先对齐。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
打回上一条状态同步的一处失真:我把 op7418#4/op7418#5「发送后内容残留」标成完成(checklist [x] +
进度 note 列为 done),但同一文档决策日志(2026-06-20 条)已写明用户再次确认"内容已发出
但文本仍残留输入框"、op7418#615 source-pin 不覆盖该症状、不能算闭环——状态表/清单与决策日志
自相矛盾,违反刚加的"三者必须一致"。
修正(与决策日志对齐):
- checklist「复现并修发送后内容残留」[x] → [ ],标注"待复核/待修复(用户 2026-06-20 再报)"。
- Phase 2 进度 note:拆分——op7418#4/op7418#5 仅失败保留有基础修复(op7418#615),发送成功后文本残留待复核;
note 标题从"主链路已收口"改为"op7418#1op7418#3 收口、op7418#4/op7418#5 待复核";待续列表补回 op7418#4/op7418#5(重新打开)。
- op7418#2 context-cost 非阻断保持完成(checklist [x] + note)不变。
后续修 op7418#4/op7418#5 时重点:PromptInput 受控/非受控清空边界、setInputValue('') 与
controller.textInput.clear() 是否同源、成功 accepted 后 remount/local draft 恢复、
badge/confirm/image 分支与普通 Enter 分支是否一致(决策日志已记排查方向)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
按"完成即回写进度"规则同步三处:
- checklist「复现并修发送后内容残留」[ ]→[x],标注已修 + CDP 验证 + 根因/修法(de123df)。
- Phase 2 进度 note:op7418#1op7418#5 全部落地;op7418#4/op7418#5 从"待复核"改为"已定位+修复"(含根因/CDP 结论);
待续列表移除 op7418#4/op7418#5、只留 Session/Stream cluster。
- 决策日志加同日条目:CDP 埋点定位 = 首条消息 accept 布局翻转 remount composer、inputValue
从 sessionStorage 草稿重读;修法 = accept 处清草稿;3401/3401 + CDP 文本/图文首条 800ms 即清。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户在浏览器实测不残留、仅桌面 App 残留 → Claude 协助完整重启 electron:dev(kill 整棵
进程树 + 释放 3000 + 后台重启)→ 用户在重启后真实 App 验证发送即清空 → op7418#4/op7418#5 闭环。
根因:de123df(page.tsx accept 处清首条草稿)一直是对的;用户残留是 Electron dev 没把
page.tsx 改动热更新进 renderer、窗口刷新无效,得整进程重启。这解释了全程「Claude CDP
浏览器清、用户残留」的矛盾——不是 Electron 行为差异,是构建新鲜度差异(Claude 浏览器硬刷
过有修复、用户 Electron 旧构建没有)。
回写:checklist [x](用户真实 App 验证)、进度 note op7418#1op7418#5 全闭环、验收去 ⚠️、决策日志加
闭环条目 + 教训(UI 修复在桌面 App 验证必须整重启 electron:dev)。Codex P1(prefill/
initialValue 回灌)仍是 de123df 的真实独立漏洞、值得单独补,与本次残留无关。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
纯文档同步,无代码改动。目的:让下一个进程打开文档时不从旧状态误判进度。
三处状态表此前已标 Phase 0/1 ✅、决策日志也已确认完成,唯独执行清单 checkbox
与 README 索引、issue-tracker op7418#632 仍停在旧值——三处不一致即状态失真,本次对齐。
README.md:
- v0.56.x 索引行状态列 "📋 待 Phase 0 收束" → "🚧 Phase 0/1 ✅;Phase 2 进行中
(Composer/Context 主链路 op7418#1op7418#5 闭环,Session/Stream cluster op7418#629/op7418#635 待续)",
追上 plan frontmatter 与决策日志。
v0.56.x-stability-trust.md:
- Phase 0 执行清单 8 项 [ ]→[x],逐条带回溯(3360/3360、dd4ead4、b853188/2de9c2b)。
A2 计时器项如实标注:按 keyed-remount 构造性消除 + 截图不可判别记录入 Smoke Ledger,
非逐帧视觉确认(反假数据,不谎称做了视觉确认)。
- Phase 1 执行清单 5 项 [ ]→[x],带回溯(milestone op7418#1 / 9 labels / .github/TRIAGE.md)。
issue-tracker.md:
- op7418#632 状态 "🔴 待修" → "🟡 假%已修,item3 分母对齐待续"。核心显示 bug(假百分比/>100%)
已由 effective-base-URL 写入 gate + 渲染期 trusted gate + clamp 修复并经真实 GLM
会话验证;item3(显示分母对齐压缩阈值)是独立待续阶段,故标部分修复而非已修复。
- 顶部"最后更新"同步到 2026-06-26 + op7418#632 同步说明。
验证:git diff 确认仅 3 文档、16/16 行 checkbox 与状态文字,无代码/意外文件。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
- docs/research/ai-sdk-7-toolloop-parity-gaps.md: 新增「Phase 5 处置」节,全部 gap
收口——P1×3 关闭(op7418#1/op7418#2 补偿由 parity 8/8 复跑锁定;op7418#3 降级论证:Phase 4 已证
approval HMAC 不需要 SDK toolApproval 停机语义,维持 in-execute 路线),
P2/P3 关闭或 backlog(op7418#4/op7418#5 列为替换路线前置条件,op7418#7 归档 tech-debt op7418#49op7418#8 有 Phase 5 新实证)
- scripts/smoke-ai-sdk7-phase5-decision.ts: 新增决策门对照 smoke——prod runAgentLoop
与 POC runToolLoopAgentPoc 用同一 AgentLoopOptions 逐场景对照(长文本 / approval
批准 / approval 拒绝 / abort→continue),机械比较归一化事件序列 + 尾部契约 +
usage 存在性;DB 只读、数据目录隔离、输出全 scrub。探针注意:approval 批准分支
用 printf(echo 命中 permission-checker 自动放行规则不会触发 ask)
- docs/exec-plans/active/_smoke-evidence/ai-sdk7-phase5-decision-smoke.json:
OpenRouter 真实渠道 4/4 场景 contractMatch=true(input_tokens 逐场景完全相同,
tool_result 逐字相同,中断轮双侧 done 收尾、同 session 续发一次通过);
凭据形态 grep=0
- docs/research/ai-sdk-7-adoption-decision.md: 新增采用决策文档——结论 partial
(依赖升级 go / provider 能力 capability-gated go / Phase 4 外围能力 go /
@ai-sdk/mcp 与默认 loop 替换 no-go-现在),四层 rollback plan(能力开关→
wrapper→runtime switch→known-good version),每项结论标注 Phase 1-5 证据来源;
默认 Runtime 切换留人类闸门
- docs/exec-plans/tech-debt-tracker.md: 新增 op7418#49(tool-error part 被两条 loop
一致吞掉的既有 UX 债,独立于采用决策)
- docs/exec-plans/active/ai-sdk-7-runtime-loop-adoption.md: Phase 5 状态回写 +
决策日志 + Smoke Ledger / Loop Ledger 各一行
- docs/research/README.md: 索引新增决策文档条目
验证: npm run test 3598/3598 全绿;smoke 4/4 contractMatch(1 个 fix cycle 收敛,
两处均为脚本层问题非 loop 差异);src/ 零改动(默认 Runtime/聊天路径零变化)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户批准 partial(2026-07-04, run issue op7418#10): 采用 ai@7/@ai-sdk/* 依赖升级、
provider 参数能力 capability-gated、openai-chat image wrapper、timeout 原因码/
approval HMAC/trace 脱敏四件套(默认值经用户确认); @ai-sdk/mcp adapter 与
ToolLoopAgent 默认 loop 替换均不采用(留实验路径)。发版前保留官方一方 key
smoke gate。冲突仅 ai-sdk-7 计划决策日志一处,union 双方条目解决。
五个 phase 全部经 hands-off loop 完成并 Codex accepted(issues op7418#1/op7418#6/op7418#7/op7418#8/op7418#10)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
canblmz1 pushed a commit to canblmz1/CodePilot that referenced this pull request Aug 28, 2026
…lease
prefix-safe-json 0.2.0 -> 0.4.3 (exact). 0.4.3 is a security patch
(GHSA-3xpw-9694-2xxp) fixing three root causes in the AI SDK adapter/gate
this integration depends on:
1. AiSdkStreamAdapter.push() used to silently drop every raw event once
it had already observed its own terminal, so late/contradictory
evidence for a call never reached the coordinator at all.
2. takeDecision() used to read a decision snapshot frozen at finish()
time instead of the coordinator's live diagnostics, so evidence
recorded after finish() but before that call's authority was consumed
was never consulted.
3. A raw event carrying conflicting id/toolCallId used to silently
prefer id instead of failing the stream closed.
No public API change - createAiSdkExecutionGuard()/push()/finish()/
takeDecision() and the ExecuteDecision/NonExecutableDecision shapes this
integration reads (action, toolCallId, reason) are unchanged, confirmed
directly against the installed package's .d.ts, not assumed.
Verified against the real 0.4.3 install (resolved version, and lockfile
integrity hash, both confirmed exactly 0.4.3):
- npx tsc --noEmit (full project): clean, 0 errors.
- src/__tests__/unit/execution-guard.test.ts: 16/16 passing, identical
to the 0.2.0 result.
Adds src/__tests__/unit/execution-guard-post-terminal-authority.test.ts,
answering the actual question this bump exists to answer: does this
integration's own code exercise the fix, not just "does the library
still pass its own tests." resolvePendingExecutions() in
execution-guard.ts reads `decisions` directly off guard.finish()'s own
return value in the same statement - it never calls takeDecision().
A fresh guard is created per step and is never reused once its finish()
is read, so there is no async gap between this integration's own
finish() call and its own decision consumption for GHSA-3xpw-9694-2xxp's
literal finish()-to-takeDecision() window to open in here.
What is live in this integration is root cause op7418#1: whether a
late/contradicting raw event that arrives before a step's own
resolvePendingExecutions() call - anywhere in that step's fullStream -
correctly revokes authority instead of being silently dropped by the
adapter. The new test proves that directly, through this repo's real
execution-guard.ts functions (createStepGuard/registerDeferredExecution/
resolvePendingExecutions - the exact call path agent-loop.ts uses), plus
a control case confirming the fix does not overcorrect a genuinely clean
step. A second test exercises the raw prefix-safe-json library
(createAiSdkExecutionGuard directly, real push/finish/takeDecision, no
synthetic decision object) to confirm the literal advisory scenario is
fixed at the library level.
package-lock.json regenerated with `npm install prefix-safe-json@0.4.3
--save-exact`, not hand-edited.
Sign up for freeto 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.

2 participants

@xuxu777xu@op7418
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat: Windows platform adaptation by xuxu777xu · Pull Request #1 · op7418/CodePilot · GitHub
Skip to content

feat: Windows platform adaptation - #1

Merged
op7418 merged 2 commits into
op7418:mainfrom
xuxu777xu:feat/windows-drive-switcher
Feb 7, 2026
Merged

feat: Windows platform adaptation#1
op7418 merged 2 commits into
op7418:mainfrom
xuxu777xu:feat/windows-drive-switcher

Conversation

@xuxu777xu

@xuxu777xuxuxu777xu commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

Summary

CodePilot 原本仅支持 macOS,本 PR 添加完整的 Windows 平台适配,使其可以在 Windows 上正常构建、运行和使用。

Changes

跨平台基础设施

  • 新增 src/lib/platform.ts:统一的跨平台工具模块,包含 Claude CLI 发现逻辑(Windows .cmd/.bat shell 处理、where/which 回退)、PATH 扩展(AppData/npm 等 Windows 路径)
  • 重构 src/app/api/claude-status/route.ts:移除硬编码的 Unix 路径,改用共享的 platform 工具
  • 重构 src/lib/claude-client.ts:同上,并确保 USERPROFILE 和扩展 PATH 在 SDK 子进程中可用

Electron 主进程

  • electron/main.ts
    • Windows 进程派生使用 windowsHide 防止控制台窗口闪烁
    • PATH 构建适配 Windows 分隔符(;)和目录结构(AppData/npm)
    • 窗口标题栏适配:macOS hiddenInset / Windows hidden + titleBarOverlay
    • 图标适配:Windows 使用 .ico
    • loadUserShellEnv() 跳过非 macOS 平台

构建配置

  • electron-builder.yml:新增 win + nsis 构建目标,支持自定义安装目录、桌面/开始菜单快捷方式
  • package.json:新增 electron:pack:win 脚本,原 electron:pack 改为平台无关
  • build/icon.ico:Windows 应用图标

UI 适配

  • src/components/chat/FolderPicker.tsx:新增盘符下拉切换器,解决 Windows 盘符根目录无法向上导航的问题
  • src/app/api/files/browse/route.ts:API 返回可用 Windows 盘符列表
  • src/components/skills/SkillsManager.tsx:修复 key 重复警告

Test plan

  • Windows 上 npm run electron:pack:win 构建成功
  • 安装后启动,Claude CLI 自动检测并连接
  • 标题栏样式正确(隐藏标题栏 + overlay 控制按钮)
  • FolderPicker 盘符切换正常工作
  • macOS 上 npm run electron:pack:mac 构建无回归

🤖 Generated with Claude Code

xuxu777xuand others added 2 commits February 7, 2026 13:29
When navigating to a drive root on Windows (e.g. C:\), path.dirname
returns itself, disabling the "go up" button and trapping the user on
that drive. This adds a compact dropdown next to the up button that
lists all available drives (auto-detected via fs.accessSync), allowing
quick switching between drives. macOS/Linux are unaffected (empty array,
dropdown not rendered).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add src/lib/platform.ts: cross-platform Claude CLI discovery
(candidate paths, .cmd/.bat shell handling, where/which fallback)
- Refactor claude-status route and claude-client to use shared platform utils
- Electron main: Windows process spawning (windowsHide), PATH construction
with AppData/npm dirs, titleBarOverlay, .ico icon support
- electron-builder.yml: add win/nsis build targets
- package.json: add electron:pack:win script
- FolderPicker: drive switcher dropdown for navigating between drives
- SkillsManager: fix duplicate key warning with filePath fallback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@xuxu777xuxuxu777xu changed the title feat: add Windows drive switcher in FolderPickerfeat: Windows platform adaptationFeb 7, 2026
@op7418
op7418 merged commit b819eb7 into op7418:mainFeb 7, 2026
op7418 added a commit that referenced this pull request Apr 12, 2026
…ion for Native Runtime
Two feature gaps where Native Runtime didn't match SDK Runtime, both
surfaced during post-hermes-upgrade manual testing:
── #1: Compression notification now human-readable ──
Before: chat/route.ts:402 emitted `message: 'context_compressed'` as
a machine string. useSSEStream's notification branch showed this raw
string in the status bar — users saw "context_compressed" flash by.
After: message is now `"Context compressed: N older messages summarized,
~X tokens saved"` with structured `stats: { messagesCompressed, tokensSaved }`
for future rich UI handling. Added `subtype: 'context_compressed'` for
dedicated frontend handlers.
── #3: AskUserQuestion tool for Native Runtime ──
Before: only SDK Runtime had AskUserQuestion (built into Claude Code CLI).
Native Runtime had no such tool, so the model could never ask structured
questions — the existing AskUserQuestionUI in PermissionPrompt.tsx was
unreachable dead UI code for Native Runtime users.
After:
- New builtin tool `src/lib/builtin-tools/ask-user-question.ts`
registered in index.ts, condition 'always'
- Zod schema: 1-6 questions, each with 1-6 options, optional multiSelect
- Execute receives answers from permission flow (injected by frontend)
and formats as Q/A pairs for the model
- permission-checker.ts: new ALWAYS_ASK_TOOLS set ensures AskUserQuestion
(and ExitPlanMode) always show UI even in trust mode — without this,
trust mode would auto-approve and return empty answers
- PermissionPrompt.tsx: NEVER_AUTO_APPROVE set prevents full_access mode
from auto-approving AskUserQuestion — the UI must render so the user
can answer
The data flow:
Model → AskUserQuestion({ questions }) → permission wrapper intercepts
→ SSE permission_request → frontend AskUserQuestionUI renders
→ user picks options → updatedInput({ questions, answers }) → tool
execute formats answers → model gets "Q: ... A: ..." string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KevinYoung-Kw referenced this pull request in KevinYoung-Kw/CodePilot Apr 15, 2026
**补充修复**
在 #1 斜杠命令保留已有文本的修复基础上,进一步确保选择命令后光标自动定位到输入框尾部,而不是默认的首部。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KevinYoung-Kw referenced this pull request in KevinYoung-Kw/CodePilot Apr 15, 2026
**补充修复**
在 #1 斜杠命令保留已有文本的修复基础上,进一步确保选择命令后光标自动定位到输入框尾部,而不是默认的首部。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
v0.56.x 计划 Phase 1:建立稳定性治理入口,并用当前源码重新核验 Notion/issue 列出的
7 个 issue(不采信 issue 自述根因)。
GitHub 侧(已在仓库生效,非本 commit 内容):
- 创建 milestone #1「v0.56.x Stability / Trust」。
- 创建 9 个治理 label:P0-crash-or-interrupt / P0-data-loss-risk / P1-runtime-session /
P1-context / P1-file-reference / P1-installer-update / P1-performance / needs-repro /
v0.57+ parking-lot。
- 给 #626/#628/#629/#632/#633/#634/#635 按复核结论打 milestone + 优先级 label。
本 commit 文件:
- .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml:bug 表单强制必填
版本/OS/runtime/provider-model/可复现/复现步骤/期望vs实际 + 影响面勾选;feature
表单注明 v0.56.x 冻结新功能 → v0.57+ parking-lot;config 关闭空白 issue + 冻结说明
与 Discussions 入口。
- .github/PULL_REQUEST_TEMPLATE.md:Summary / Repro+root cause / Changes / Tests /
Screenshots-logs / 自查清单(链到 CLAUDE.md 与 AGENTS.md,不复制维护)。
- .github/TRIAGE.md:对外冻结说明、label 体系、issue/PR triage 规则、自动化候选。
- v0.56.x-stability-trust.md:标 Phase 0 完成 + 新增「2026-06-19 Claude Code 源码复核」
表(7 issue 逐条 file:line 证据)。关键复核结论:
* #632 ">100%" 确认是未 clamp 的 ratio*100 显示 bug(RunCockpit.tsx:169 等),分母
contextWindow 不可靠;"跨会话串" 源码不成立。
* #629 空 assistant 已防护,残留真实 gap:is_error result 路径不清坏 sdk_session_id
(claude-client.ts:1908 先置 resultEmitted)。
* #635 截图-only,最强候选 = SDK runtime 无自生成 keepalive(claude-client.ts:1956),
慢 proxy 静默 >330s 被 idle abort(B-019)。
* #628 确认真实风险:@file origin path 在 MessageInput.tsx:161 丢失,body.mentions[]
送达但 route.ts 从不消费 → 写 .codepilot-uploads 副本,AI 改副本。
* #634 根因不成立——5 个 notify/schedule 工具均注册(builtin-tools/index.ts:250),
issue 引用的 UI 串不在当前源码(疑旧版);附带 Plan 模式 list_tasks 泄漏。
* #626 polling 排除(8h 间隔),候选 animate-pulse × backdrop-filter 重绘。
* #633 mac 无法复现;NSIS-only + 未签名 + 无 portable + CI 不验安装启动。
- issue-tracker.md:新增「v0.56.x 治理 issue」看板索引表(指向 plan 复核表,不重复分析)。
验证:docs-drift 通过;npm run test(hook)。Phase 1 验收(milestone/labels/模板/冻结
说明就绪)达成。下一步 Phase 2:按复核结论修 chat 主链路(上下文百分比语义、context-cost
不阻断发送、Codex 多模态发送、发送后清草稿)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: issue #632 报"上下文 >100% / 假百分比 / 压缩后跳变";Phase 1 源码复核确认是
真实显示 bug("跨会话串"不成立)。
Triage(当前源码): 用量百分比 = usage.ratio*100,在 RunCockpit.tsx 与
RunCockpitPopoverContent.tsx 两处直接渲染、未封顶;usage.ratio = used / contextWindow,
而 contextWindow 来自 sdkContextWindow ?? latestSdkContextWindow ?? catalogContextWindow
(useContextUsage.ts)。很多第三方 proxy 不上报 context_window → 落到静态 catalog 兜底
(一个猜测值),used 又会在压缩后跳变 → 百分比蹦到 200%/500%。根因是"拿不可信的分母
算百分比",不是上下文真的超了。
Fix:
- useContextUsage.ts: 新增 ContextUsageData.contextWindowTrusted —— 仅当 SDK/上游真实
上报窗口时为 true(catalog 兜底不算)。三个 return 分支(baseline / snapshot / no-baseline)
都按各自来源正确赋值。不可信时不把窗口喂给 buildContextUsageBreakdown,dot-matrix 退回
按已用 token 的构成比例,不编造容量。
- RunCockpit.tsx: hasFullCtx 增加 && usage.contextWindowTrusted —— 不可信时自动落到既有的
绝对已用 token 显示(触发按钮)/ showUnknownCapacityBlock 分支(浮层,已测试的"容量未知"
路径)。百分比文案 clamp ≤100%。
- RunCockpitPopoverContent.tsx: 浮层 header 百分比同样 clamp ≤100%(防可信窗口被 used 短暂
超过时仍蹦 >100%)。
语义验收: 输入框右下角不可信时只显示已用绝对值;浮层不可信时只显示已用 + 不同种类构成
比例(无百分比/remaining/unused/假总量);可信时百分比封顶 100%。
Verify: typecheck 通过;context-window-trusted.test.ts 6 条 source-pin + 既有
run-cockpit-unknown-capacity / context-dot-matrix / context-usage-walk / context-breakdown
全绿;全量单测 3366/3366。未做:真实 untrusted-window provider 会话的 CDP 视觉走查
(fix 把 untrusted 路由到既有已发布的"容量未知"分支,风险低;视觉走查列为后续)。
Guardrail: context-window-trusted.test.ts 钉死 trusted 派生只认 SDK 来源、不可信时不喂窗口、
hasFullCtx 必须 gate trusted、两处显示 clamp ≤100%,防回退到"拿 catalog 当真实分母算百分比"。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: Codex 复核 fix#1(b842628)后发现 P2 残留——文字已改成"只显示已用 token",
但输入框右下角触发按钮旁的 mini dot-bar 仍用 200K 兜底画出"用了多少/还剩多少"的容量
暗示,与"拿不到总长度就不显示容量"及 commit message 的"不编造容量"不一致。
Triage(当前源码): ContextDotMatrix.tsx 有 FALLBACK_CONTEXT_WINDOW=200_000,
minCellsPerKind=0(mini-bar)在窗口未知时用它当分母(:88);RunCockpit.tsx:200 的触发
按钮无条件渲染这个 mini-bar。所以即使 b842628 把文字降级为绝对已用,小条仍画假容量。
minCellsPerKind=0 全仓只有 RunCockpit 触发按钮一个调用方。
Fix:
- RunCockpit.tsx: mini-bar 用 {hasFullCtx && (...)} 包裹——仅在可信窗口下渲染容量小条;
不可信时触发按钮只剩绝对已用 token 文本(贴合"输入框右下角只显示已用数值")。
- ContextDotMatrix.tsx: 删除 FALLBACK_CONTEXT_WINDOW(200K)。窗口未知时两种模式都按
used+pending 分配(构成视图,非容量%),不再编造容量。
Verify: typecheck 通过;context-dot-matrix.test.ts 旧的"unknown mini-bar 用 200K 兜底
(filled<=2)"语义改为新的"used 构成(filled>=8)";context-window-trusted.test.ts 加 2 条
guardrail(mini-bar gate 在 hasFullCtx + 源码无 200K 兜底残留);全量单测 3368/3368。
Guardrail: 两条 source-pin 钉死"触发按钮 mini-bar 必须 gate 在 hasFullCtx"且"ContextDotMatrix
不得再出现 FALLBACK_CONTEXT_WINDOW/200_000",防回退到拿假容量画小条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
用户复核 fix#1 后明确显示格式:输入框右下角的上下文小标,在有可信窗口时显示
"百分比 + 已用上下文"(如 56.6% 452K),没有可信窗口时只显示已用(如 452K),
不单列"剩余"数字。
改动:RunCockpit.tsx 触发按钮 ratioText 的可信分支由 "{pct}%" 改为
"{pct}% {used}"(1 位小数,匹配用户给的 56.6% 示例);不可信/无数据分支不变。
context-window-trusted.test.ts 的 clamp pin 扩为同时断言"百分比 + 已用"格式。
验证:dev 应用热重载干净(✓ Compiled);context-window-trusted 8/8;typecheck(hook)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: 用户在运行的应用里看到 GLM-5-turbo(Claude Code/Native 会话)仍显示总上下文
200K,指出"这并不是我们知道的部分"。fix#1 本应让 catalog 静态值不可信、只显示已用。
Triage(当前源码,用户 review 驱动): agent-loop.ts:641-651(Native)在 token_usage
没有 context_window 时,从静态 catalog 填 totalUsage.context_window = getContextWindow(modelId)
(GLM-5-turbo 在 catalog 是 z.ai 核实的 202752)。而 context-usage-walk 把
token_usage.context_window 当作 SDK 实报窗口读,fix#1 的 contextWindowTrusted 据此判可信
→ catalog 猜测被"洗白"成可信 → Native GLM 显示 200K。即上游 mutator 打败了 helper 修复
(feedback_fix_all_consumers)。claude-client(Claude Code)只从 SDK modelUsage 写,不洗白;
ContextUsageIndicator 是死组件(无人 import)。
Fix: 删掉 agent-loop 的 catalog 洗白。Native 无 runtime 实报时 context_window 留空 →
useContextUsage 回落 catalog 为不可信 → 只显示已用绝对值,不再有假百分比/假总量。
仅对新 turn 生效(历史消息已存的 context_window 不改写,遵守不改用户数据;旧会话发新消息后转为已用-only)。
Verify: typecheck;context-window-trusted.test.ts 新增 pin 断言 agent-loop 不再
`.context_window = catalogWindow`;该文件 9 测 + agent-loop-error-event 全过。运行中 dev 应用
server 重编译干净(Native GLM 需发新消息验证)。
Guardrail: source-pin 防 Native 再把 catalog 洗进 SDK-authoritative 字段。
设计记录(用户批准"先记计划再实现"): v0.56.x 计划写入 context-window 来源优先级修订设计
(runtime 实报 > provider 配置 contextWindow > 压缩阈值 > catalog 不可信)+ 跨 Runtime 用户
配置源(#1,待实现) + 显示分母对齐压缩阈值(#3,待实现)。本提交是设计第一步(去洗白)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
把"为什么 GLM 显示 200K + 窗口来源该怎么改"写成评审稿放进 v0.56.x Phase 2,按
外部事实 / 本地证据(file:line) / 推断与设计三层分写,供 Codex 核实。
要点:
- Agent SDK v0.2.111 的 modelUsage.contextWindow(sdk.d.ts:945)是未文档化字段,来自
SDK 内置模型目录而非 API;第一方可靠、第三方(经 base_url 的 GLM)返回通用默认值;
无 SDK 设置可覆盖;Anthropic 建议自维护窗口表。
- 实测 GLM 会话 token_usage.context_window=200000 ≠ 本地 catalog 202752,证实来自 SDK
默认而非 catalog/Native 洗白;该会话是 Claude Code(故上一提交的 Native 修复不覆盖它)。
- 修订设计:窗口来源优先级 = 用户覆盖 > 已核实 catalog/provider 配置 > SDK(仅第一方) >
只显示已用;第三方忽略 SDK 默认值;跨 Runtime;显示分母对齐压缩阈值(#3)。
- 列出待定决策(已核实优先 vs 纯手动) + 给 Codex 的 5 个核实点。
未改任何产品代码(纯文档)。#1/#3 实现待 Codex 核实后进行。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Codex 复核设计稿后订正(实现 #1/#3 前必须):
- A:原"官方文档不记载 contextWindow/maxOutputTokens"不准 → 改为 SDK TypeScript
reference 有字段定义,是 cost-tracking 指南未解释来源/可信度。
- B/C:原"catalog 202752 比 SDK 200000 更准且 z.ai 核实"站不住 → z.ai 官方写
200K/128K,catalog 该条来源存疑;结论收敛为"SDK 200000 不可作为 provider 实报采信",
不延伸到"catalog 更准";另标记需单独核 model-context.ts:42 的真实来源。
- D + 决策日志:统一优先级(消除冲突,旧决策日志把第三方 SDK 又洗白成可信)→
用户手动覆盖 > provider/model 配置且来源已验证 > 第一方 runtime 实报 > 只显示已用;
第三方 SDK contextWindow 默认不可信、无明确来源 catalog 不当可信%显示。
- "Anthropic 官方建议自维护表"未核到原文 → 降级为工程结论。
- 澄清:用户实际看到 200K 的 GLM 会话是 Claude Code(SDK 默认 200000),非 Native 洗白
路径(681706b 的 Native 修复有效但治另一条路径)。
- E:决策收敛为一条基线 + 剩余一项请用户定(第一方 SDK 实报是否自动显示百分比)。
Codex 核为真的部分(sdk.d.ts:945 字段、代码写入 token_usage、历史 SDK 窗口被当可信、
Native 洗白已去、显示分母 vs 压缩阈值脱节)保留。纯文档,未动产品代码。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
F 段核实点 #1 还残留旧"官方文档未记载(A)",与已订正的 A 段不一致。改为:
sdk.d.ts:945 的 contextWindow/maxOutputTokens 存在,SDK TypeScript reference 已列,
只是 cost-tracking 指南未解释来源/可信度。纯文档。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
… Phase 2 ①)
Signal: 用户 GLM-5-turbo(Claude Code 经代理)显示总上下文 200K,且 Codex 核实 SDK 的
modelUsage.contextWindow 来自 SDK 内置目录、对第三方是通用默认值、无 SDK 设置可覆盖。
Triage: claude-client.ts extractTokenUsage 把 SDK modelUsage.contextWindow 无条件写入
token_usage.context_window;walk + fix#1 据此判可信 → 第三方代理(GLM)的 SDK 默认 200000
被当可信显示。Native 的 catalog 洗白已于 681706b 去掉;本提交补 SDK 路径。
Fix(Codex 统一口径"第一方 runtime 实报可信、第三方不可信"):
- ai-provider.ts 导出 isFirstPartyAnthropicEndpoint(baseUrl)(空/anthropic.com → 第一方)。
- extractTokenUsage 增 trustContextWindow,仅 true 时写 context_window;两个调用点都传
isFirstPartyAnthropicEndpoint(resolved.provider?.base_url)。第三方(自定义 base_url,如 GLM)
→ 不写 context_window → useContextUsage 回落 catalog 为不可信 → 只显示已用。
效果 + 边界: 第一方 Anthropic 继续显示百分比+已用;第三方代理新 turn 起只显示已用。
仅对新写入生效(历史消息已存的 context_window 不改写,遵守不改用户数据);现有 GLM 会话
仍显示旧值,需新会话/新 turn 验证(walk 会读历史,故旧会话需自然滚动出旧窗口或新建)。
Verify: typecheck;extract-token-usage-context-window.test.ts 增 2 pin(gate + 两调用点传
第一方判别);全量 3371/3371。
Guardrail: source-pin 钉死 context_window 写入受 trustContextWindow 门控 + 两调用点必须传
isFirstPartyAnthropicEndpoint,防回退到无条件信任第三方 SDK 窗口。
remaining(Phase 2 ①/③ 未完): provider/model 配置窗口作为最高优先可信源(用户覆盖) + 渲染层
对现有会话按第一方 gate(治旧会话) + #3 显示分母对齐压缩阈值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
计划文档状态审计修正(决策日志准、但概览层过期):
- frontmatter 状态行:📋 待接手 → 🚧 Phase 0/1 已完成、Phase 2 进行中。
- 「状态总览」表:Phase 1 待开始 → ✅ 已完成(2026-06-19);Phase 2 待开始 → 🚧 进行中。
- Phase 2 加进度 note:Composer/Context 主链路 #1#5 全部收口(含 commit + #3 真实
Codex 冒烟回复 circle);Session/Stream cluster #629/#635 + 终态原因码 + 压缩回滚
+ 诊断导出字段待续。
- Phase 2 执行清单 4 项已完成项 [ ]→[x](上下文 UI 语义 / context-cost 去阻断 /
Codex 多模态发送 / 发送后草稿清理)。
CLAUDE.md 执行计划段新增「完成即回写进度(与 Codex 对齐协作)」:任一 Phase/子项做完
必须立即回写三处且一致——执行清单勾选 / 状态总览表+frontmatter / 决策日志(commit
+验证结论);Claude 实施+回写、Codex 审查+维护;三者不一致视为状态失真须先对齐。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
打回上一条状态同步的一处失真:我把 #4/#5「发送后内容残留」标成完成(checklist [x] +
进度 note 列为 done),但同一文档决策日志(2026-06-20 条)已写明用户再次确认"内容已发出
但文本仍残留输入框"、#615 source-pin 不覆盖该症状、不能算闭环——状态表/清单与决策日志
自相矛盾,违反刚加的"三者必须一致"。
修正(与决策日志对齐):
- checklist「复现并修发送后内容残留」[x] → [ ],标注"待复核/待修复(用户 2026-06-20 再报)"。
- Phase 2 进度 note:拆分——#4/#5 仅失败保留有基础修复(#615),发送成功后文本残留待复核;
note 标题从"主链路已收口"改为"#1#3 收口、#4/#5 待复核";待续列表补回 #4/#5(重新打开)。
- #2 context-cost 非阻断保持完成(checklist [x] + note)不变。
后续修 #4/#5 时重点:PromptInput 受控/非受控清空边界、setInputValue('') 与
controller.textInput.clear() 是否同源、成功 accepted 后 remount/local draft 恢复、
badge/confirm/image 分支与普通 Enter 分支是否一致(决策日志已记排查方向)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
按"完成即回写进度"规则同步三处:
- checklist「复现并修发送后内容残留」[ ]→[x],标注已修 + CDP 验证 + 根因/修法(58c7aad)。
- Phase 2 进度 note:#1#5 全部落地;#4/#5 从"待复核"改为"已定位+修复"(含根因/CDP 结论);
待续列表移除 #4/#5、只留 Session/Stream cluster。
- 决策日志加同日条目:CDP 埋点定位 = 首条消息 accept 布局翻转 remount composer、inputValue
从 sessionStorage 草稿重读;修法 = accept 处清草稿;3401/3401 + CDP 文本/图文首条 800ms 即清。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
用户在浏览器实测不残留、仅桌面 App 残留 → Claude 协助完整重启 electron:dev(kill 整棵
进程树 + 释放 3000 + 后台重启)→ 用户在重启后真实 App 验证发送即清空 → #4/#5 闭环。
根因:58c7aad(page.tsx accept 处清首条草稿)一直是对的;用户残留是 Electron dev 没把
page.tsx 改动热更新进 renderer、窗口刷新无效,得整进程重启。这解释了全程「Claude CDP
浏览器清、用户残留」的矛盾——不是 Electron 行为差异,是构建新鲜度差异(Claude 浏览器硬刷
过有修复、用户 Electron 旧构建没有)。
回写:checklist [x](用户真实 App 验证)、进度 note #1#5 全闭环、验收去 ⚠️、决策日志加
闭环条目 + 教训(UI 修复在桌面 App 验证必须整重启 electron:dev)。Codex P1(prefill/
initialValue 回灌)仍是 58c7aad 的真实独立漏洞、值得单独补,与本次残留无关。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
纯文档同步,无代码改动。目的:让下一个进程打开文档时不从旧状态误判进度。
三处状态表此前已标 Phase 0/1 ✅、决策日志也已确认完成,唯独执行清单 checkbox
与 README 索引、issue-tracker #632 仍停在旧值——三处不一致即状态失真,本次对齐。
README.md:
- v0.56.x 索引行状态列 "📋 待 Phase 0 收束" → "🚧 Phase 0/1 ✅;Phase 2 进行中
(Composer/Context 主链路 #1#5 闭环,Session/Stream cluster #629/#635 待续)",
追上 plan frontmatter 与决策日志。
v0.56.x-stability-trust.md:
- Phase 0 执行清单 8 项 [ ]→[x],逐条带回溯(3360/3360、9c6e772、f99edbb/d00449f)。
A2 计时器项如实标注:按 keyed-remount 构造性消除 + 截图不可判别记录入 Smoke Ledger,
非逐帧视觉确认(反假数据,不谎称做了视觉确认)。
- Phase 1 执行清单 5 项 [ ]→[x],带回溯(milestone #1 / 9 labels / .github/TRIAGE.md)。
issue-tracker.md:
- #632 状态 "🔴 待修" → "🟡 假%已修,item3 分母对齐待续"。核心显示 bug(假百分比/>100%)
已由 effective-base-URL 写入 gate + 渲染期 trusted gate + clamp 修复并经真实 GLM
会话验证;item3(显示分母对齐压缩阈值)是独立待续阶段,故标部分修复而非已修复。
- 顶部"最后更新"同步到 2026-06-26 + #632 同步说明。
验证:git diff 确认仅 3 文档、16/16 行 checkbox 与状态文字,无代码/意外文件。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jul 4, 2026
- docs/research/ai-sdk-7-toolloop-parity-gaps.md: 新增「Phase 5 处置」节,全部 gap
收口——P1×3 关闭(#1/#2 补偿由 parity 8/8 复跑锁定;#3 降级论证:Phase 4 已证
approval HMAC 不需要 SDK toolApproval 停机语义,维持 in-execute 路线),
P2/P3 关闭或 backlog(#4/#5 列为替换路线前置条件,#7 归档 tech-debt #49#8 有 Phase 5 新实证)
- scripts/smoke-ai-sdk7-phase5-decision.ts: 新增决策门对照 smoke——prod runAgentLoop
与 POC runToolLoopAgentPoc 用同一 AgentLoopOptions 逐场景对照(长文本 / approval
批准 / approval 拒绝 / abort→continue),机械比较归一化事件序列 + 尾部契约 +
usage 存在性;DB 只读、数据目录隔离、输出全 scrub。探针注意:approval 批准分支
用 printf(echo 命中 permission-checker 自动放行规则不会触发 ask)
- docs/exec-plans/active/_smoke-evidence/ai-sdk7-phase5-decision-smoke.json:
OpenRouter 真实渠道 4/4 场景 contractMatch=true(input_tokens 逐场景完全相同,
tool_result 逐字相同,中断轮双侧 done 收尾、同 session 续发一次通过);
凭据形态 grep=0
- docs/research/ai-sdk-7-adoption-decision.md: 新增采用决策文档——结论 partial
(依赖升级 go / provider 能力 capability-gated go / Phase 4 外围能力 go /
@ai-sdk/mcp 与默认 loop 替换 no-go-现在),四层 rollback plan(能力开关→
wrapper→runtime switch→known-good version),每项结论标注 Phase 1-5 证据来源;
默认 Runtime 切换留人类闸门
- docs/exec-plans/tech-debt-tracker.md: 新增 #49(tool-error part 被两条 loop
一致吞掉的既有 UX 债,独立于采用决策)
- docs/exec-plans/active/ai-sdk-7-runtime-loop-adoption.md: Phase 5 状态回写 +
决策日志 + Smoke Ledger / Loop Ledger 各一行
- docs/research/README.md: 索引新增决策文档条目
验证: npm run test 3598/3598 全绿;smoke 4/4 contractMatch(1 个 fix cycle 收敛,
两处均为脚本层问题非 loop 差异);src/ 零改动(默认 Runtime/聊天路径零变化)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jul 4, 2026
用户批准 partial(2026-07-04, run issue #10): 采用 ai@7/@ai-sdk/* 依赖升级、
provider 参数能力 capability-gated、openai-chat image wrapper、timeout 原因码/
approval HMAC/trace 脱敏四件套(默认值经用户确认); @ai-sdk/mcp adapter 与
ToolLoopAgent 默认 loop 替换均不采用(留实验路径)。发版前保留官方一方 key
smoke gate。冲突仅 ai-sdk-7 计划决策日志一处,union 双方条目解决。
五个 phase 全部经 hands-off loop 完成并 Codex accepted(issues #1/#6/#7/#8/#10)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ion for Native Runtime
Two feature gaps where Native Runtime didn't match SDK Runtime, both
surfaced during post-hermes-upgrade manual testing:
── op7418#1: Compression notification now human-readable ──
Before: chat/route.ts:402 emitted `message: 'context_compressed'` as
a machine string. useSSEStream's notification branch showed this raw
string in the status bar — users saw "context_compressed" flash by.
After: message is now `"Context compressed: N older messages summarized,
~X tokens saved"` with structured `stats: { messagesCompressed, tokensSaved }`
for future rich UI handling. Added `subtype: 'context_compressed'` for
dedicated frontend handlers.
── op7418#3: AskUserQuestion tool for Native Runtime ──
Before: only SDK Runtime had AskUserQuestion (built into Claude Code CLI).
Native Runtime had no such tool, so the model could never ask structured
questions — the existing AskUserQuestionUI in PermissionPrompt.tsx was
unreachable dead UI code for Native Runtime users.
After:
- New builtin tool `src/lib/builtin-tools/ask-user-question.ts`
registered in index.ts, condition 'always'
- Zod schema: 1-6 questions, each with 1-6 options, optional multiSelect
- Execute receives answers from permission flow (injected by frontend)
and formats as Q/A pairs for the model
- permission-checker.ts: new ALWAYS_ASK_TOOLS set ensures AskUserQuestion
(and ExitPlanMode) always show UI even in trust mode — without this,
trust mode would auto-approve and return empty answers
- PermissionPrompt.tsx: NEVER_AUTO_APPROVE set prevents full_access mode
from auto-approving AskUserQuestion — the UI must render so the user
can answer
The data flow:
Model → AskUserQuestion({ questions }) → permission wrapper intercepts
→ SSE permission_request → frontend AskUserQuestionUI renders
→ user picks options → updatedInput({ questions, answers }) → tool
execute formats answers → model gets "Q: ... A: ..." string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ge generation results
GPT-Image-2.0 skill silent failure had two compounding causes both
on the 'tool result' loop:
P0 op7418#1 — function_call_output translated with sentinel toolName
translate-input.ts wrote toolName: '__from_responses_proxy__' for every
tool-result and the comment claimed 'ai-sdk doesn't use this for
routing'. That was wrong. Anthropic and OpenAI Responses both look
up the tool definition by tool-result.toolName when reconciling the
result with the request's tool surface; with a sentinel they can't
correlate and refuse to produce the continuation turn — exactly the
'tool ran, no follow-up text' the user saw.
Fix: walk the input array once first to build call_id → toolName
from function_call items, then look up the real name when translating
function_call_output. Orphan results (no matching function_call) fall
back to a named sentinel '__orphan_function_call_output__' AND emit
console.warn naming the call_id. The divergence stays loud.
P0 op7418#2 — imageGeneration / imageView silently dropped
event-mapper.ts had both item types in CHAT_ONLY_ITEM_TYPES, which
returns null on item/started + item/completed. That set is correct
for agentMessage/plan/reasoning (they have streaming delta channels
so the content arrives separately), but imageGeneration / imageView
have NO delta channel — their final item is the only surface where
the result reaches the user. Silent drop meant 'tool ran' with no
visible image.
Fix: move both types to TOOL_LIKE_ITEM_TYPES, add explicit
translateItemStarted branches with names image_generation /
image_view, and the existing TOOL_LIKE_ITEM_TYPES completion branch
already packs the full item into output — preserving result,
savedPath, revisedPrompt, path for chat-side rendering.
ThreadItemLike grew matching fields so TS doesn't downgrade access
to (item as { path?: string }).path casts.
Tests (8 new)
src/__tests__/unit/codex-proxy-translators.test.ts (+3):
- toolName resolves from matching function_call (gpt_image_2 case)
- toolName resolves correctly with interleaved out-of-order calls
- orphan function_call_output → named sentinel + console.warn
src/__tests__/unit/codex-event-mapper.test.ts (+4):
- imageGeneration item/started → tool_started(name='image_generation')
- imageGeneration item/completed → tool_completed with full
result + savedPath + revisedPrompt payload
- imageView item/started → tool_started(name='image_view') + path
- imageView item/completed → tool_completed with path preserved
src/__tests__/unit/codex-proxy-tool-contract.test.ts (+1):
- End-to-end continuation: function_call → function_call_output →
streamText(messages) — MockLanguageModelV3 must see toolName
'gpt_image_2' in its prompt, NOT '__from_responses_proxy__'.
Continuation text-delta event fires.
The mapper-side translate also removed the chatOnly array's
imageView / imageGeneration entries from the old 'returns null'
parameterised test; replaced with the new lifecycle describe block.
Closeout doc records round 7 ✅ items; remaining must-haves
unchanged (4-family smoke matrix + codex-sdk POC).
All 2416 tests pass (was 2412 + 8 new − 4 obsolete from the chatOnly
table for imageView/imageGeneration).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ce 2a
Direction approved; three sharpenings folded into the existing
Phase 2 plan structure without restructuring.
1. Widget wire-format single source (review revision op7418#1)
slice 7's WIDGET_SYSTEM_PROMPT template-literal-embeds
WIDGET_WIRE_FORMAT_SPEC. With artifactContracts ordered BEFORE
capabilityFragments in the compiler, the wire spec would land in
the final system prompt twice (once from artifactContract, once
from the capability fragment tail). The plan now declares hard
constraints — CANONICAL_SHOW_WIDGET_JSON, the "FINAL OUTPUT
FORMAT" title, and WIDGET_WIRE_FORMAT_SPEC each must appear
exactly once in the compiled system prompt — and assigns slice
2c a small refactor that strips the wire spec from
WIDGET_SYSTEM_PROMPT so artifactContract becomes the sole holder.
Compile-time sanity check (capability fragment text MUST NOT
contain artifactContract.canonicalJson) added as a defence-in-
depth FAIL path.
2. Expected Differences Ledger (review revision op7418#2)
2b's "compiler output === Runtime current prompt" stance
directly conflicted with slice 2d's plan to canonicalize Native
memory / notify / media-import paraphrases. Equivalence reading
strictly would have locked the old drift in. Plan now introduces
`src/lib/harness/expected-differences.ts` with typed entries
(runtimeId, capability, diff kind, justification,
plannedResolution, compilerSource, runtimeSource). 2b harness
reads "compiler vs runtime diff ⊆ ledger"; unregistered
differences fail. Initial ledger seeded with the four known
Phase 5c slice 7b tech-debt items, three earmarked for slice 2d
and one (image_generation MediaBlock shape) earmarked
follow_up. Slice 2d completion = manual ledger entry removal
(deliberate non-automation, preserves audit trail).
3. runtimeHints boundary (review revision op7418#3)
Plan tightens the runtimeHints type declaration so it cannot
become a fourth prompt-assembly point. Allowed: IDs (mcp server
names, tool keys, builtin tool name set), fragmentIds refs into
CompiledContext, adapter options (stopWhen / stepCount /
passthroughToolTypes). Forbidden: any prompt text string, tool
description paraphrase, capability redefinition. Three test
layers — type-level (string fields ≤ 64 chars, no newline / no
markdown), runtime-level (no template-literal-shaped values),
source-grep level (no multi-line template literals in
runtimeHints assignments) — plus a dangling-reference check
that every fragmentId in runtimeHints resolves in
CompiledContext.
Regression test list extended 9 → 12. Decision log records all
three revisions with rationale.
Plan still in 📋 status. No code; awaiting Codex re-review on the
revised draft, then slice 2a opens.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
User mode change: "internal slice order preserved, external single
delivery; stop only after Phase 2 is done; Codex review takes the
batch." This commit lands slices 2a–2e together with all post-
review hardenings (Widget wire-format single source, Expected
Differences Ledger, runtimeHints prose ban).
Internal slice walk
2a — context-compiler.ts (NEW)
Pure function `compileContext(input): CompiledContext`. No IO,
no provider calls. Resolves enabledCapabilities (null = catalog
live default), looks up exposure for the calling runtime, emits
capabilityFragments + artifactContracts + memory + workspace +
toolDescriptors + runtimeHints + budget + systemPromptText +
diagnostics. Hard contracts: artifactContract before capability
in the assembled prompt; fragmentId uniqueness; cross-runtime
fragment text identity; compile-time FAIL if a capability
fragment text contains an artifact contract canonicalJson
(wire-format dedup); compile-time FAIL if load-bearing fragments
exceed budget. runtimeHints types strictly ID/refs/adapter
options — no prose, no template literals.
2b — expected-differences.ts (NEW)
Drift ledger. Initial 4 entries from slice 7b tech-debt. Three
slice_2d entries consumed by this commit (see 2d below); the
one remaining `follow_up` is image_generation MediaBlock shape
(non-prompt, future slice).
2c — ClaudeCode SDK (claude-client.ts) source-pin only
The SDK path has always imported MCP canonicals directly
(memory-search-mcp, notification-mcp, media-import-mcp,
cli-tools-mcp, dashboard-mcp) — no paraphrase ever existed.
Slice 2c codifies this with a contract test: claude-client.ts
must not import capability prompts from builtin-tools/* and
must not declare its own _SYSTEM_PROMPT scalars.
2d — Native Runtime (builtin-tools/*) re-export MCP canonicals
`memory-search.ts` now `export const MEMORY_SEARCH_SYSTEM_PROMPT =
CANONICAL_MEMORY_SEARCH_SYSTEM_PROMPT` (imported from
memory-search-mcp.ts). Same pattern for `notification.ts`
(NOTIFICATION_SYSTEM_PROMPT = NOTIFICATION_MCP_SYSTEM_PROMPT)
and `media.ts` (MEDIA_SYSTEM_PROMPT = MEDIA_MCP_SYSTEM_PROMPT
from media-import-mcp.ts). Three ledger entries removed in
sync.
2e — Codex bridge (builtin-bridge.ts + unified-adapter.ts)
Bridge no longer holds WIDGET_PROMPT / MEDIA_PROMPT /
MEMORY_PROMPT / NOTIFY_PROMPT scalars (all four declarations
deleted). `createCodePilotBuiltinTools().systemPrompt` is
permanently `''`. `unified-adapter.ts` now calls
`compileContext({ runtimeId: 'codex_runtime', ... })` and feeds
`compiled.systemPromptText` to Codex's `instructions`. A new
helper `capabilitiesFromBridgeToolNames` maps the bridge's
mounted tool names back to capability ids so the compiler's
enabledCapabilities aligns with what the bridge actually
exposes (workspace-gated memory tools naturally drop out when
workspacePath is empty).
Slice 2c Widget wire-format single source (review revision op7418#1)
WIDGET_SYSTEM_PROMPT in widget-guidelines.ts no longer
template-literal-embeds `${WIDGET_WIRE_FORMAT_SPEC}`. The
artifactContract is now the sole holder of the wire-format spec
+ canonical JSON. Compiler's `detectWireFormatDuplication` sanity
check throws at compile time if any capability fragment text
contains the artifact contract canonicalJson — that's the forcing
function preventing the spec from being re-injected.
Three regression pins enforce single occurrence in the compiled
prompt: CANONICAL_SHOW_WIDGET_JSON × 1, "FINAL OUTPUT FORMAT —
non-negotiable" × 1, WIDGET_WIRE_FORMAT_SPEC × 1.
runtimeHints boundary (review revision op7418#3)
ClaudeCodeHints / NativeHints / CodexProxyHints types now carry
only IDs (mcp server names, tool keys, builtin tool name set) +
adapter options (stopWhen, stepCount, passthroughToolTypes).
Tests pin: type-level (no string field > 64 chars, no newline,
no Markdown markers), runtime-level (scan all string values for
prose), source-grep (CodexProxyHints type definition can't
contain `promptOverride` / `promptExtra` / `widgetPrompt` / etc).
Tests
New harness-context-compiler.test.ts (23 pins): catalog hygiene,
Widget wire-format single source (op7418#10), ordering, budget
enforcement, cross-runtime fragment identity (op7418#9), tool
descriptors, runtimeHints boundary (op7418#11), Expected Differences
Ledger consistency (op7418#12), JSON parseability of every artifact
contract.
New harness-context-compiler-equivalence.test.ts (9 pins):
compiler source reachability, runtime drift honesty,
ledger/slice ownership correctness, "post-slice-2d: Native
ledger holds only the follow_up MediaBlock entry".
Updated harness-capability-contract.test.ts: drift pins now
check (a) bridge holds no local _PROMPT scalars, (b) Native
builtin-tools re-export MCP canonicals, (c) unified-adapter
imports compileContext + consumes systemPromptText, (d)
claude-client.ts doesn't import from builtin-tools/* and
doesn't declare own _SYSTEM_PROMPT.
Updated codex-widget-format-contract.test.ts: the "WIDGET_SYSTEM_PROMPT
embeds WIDGET_WIRE_FORMAT_SPEC" and "appears inside
WIDGET_SYSTEM_PROMPT" pins are flipped — slice 2c REMOVED the
embed; the new pins verify the compiler-side import line.
Updated codex-builtin-bridge.test.ts: tests previously asserting
`bridge.systemPrompt` contained capability tags now assert it
equals `''` (bridge is no longer the prompt-assembly point).
Verification
CODEX_DISABLED=1 npx tsx --test \
src/__tests__/unit/harness-context-compiler.test.ts \
src/__tests__/unit/harness-context-compiler-equivalence.test.ts \
src/__tests__/unit/harness-capability-contract.test.ts \
src/__tests__/unit/codex-widget-format-contract.test.ts \
src/__tests__/unit/codex-builtin-bridge.test.ts
→ 74/74 pass
npm run test → 2576/2576 pass
Completion criteria check (per user spec)
[x] npm run test all green (2576/2576)
[x] Context Compiler unit tests all green
[x] equivalence / expected-diff harness all green
[x] harness-capability-contract / codex-widget-format /
codex-builtin-bridge tests all green
[x] no new runtime-local prompt duplicates (Native re-exports
canonical; ClaudeCode imports canonical; bridge holds none)
[x] Codex bridge no longer holds WIDGET_PROMPT / MEDIA_PROMPT /
MEMORY_PROMPT / NOTIFY_PROMPT scalars (all four removed,
drift test pins their absence)
[x] all three Runtimes adapt compiler output, none redefine
capability prompts
Docs
- phase-5d-phase-2-context-compiler.md: slice statuses 2a–2e all
✅ 2026-05-17; note the one-shot delivery mode change.
- phase-5d-harness-capability-contract.md: Phase 2 row ✅, awaiting
Codex review.
- handover/harness-capability-contract.md: new "Context Compiler"
section detailing inputs/outputs/constraints, three-runtime
consumption pattern, Expected Differences Ledger contract.
- refactor-closeout.md: new decision-log entry recording the
Phase 2 delivery shape + completion criteria check.
Phase 5d Phase 2 ✅ pending Codex review. Phase 3 (Runtime
Capability Adapter) / Phase 4 (Artifact Contract) / Phase 5
(new-Runtime Playbook) intentionally NOT opened — stopping per
user instruction.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
… to breakdown
## 用户视角
升级前:popover 的"文件与附件 / 本次待加入"两行永远 0 —— 数据通道没接通。即使 composer 里挂了 4 个 mention 和 2 个目录引用,popover breakdown 显示 0。
升级后:MessageInput → ChatView/page → RunCockpit → useContextUsage → buildContextUsageBreakdown 全链路联通。composer 里的 attachment / mention / directory 实时累加到对应类别。trigger 上的迷你点阵 + popover 主条 + 列表行三处同步更新。
发送消息后 pending 归 0;下一轮 history 里的真实 token_usage 接管 used 部分;conversation 类自动吸收。
## 不做什么
- 不改 hook 其他字段(used / ratio / state / source 等不动)
- 不改 trigger 主结构(百分比文字仍在;只有点阵 cells 在分配时反映 pending)
- 不改 composer text 估算(composerTextTokens 仍 0;那是 Phase 3+ 的事)
## 怎么验收
- npm run test → 2921/2921 pass
- composer 里加附件 / @mention / "+" 目录 → trigger 上 pending 部分立刻有虚线 cells
- 发送消息 → pending 归零;下轮 used cells 更新
## 改动(6 文件)
### src/lib/message-input-logic.ts
新增 `PendingContextSubTotals` interface + `computePendingContextSubTotals()` 函数。逻辑 mirror `computePendingContextTokens`(同样的 null 过滤、同样的迭代顺序),但返回 { attachment, mention, directory } 三键。两个函数加起来 = 等于 computePendingContextTokens 总数。
### src/hooks/useContextUsage.ts
options 加可选 `pending?: { attachmentTokens?, mentionTokens?, directoryTokens?, composerTextTokens? }`。三条返回路径(snapshot / walk / noData)都把 options?.pending 转发给 buildContextUsageBreakdown。useMemo deps 数组加 options?.pending。
### src/components/chat/RunCockpit.tsx
RunCockpitProps 加可选 `pendingContextSubTotals?: { attachment, mention, directory }`。组件内部把它转换成 hook options.pending 形态(attachment → attachmentTokens 等)。可选 prop 默认 undefined → 不破坏现有 callsites。
### src/components/chat/MessageInput.tsx
- import 加 computePendingContextSubTotals + PendingContextSubTotals type
- props 加可选 `onPendingContextSubTotalsChange?` callback(跟现有 onPendingContextTokensChange 并列)
- 新增 useMemo 算 pendingContextSubTotals + useEffect emit callback
- 与现有 pendingContextTokens 走同一份 source 数据,逻辑同步无 divergence
### src/components/chat/ChatView.tsx
- 加 state `pendingContextSubTotals` (PendingContextSubTotals | undefined)
- MessageInput 上 wire `onPendingContextSubTotalsChange={setPendingContextSubTotals}`
- RunCockpit 上传 `pendingContextSubTotals={pendingContextSubTotals}`
### src/app/chat/page.tsx
- 跟 ChatView 完全镜像:state + MessageInput callback + RunCockpit prop
- 两个入口独立持有 state(按 StreamSession guardrail 不变量 op7418#1)
## Scope discipline
- 不新增测试(Codex 负责测试覆盖;用户分工已明确)
- 不动 buildContextUsageBreakdown / computePendingContextTokens 既有签名 → 旧调用 zero-risk
- 不改 chat-static-graph 排除清单 → MessageInput / RunCockpit 改动属于增量 prop,没新依赖链
- composerTextTokens 仍未 wire(composer 纯文本估算属于未来扩展,pending_next_turn 行暂时仍 0)
## StreamSession guardrail 合规
- 双入口(page.tsx 首消息 + ChatView 后续)独立 state — 不变量 op7418#1 ✅
- onSend / onCommand 签名不变 — rewind point 不变量 op7418#2 ✅
- 不动 capability cache — 不变量 op7418#3 ✅
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…18#31)
Codex review second round caught two real P1 inconsistencies introduced by
the Dashboard/CLI split slice plus non-blocking contract drift.
P1.1 — Dashboard injection gate ≠ route auth gate.
runtime.ts injected the dashboard read/write MCPs whenever prompt + working
directory + dashboard keyword matched, but the route's `authorize` requires
`sameRealPath(workspacePath, assistant_workspace_path)`. Mismatch → the model
sees the tool and Codex 403s at call time. Fix: dashboard injection mirrors
memory's gate exactly (same sameRealPath check, same `assistantWorkspacePath`
passed as `workspacePath`) so "inject" and "route-authorize" never disagree.
CLI tools don't need this (no workspace scope).
P1.2 — Matrix promoted only for codex_account; runtime injects for ALL
codex_runtime providers.
The runtime didn't gate injection by provider, so under a CodePilot proxy
provider the dashboard/cli MCPs WERE injected (callable), but the matrix
returned `perception_only` for non-codex_account — the opposite drift from
P1.1 ("model says yes, Settings says no"). Fix per Codex's preferred option:
move the promotion into `capabilityMatrixForRuntime` so it applies to ALL
codex_runtime providers; `capabilityMatrixForRuntimeProvider` now only adds
codex_account-specific overrides (native notes + image/media demotion).
`buildCapabilityMatrix` delegates to `capabilityMatrixForRuntime` so every
matrix entry point stays aligned.
Non-blocking op7418#1 — contract text drift.
capability-contract.ts dashboard/cli `deferredReason` + `codex_proxy.notes`
rewritten — explicit that the LEGACY provider-proxy bridge is unsupported
(true), and that the codex_runtime path now ships via the mutation-level MCP
split + matrix-layer promotion. No schema changes (`kind: 'unsupported'`
stays accurate for the legacy bridge surface); the existing matrix invariant
test gets a `MATRIX_LAYER_PROMOTIONS` exception list documenting why the two
promoted cells are allowed to be executable despite `kind: 'unsupported'`.
Schema cleanup (introduce a new `mcp_server_split` kind, drop the exception
list) tracked as tech-debt op7418#33.
Non-blocking op7418#2 — elicitation policy pins.
codex-mcp-events.test.ts now pins all 4 new server names:
codepilot_{dashboard,cli_tools}_read → auto_accept,
codepilot_{dashboard,cli_tools}_write → user_approval.
Also added a regression guard: `codex_runtime + non-codex_account provider`
must STILL show dashboard/cli_tools executable with mixed trust + the right
noteKey. Updated the two pre-existing tests that asserted the OLD behaviour
(dashboard/cli perception_only on codex_runtime) — they now assert the
promoted state. Also synced the static `CAPABILITY_EXECUTABLE_RUNTIMES` map.
Per Codex review's explicit ask: the "待真账号 smoke" wording stays in the
op7418#31 capability table — this commit fixes the inconsistencies, but the
real-account end-to-end smoke for natural-conversation triggering + write
approval card + Deny blocking is still owed by the user.
Full unit suite 3045/3045. Live route: bad workspace still 403 (auth gate
intact); tools/list subsets unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Codex review 认可方向,按 5 条反馈修订(纯文档,无代码):
- Phase A 增"开工前核验"(Opus 4.8 官方 model id / context window / thinking·effort / 1M beta,不臆测)
- Phase A 实现范围增"泛化 Opus 4.7 专属逻辑"(isOpus47Model / OPUS_4_7_PATTERN / applyContext1mBeta /
effort 门控 / claude-client sanitizer,配回归测试)—— catalog 显示 ≠ 请求正确
- OpenRouter Opus 4.8 改 deferred(不臆测 slug),首轮只接 Anthropic direct
- opus 别名 / 默认先不动(仍 4.7),只新增显式 claude-opus-4-8,切换待 smoke 后用户拍板
- Phase D 拆 D0/D:D0 把 apply-discovery-diff 全量 flake + no-verify 事件记入 tech-debt op7418#30(本提交即 D0);
D 建议先于 A/B/C,代码 phase 不再靠 --no-verify
- Open Questions op7418#1/op7418#2 据上述决议收敛
本提交纯文档;pre-commit 同样因 apply-discovery-diff 全量 flake 用 --no-verify,已确认 docs-drift 绿。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
v0.56.x 计划 Phase 1:建立稳定性治理入口,并用当前源码重新核验 Notion/issue 列出的
7 个 issue(不采信 issue 自述根因)。
GitHub 侧(已在仓库生效,非本 commit 内容):
- 创建 milestone op7418#1「v0.56.x Stability / Trust」。
- 创建 9 个治理 label:P0-crash-or-interrupt / P0-data-loss-risk / P1-runtime-session /
P1-context / P1-file-reference / P1-installer-update / P1-performance / needs-repro /
v0.57+ parking-lot。
- 给 op7418#626/op7418#628/op7418#629/op7418#632/op7418#633/op7418#634/op7418#635 按复核结论打 milestone + 优先级 label。
本 commit 文件:
- .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml:bug 表单强制必填
版本/OS/runtime/provider-model/可复现/复现步骤/期望vs实际 + 影响面勾选;feature
表单注明 v0.56.x 冻结新功能 → v0.57+ parking-lot;config 关闭空白 issue + 冻结说明
与 Discussions 入口。
- .github/PULL_REQUEST_TEMPLATE.md:Summary / Repro+root cause / Changes / Tests /
Screenshots-logs / 自查清单(链到 CLAUDE.md 与 AGENTS.md,不复制维护)。
- .github/TRIAGE.md:对外冻结说明、label 体系、issue/PR triage 规则、自动化候选。
- v0.56.x-stability-trust.md:标 Phase 0 完成 + 新增「2026-06-19 Claude Code 源码复核」
表(7 issue 逐条 file:line 证据)。关键复核结论:
* op7418#632 ">100%" 确认是未 clamp 的 ratio*100 显示 bug(RunCockpit.tsx:169 等),分母
contextWindow 不可靠;"跨会话串" 源码不成立。
* op7418#629 空 assistant 已防护,残留真实 gap:is_error result 路径不清坏 sdk_session_id
(claude-client.ts:1908 先置 resultEmitted)。
* op7418#635 截图-only,最强候选 = SDK runtime 无自生成 keepalive(claude-client.ts:1956),
慢 proxy 静默 >330s 被 idle abort(B-019)。
* op7418#628 确认真实风险:@file origin path 在 MessageInput.tsx:161 丢失,body.mentions[]
送达但 route.ts 从不消费 → 写 .codepilot-uploads 副本,AI 改副本。
* op7418#634 根因不成立——5 个 notify/schedule 工具均注册(builtin-tools/index.ts:250),
issue 引用的 UI 串不在当前源码(疑旧版);附带 Plan 模式 list_tasks 泄漏。
* op7418#626 polling 排除(8h 间隔),候选 animate-pulse × backdrop-filter 重绘。
* op7418#633 mac 无法复现;NSIS-only + 未签名 + 无 portable + CI 不验安装启动。
- issue-tracker.md:新增「v0.56.x 治理 issue」看板索引表(指向 plan 复核表,不重复分析)。
验证:docs-drift 通过;npm run test(hook)。Phase 1 验收(milestone/labels/模板/冻结
说明就绪)达成。下一步 Phase 2:按复核结论修 chat 主链路(上下文百分比语义、context-cost
不阻断发送、Codex 多模态发送、发送后清草稿)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…e 2 op7418#1)
Signal: issue op7418#632 报"上下文 >100% / 假百分比 / 压缩后跳变";Phase 1 源码复核确认是
真实显示 bug("跨会话串"不成立)。
Triage(当前源码): 用量百分比 = usage.ratio*100,在 RunCockpit.tsx 与
RunCockpitPopoverContent.tsx 两处直接渲染、未封顶;usage.ratio = used / contextWindow,
而 contextWindow 来自 sdkContextWindow ?? latestSdkContextWindow ?? catalogContextWindow
(useContextUsage.ts)。很多第三方 proxy 不上报 context_window → 落到静态 catalog 兜底
(一个猜测值),used 又会在压缩后跳变 → 百分比蹦到 200%/500%。根因是"拿不可信的分母
算百分比",不是上下文真的超了。
Fix:
- useContextUsage.ts: 新增 ContextUsageData.contextWindowTrusted —— 仅当 SDK/上游真实
上报窗口时为 true(catalog 兜底不算)。三个 return 分支(baseline / snapshot / no-baseline)
都按各自来源正确赋值。不可信时不把窗口喂给 buildContextUsageBreakdown,dot-matrix 退回
按已用 token 的构成比例,不编造容量。
- RunCockpit.tsx: hasFullCtx 增加 && usage.contextWindowTrusted —— 不可信时自动落到既有的
绝对已用 token 显示(触发按钮)/ showUnknownCapacityBlock 分支(浮层,已测试的"容量未知"
路径)。百分比文案 clamp ≤100%。
- RunCockpitPopoverContent.tsx: 浮层 header 百分比同样 clamp ≤100%(防可信窗口被 used 短暂
超过时仍蹦 >100%)。
语义验收: 输入框右下角不可信时只显示已用绝对值;浮层不可信时只显示已用 + 不同种类构成
比例(无百分比/remaining/unused/假总量);可信时百分比封顶 100%。
Verify: typecheck 通过;context-window-trusted.test.ts 6 条 source-pin + 既有
run-cockpit-unknown-capacity / context-dot-matrix / context-usage-walk / context-breakdown
全绿;全量单测 3366/3366。未做:真实 untrusted-window provider 会话的 CDP 视觉走查
(fix 把 untrusted 路由到既有已发布的"容量未知"分支,风险低;视觉走查列为后续)。
Guardrail: context-window-trusted.test.ts 钉死 trusted 派生只认 SDK 来源、不可信时不喂窗口、
hasFullCtx 必须 gate trusted、两处显示 clamp ≤100%,防回退到"拿 catalog 当真实分母算百分比"。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Signal: Codex 复核 fixop7418#1(9ea29a4)后发现 P2 残留——文字已改成"只显示已用 token",
但输入框右下角触发按钮旁的 mini dot-bar 仍用 200K 兜底画出"用了多少/还剩多少"的容量
暗示,与"拿不到总长度就不显示容量"及 commit message 的"不编造容量"不一致。
Triage(当前源码): ContextDotMatrix.tsx 有 FALLBACK_CONTEXT_WINDOW=200_000,
minCellsPerKind=0(mini-bar)在窗口未知时用它当分母(:88);RunCockpit.tsx:200 的触发
按钮无条件渲染这个 mini-bar。所以即使 9ea29a4 把文字降级为绝对已用,小条仍画假容量。
minCellsPerKind=0 全仓只有 RunCockpit 触发按钮一个调用方。
Fix:
- RunCockpit.tsx: mini-bar 用 {hasFullCtx && (...)} 包裹——仅在可信窗口下渲染容量小条;
不可信时触发按钮只剩绝对已用 token 文本(贴合"输入框右下角只显示已用数值")。
- ContextDotMatrix.tsx: 删除 FALLBACK_CONTEXT_WINDOW(200K)。窗口未知时两种模式都按
used+pending 分配(构成视图,非容量%),不再编造容量。
Verify: typecheck 通过;context-dot-matrix.test.ts 旧的"unknown mini-bar 用 200K 兜底
(filled<=2)"语义改为新的"used 构成(filled>=8)";context-window-trusted.test.ts 加 2 条
guardrail(mini-bar gate 在 hasFullCtx + 源码无 200K 兜底残留);全量单测 3368/3368。
Guardrail: 两条 source-pin 钉死"触发按钮 mini-bar 必须 gate 在 hasFullCtx"且"ContextDotMatrix
不得再出现 FALLBACK_CONTEXT_WINDOW/200_000",防回退到拿假容量画小条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户复核 fixop7418#1 后明确显示格式:输入框右下角的上下文小标,在有可信窗口时显示
"百分比 + 已用上下文"(如 56.6% 452K),没有可信窗口时只显示已用(如 452K),
不单列"剩余"数字。
改动:RunCockpit.tsx 触发按钮 ratioText 的可信分支由 "{pct}%" 改为
"{pct}% {used}"(1 位小数,匹配用户给的 56.6% 示例);不可信/无数据分支不变。
context-window-trusted.test.ts 的 clamp pin 扩为同时断言"百分比 + 已用"格式。
验证:dev 应用热重载干净(✓ Compiled);context-window-trusted 8/8;typecheck(hook)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…llow-up)
Signal: 用户在运行的应用里看到 GLM-5-turbo(Claude Code/Native 会话)仍显示总上下文
200K,指出"这并不是我们知道的部分"。fixop7418#1 本应让 catalog 静态值不可信、只显示已用。
Triage(当前源码,用户 review 驱动): agent-loop.ts:641-651(Native)在 token_usage
没有 context_window 时,从静态 catalog 填 totalUsage.context_window = getContextWindow(modelId)
(GLM-5-turbo 在 catalog 是 z.ai 核实的 202752)。而 context-usage-walk 把
token_usage.context_window 当作 SDK 实报窗口读,fixop7418#1 的 contextWindowTrusted 据此判可信
→ catalog 猜测被"洗白"成可信 → Native GLM 显示 200K。即上游 mutator 打败了 helper 修复
(feedback_fix_all_consumers)。claude-client(Claude Code)只从 SDK modelUsage 写,不洗白;
ContextUsageIndicator 是死组件(无人 import)。
Fix: 删掉 agent-loop 的 catalog 洗白。Native 无 runtime 实报时 context_window 留空 →
useContextUsage 回落 catalog 为不可信 → 只显示已用绝对值,不再有假百分比/假总量。
仅对新 turn 生效(历史消息已存的 context_window 不改写,遵守不改用户数据;旧会话发新消息后转为已用-only)。
Verify: typecheck;context-window-trusted.test.ts 新增 pin 断言 agent-loop 不再
`.context_window = catalogWindow`;该文件 9 测 + agent-loop-error-event 全过。运行中 dev 应用
server 重编译干净(Native GLM 需发新消息验证)。
Guardrail: source-pin 防 Native 再把 catalog 洗进 SDK-authoritative 字段。
设计记录(用户批准"先记计划再实现"): v0.56.x 计划写入 context-window 来源优先级修订设计
(runtime 实报 > provider 配置 contextWindow > 压缩阈值 > catalog 不可信)+ 跨 Runtime 用户
配置源(op7418#1,待实现) + 显示分母对齐压缩阈值(op7418#3,待实现)。本提交是设计第一步(去洗白)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
把"为什么 GLM 显示 200K + 窗口来源该怎么改"写成评审稿放进 v0.56.x Phase 2,按
外部事实 / 本地证据(file:line) / 推断与设计三层分写,供 Codex 核实。
要点:
- Agent SDK v0.2.111 的 modelUsage.contextWindow(sdk.d.ts:945)是未文档化字段,来自
SDK 内置模型目录而非 API;第一方可靠、第三方(经 base_url 的 GLM)返回通用默认值;
无 SDK 设置可覆盖;Anthropic 建议自维护窗口表。
- 实测 GLM 会话 token_usage.context_window=200000 ≠ 本地 catalog 202752,证实来自 SDK
默认而非 catalog/Native 洗白;该会话是 Claude Code(故上一提交的 Native 修复不覆盖它)。
- 修订设计:窗口来源优先级 = 用户覆盖 > 已核实 catalog/provider 配置 > SDK(仅第一方) >
只显示已用;第三方忽略 SDK 默认值;跨 Runtime;显示分母对齐压缩阈值(op7418#3)。
- 列出待定决策(已核实优先 vs 纯手动) + 给 Codex 的 5 个核实点。
未改任何产品代码(纯文档)。op7418#1/op7418#3 实现待 Codex 核实后进行。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Codex 复核设计稿后订正(实现 op7418#1/op7418#3 前必须):
- A:原"官方文档不记载 contextWindow/maxOutputTokens"不准 → 改为 SDK TypeScript
reference 有字段定义,是 cost-tracking 指南未解释来源/可信度。
- B/C:原"catalog 202752 比 SDK 200000 更准且 z.ai 核实"站不住 → z.ai 官方写
200K/128K,catalog 该条来源存疑;结论收敛为"SDK 200000 不可作为 provider 实报采信",
不延伸到"catalog 更准";另标记需单独核 model-context.ts:42 的真实来源。
- D + 决策日志:统一优先级(消除冲突,旧决策日志把第三方 SDK 又洗白成可信)→
用户手动覆盖 > provider/model 配置且来源已验证 > 第一方 runtime 实报 > 只显示已用;
第三方 SDK contextWindow 默认不可信、无明确来源 catalog 不当可信%显示。
- "Anthropic 官方建议自维护表"未核到原文 → 降级为工程结论。
- 澄清:用户实际看到 200K 的 GLM 会话是 Claude Code(SDK 默认 200000),非 Native 洗白
路径(f79fd54 的 Native 修复有效但治另一条路径)。
- E:决策收敛为一条基线 + 剩余一项请用户定(第一方 SDK 实报是否自动显示百分比)。
Codex 核为真的部分(sdk.d.ts:945 字段、代码写入 token_usage、历史 SDK 窗口被当可信、
Native 洗白已去、显示分母 vs 压缩阈值脱节)保留。纯文档,未动产品代码。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
F 段核实点 op7418#1 还残留旧"官方文档未记载(A)",与已订正的 A 段不一致。改为:
sdk.d.ts:945 的 contextWindow/maxOutputTokens 存在,SDK TypeScript reference 已列,
只是 cost-tracking 指南未解释来源/可信度。纯文档。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…#632 / Phase 2 ①)
Signal: 用户 GLM-5-turbo(Claude Code 经代理)显示总上下文 200K,且 Codex 核实 SDK 的
modelUsage.contextWindow 来自 SDK 内置目录、对第三方是通用默认值、无 SDK 设置可覆盖。
Triage: claude-client.ts extractTokenUsage 把 SDK modelUsage.contextWindow 无条件写入
token_usage.context_window;walk + fixop7418#1 据此判可信 → 第三方代理(GLM)的 SDK 默认 200000
被当可信显示。Native 的 catalog 洗白已于 f79fd54 去掉;本提交补 SDK 路径。
Fix(Codex 统一口径"第一方 runtime 实报可信、第三方不可信"):
- ai-provider.ts 导出 isFirstPartyAnthropicEndpoint(baseUrl)(空/anthropic.com → 第一方)。
- extractTokenUsage 增 trustContextWindow,仅 true 时写 context_window;两个调用点都传
isFirstPartyAnthropicEndpoint(resolved.provider?.base_url)。第三方(自定义 base_url,如 GLM)
→ 不写 context_window → useContextUsage 回落 catalog 为不可信 → 只显示已用。
效果 + 边界: 第一方 Anthropic 继续显示百分比+已用;第三方代理新 turn 起只显示已用。
仅对新写入生效(历史消息已存的 context_window 不改写,遵守不改用户数据);现有 GLM 会话
仍显示旧值,需新会话/新 turn 验证(walk 会读历史,故旧会话需自然滚动出旧窗口或新建)。
Verify: typecheck;extract-token-usage-context-window.test.ts 增 2 pin(gate + 两调用点传
第一方判别);全量 3371/3371。
Guardrail: source-pin 钉死 context_window 写入受 trustContextWindow 门控 + 两调用点必须传
isFirstPartyAnthropicEndpoint,防回退到无条件信任第三方 SDK 窗口。
remaining(Phase 2 ①/③ 未完): provider/model 配置窗口作为最高优先可信源(用户覆盖) + 渲染层
对现有会话按第一方 gate(治旧会话) + op7418#3 显示分母对齐压缩阈值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
计划文档状态审计修正(决策日志准、但概览层过期):
- frontmatter 状态行:📋 待接手 → 🚧 Phase 0/1 已完成、Phase 2 进行中。
- 「状态总览」表:Phase 1 待开始 → ✅ 已完成(2026-06-19);Phase 2 待开始 → 🚧 进行中。
- Phase 2 加进度 note:Composer/Context 主链路 op7418#1op7418#5 全部收口(含 commit + op7418#3 真实
Codex 冒烟回复 circle);Session/Stream cluster op7418#629/op7418#635 + 终态原因码 + 压缩回滚
+ 诊断导出字段待续。
- Phase 2 执行清单 4 项已完成项 [ ]→[x](上下文 UI 语义 / context-cost 去阻断 /
Codex 多模态发送 / 发送后草稿清理)。
CLAUDE.md 执行计划段新增「完成即回写进度(与 Codex 对齐协作)」:任一 Phase/子项做完
必须立即回写三处且一致——执行清单勾选 / 状态总览表+frontmatter / 决策日志(commit
+验证结论);Claude 实施+回写、Codex 审查+维护;三者不一致视为状态失真须先对齐。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
打回上一条状态同步的一处失真:我把 op7418#4/op7418#5「发送后内容残留」标成完成(checklist [x] +
进度 note 列为 done),但同一文档决策日志(2026-06-20 条)已写明用户再次确认"内容已发出
但文本仍残留输入框"、op7418#615 source-pin 不覆盖该症状、不能算闭环——状态表/清单与决策日志
自相矛盾,违反刚加的"三者必须一致"。
修正(与决策日志对齐):
- checklist「复现并修发送后内容残留」[x] → [ ],标注"待复核/待修复(用户 2026-06-20 再报)"。
- Phase 2 进度 note:拆分——op7418#4/op7418#5 仅失败保留有基础修复(op7418#615),发送成功后文本残留待复核;
note 标题从"主链路已收口"改为"op7418#1op7418#3 收口、op7418#4/op7418#5 待复核";待续列表补回 op7418#4/op7418#5(重新打开)。
- op7418#2 context-cost 非阻断保持完成(checklist [x] + note)不变。
后续修 op7418#4/op7418#5 时重点:PromptInput 受控/非受控清空边界、setInputValue('') 与
controller.textInput.clear() 是否同源、成功 accepted 后 remount/local draft 恢复、
badge/confirm/image 分支与普通 Enter 分支是否一致(决策日志已记排查方向)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
按"完成即回写进度"规则同步三处:
- checklist「复现并修发送后内容残留」[ ]→[x],标注已修 + CDP 验证 + 根因/修法(de123df)。
- Phase 2 进度 note:op7418#1op7418#5 全部落地;op7418#4/op7418#5 从"待复核"改为"已定位+修复"(含根因/CDP 结论);
待续列表移除 op7418#4/op7418#5、只留 Session/Stream cluster。
- 决策日志加同日条目:CDP 埋点定位 = 首条消息 accept 布局翻转 remount composer、inputValue
从 sessionStorage 草稿重读;修法 = accept 处清草稿;3401/3401 + CDP 文本/图文首条 800ms 即清。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户在浏览器实测不残留、仅桌面 App 残留 → Claude 协助完整重启 electron:dev(kill 整棵
进程树 + 释放 3000 + 后台重启)→ 用户在重启后真实 App 验证发送即清空 → op7418#4/op7418#5 闭环。
根因:de123df(page.tsx accept 处清首条草稿)一直是对的;用户残留是 Electron dev 没把
page.tsx 改动热更新进 renderer、窗口刷新无效,得整进程重启。这解释了全程「Claude CDP
浏览器清、用户残留」的矛盾——不是 Electron 行为差异,是构建新鲜度差异(Claude 浏览器硬刷
过有修复、用户 Electron 旧构建没有)。
回写:checklist [x](用户真实 App 验证)、进度 note op7418#1op7418#5 全闭环、验收去 ⚠️、决策日志加
闭环条目 + 教训(UI 修复在桌面 App 验证必须整重启 electron:dev)。Codex P1(prefill/
initialValue 回灌)仍是 de123df 的真实独立漏洞、值得单独补,与本次残留无关。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
纯文档同步,无代码改动。目的:让下一个进程打开文档时不从旧状态误判进度。
三处状态表此前已标 Phase 0/1 ✅、决策日志也已确认完成,唯独执行清单 checkbox
与 README 索引、issue-tracker op7418#632 仍停在旧值——三处不一致即状态失真,本次对齐。
README.md:
- v0.56.x 索引行状态列 "📋 待 Phase 0 收束" → "🚧 Phase 0/1 ✅;Phase 2 进行中
(Composer/Context 主链路 op7418#1op7418#5 闭环,Session/Stream cluster op7418#629/op7418#635 待续)",
追上 plan frontmatter 与决策日志。
v0.56.x-stability-trust.md:
- Phase 0 执行清单 8 项 [ ]→[x],逐条带回溯(3360/3360、dd4ead4、b853188/2de9c2b)。
A2 计时器项如实标注:按 keyed-remount 构造性消除 + 截图不可判别记录入 Smoke Ledger,
非逐帧视觉确认(反假数据,不谎称做了视觉确认)。
- Phase 1 执行清单 5 项 [ ]→[x],带回溯(milestone op7418#1 / 9 labels / .github/TRIAGE.md)。
issue-tracker.md:
- op7418#632 状态 "🔴 待修" → "🟡 假%已修,item3 分母对齐待续"。核心显示 bug(假百分比/>100%)
已由 effective-base-URL 写入 gate + 渲染期 trusted gate + clamp 修复并经真实 GLM
会话验证;item3(显示分母对齐压缩阈值)是独立待续阶段,故标部分修复而非已修复。
- 顶部"最后更新"同步到 2026-06-26 + op7418#632 同步说明。
验证:git diff 确认仅 3 文档、16/16 行 checkbox 与状态文字,无代码/意外文件。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
- docs/research/ai-sdk-7-toolloop-parity-gaps.md: 新增「Phase 5 处置」节,全部 gap
收口——P1×3 关闭(op7418#1/op7418#2 补偿由 parity 8/8 复跑锁定;op7418#3 降级论证:Phase 4 已证
approval HMAC 不需要 SDK toolApproval 停机语义,维持 in-execute 路线),
P2/P3 关闭或 backlog(op7418#4/op7418#5 列为替换路线前置条件,op7418#7 归档 tech-debt op7418#49op7418#8 有 Phase 5 新实证)
- scripts/smoke-ai-sdk7-phase5-decision.ts: 新增决策门对照 smoke——prod runAgentLoop
与 POC runToolLoopAgentPoc 用同一 AgentLoopOptions 逐场景对照(长文本 / approval
批准 / approval 拒绝 / abort→continue),机械比较归一化事件序列 + 尾部契约 +
usage 存在性;DB 只读、数据目录隔离、输出全 scrub。探针注意:approval 批准分支
用 printf(echo 命中 permission-checker 自动放行规则不会触发 ask)
- docs/exec-plans/active/_smoke-evidence/ai-sdk7-phase5-decision-smoke.json:
OpenRouter 真实渠道 4/4 场景 contractMatch=true(input_tokens 逐场景完全相同,
tool_result 逐字相同,中断轮双侧 done 收尾、同 session 续发一次通过);
凭据形态 grep=0
- docs/research/ai-sdk-7-adoption-decision.md: 新增采用决策文档——结论 partial
(依赖升级 go / provider 能力 capability-gated go / Phase 4 外围能力 go /
@ai-sdk/mcp 与默认 loop 替换 no-go-现在),四层 rollback plan(能力开关→
wrapper→runtime switch→known-good version),每项结论标注 Phase 1-5 证据来源;
默认 Runtime 切换留人类闸门
- docs/exec-plans/tech-debt-tracker.md: 新增 op7418#49(tool-error part 被两条 loop
一致吞掉的既有 UX 债,独立于采用决策)
- docs/exec-plans/active/ai-sdk-7-runtime-loop-adoption.md: Phase 5 状态回写 +
决策日志 + Smoke Ledger / Loop Ledger 各一行
- docs/research/README.md: 索引新增决策文档条目
验证: npm run test 3598/3598 全绿;smoke 4/4 contractMatch(1 个 fix cycle 收敛,
两处均为脚本层问题非 loop 差异);src/ 零改动(默认 Runtime/聊天路径零变化)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户批准 partial(2026-07-04, run issue op7418#10): 采用 ai@7/@ai-sdk/* 依赖升级、
provider 参数能力 capability-gated、openai-chat image wrapper、timeout 原因码/
approval HMAC/trace 脱敏四件套(默认值经用户确认); @ai-sdk/mcp adapter 与
ToolLoopAgent 默认 loop 替换均不采用(留实验路径)。发版前保留官方一方 key
smoke gate。冲突仅 ai-sdk-7 计划决策日志一处,union 双方条目解决。
五个 phase 全部经 hands-off loop 完成并 Codex accepted(issues op7418#1/op7418#6/op7418#7/op7418#8/op7418#10)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
canblmz1 pushed a commit to canblmz1/CodePilot that referenced this pull request Aug 28, 2026
…lease
prefix-safe-json 0.2.0 -> 0.4.3 (exact). 0.4.3 is a security patch
(GHSA-3xpw-9694-2xxp) fixing three root causes in the AI SDK adapter/gate
this integration depends on:
1. AiSdkStreamAdapter.push() used to silently drop every raw event once
it had already observed its own terminal, so late/contradictory
evidence for a call never reached the coordinator at all.
2. takeDecision() used to read a decision snapshot frozen at finish()
time instead of the coordinator's live diagnostics, so evidence
recorded after finish() but before that call's authority was consumed
was never consulted.
3. A raw event carrying conflicting id/toolCallId used to silently
prefer id instead of failing the stream closed.
No public API change - createAiSdkExecutionGuard()/push()/finish()/
takeDecision() and the ExecuteDecision/NonExecutableDecision shapes this
integration reads (action, toolCallId, reason) are unchanged, confirmed
directly against the installed package's .d.ts, not assumed.
Verified against the real 0.4.3 install (resolved version, and lockfile
integrity hash, both confirmed exactly 0.4.3):
- npx tsc --noEmit (full project): clean, 0 errors.
- src/__tests__/unit/execution-guard.test.ts: 16/16 passing, identical
to the 0.2.0 result.
Adds src/__tests__/unit/execution-guard-post-terminal-authority.test.ts,
answering the actual question this bump exists to answer: does this
integration's own code exercise the fix, not just "does the library
still pass its own tests." resolvePendingExecutions() in
execution-guard.ts reads `decisions` directly off guard.finish()'s own
return value in the same statement - it never calls takeDecision().
A fresh guard is created per step and is never reused once its finish()
is read, so there is no async gap between this integration's own
finish() call and its own decision consumption for GHSA-3xpw-9694-2xxp's
literal finish()-to-takeDecision() window to open in here.
What is live in this integration is root cause op7418#1: whether a
late/contradicting raw event that arrives before a step's own
resolvePendingExecutions() call - anywhere in that step's fullStream -
correctly revokes authority instead of being silently dropped by the
adapter. The new test proves that directly, through this repo's real
execution-guard.ts functions (createStepGuard/registerDeferredExecution/
resolvePendingExecutions - the exact call path agent-loop.ts uses), plus
a control case confirming the fix does not overcorrect a genuinely clean
step. A second test exercises the raw prefix-safe-json library
(createAiSdkExecutionGuard directly, real push/finish/takeDecision, no
synthetic decision object) to confirm the literal advisory scenario is
fixed at the library level.
package-lock.json regenerated with `npm install prefix-safe-json@0.4.3
--save-exact`, not hand-edited.
Sign up for freeto 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.

2 participants

@xuxu777xu@op7418
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat: Windows platform adaptation by xuxu777xu · Pull Request #1 · op7418/CodePilot · GitHub
Skip to content

feat: Windows platform adaptation - #1

Merged
op7418 merged 2 commits into
op7418:mainfrom
xuxu777xu:feat/windows-drive-switcher
Feb 7, 2026
Merged

feat: Windows platform adaptation#1
op7418 merged 2 commits into
op7418:mainfrom
xuxu777xu:feat/windows-drive-switcher

Conversation

@xuxu777xu

@xuxu777xuxuxu777xu commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

Summary

CodePilot 原本仅支持 macOS,本 PR 添加完整的 Windows 平台适配,使其可以在 Windows 上正常构建、运行和使用。

Changes

跨平台基础设施

  • 新增 src/lib/platform.ts:统一的跨平台工具模块,包含 Claude CLI 发现逻辑(Windows .cmd/.bat shell 处理、where/which 回退)、PATH 扩展(AppData/npm 等 Windows 路径)
  • 重构 src/app/api/claude-status/route.ts:移除硬编码的 Unix 路径,改用共享的 platform 工具
  • 重构 src/lib/claude-client.ts:同上,并确保 USERPROFILE 和扩展 PATH 在 SDK 子进程中可用

Electron 主进程

  • electron/main.ts
    • Windows 进程派生使用 windowsHide 防止控制台窗口闪烁
    • PATH 构建适配 Windows 分隔符(;)和目录结构(AppData/npm)
    • 窗口标题栏适配:macOS hiddenInset / Windows hidden + titleBarOverlay
    • 图标适配:Windows 使用 .ico
    • loadUserShellEnv() 跳过非 macOS 平台

构建配置

  • electron-builder.yml:新增 win + nsis 构建目标,支持自定义安装目录、桌面/开始菜单快捷方式
  • package.json:新增 electron:pack:win 脚本,原 electron:pack 改为平台无关
  • build/icon.ico:Windows 应用图标

UI 适配

  • src/components/chat/FolderPicker.tsx:新增盘符下拉切换器,解决 Windows 盘符根目录无法向上导航的问题
  • src/app/api/files/browse/route.ts:API 返回可用 Windows 盘符列表
  • src/components/skills/SkillsManager.tsx:修复 key 重复警告

Test plan

  • Windows 上 npm run electron:pack:win 构建成功
  • 安装后启动,Claude CLI 自动检测并连接
  • 标题栏样式正确(隐藏标题栏 + overlay 控制按钮)
  • FolderPicker 盘符切换正常工作
  • macOS 上 npm run electron:pack:mac 构建无回归

🤖 Generated with Claude Code

xuxu777xuand others added 2 commits February 7, 2026 13:29
When navigating to a drive root on Windows (e.g. C:\), path.dirname
returns itself, disabling the "go up" button and trapping the user on
that drive. This adds a compact dropdown next to the up button that
lists all available drives (auto-detected via fs.accessSync), allowing
quick switching between drives. macOS/Linux are unaffected (empty array,
dropdown not rendered).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add src/lib/platform.ts: cross-platform Claude CLI discovery
(candidate paths, .cmd/.bat shell handling, where/which fallback)
- Refactor claude-status route and claude-client to use shared platform utils
- Electron main: Windows process spawning (windowsHide), PATH construction
with AppData/npm dirs, titleBarOverlay, .ico icon support
- electron-builder.yml: add win/nsis build targets
- package.json: add electron:pack:win script
- FolderPicker: drive switcher dropdown for navigating between drives
- SkillsManager: fix duplicate key warning with filePath fallback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@xuxu777xuxuxu777xu changed the title feat: add Windows drive switcher in FolderPickerfeat: Windows platform adaptationFeb 7, 2026
@op7418
op7418 merged commit b819eb7 into op7418:mainFeb 7, 2026
op7418 added a commit that referenced this pull request Apr 12, 2026
…ion for Native Runtime
Two feature gaps where Native Runtime didn't match SDK Runtime, both
surfaced during post-hermes-upgrade manual testing:
── #1: Compression notification now human-readable ──
Before: chat/route.ts:402 emitted `message: 'context_compressed'` as
a machine string. useSSEStream's notification branch showed this raw
string in the status bar — users saw "context_compressed" flash by.
After: message is now `"Context compressed: N older messages summarized,
~X tokens saved"` with structured `stats: { messagesCompressed, tokensSaved }`
for future rich UI handling. Added `subtype: 'context_compressed'` for
dedicated frontend handlers.
── #3: AskUserQuestion tool for Native Runtime ──
Before: only SDK Runtime had AskUserQuestion (built into Claude Code CLI).
Native Runtime had no such tool, so the model could never ask structured
questions — the existing AskUserQuestionUI in PermissionPrompt.tsx was
unreachable dead UI code for Native Runtime users.
After:
- New builtin tool `src/lib/builtin-tools/ask-user-question.ts`
registered in index.ts, condition 'always'
- Zod schema: 1-6 questions, each with 1-6 options, optional multiSelect
- Execute receives answers from permission flow (injected by frontend)
and formats as Q/A pairs for the model
- permission-checker.ts: new ALWAYS_ASK_TOOLS set ensures AskUserQuestion
(and ExitPlanMode) always show UI even in trust mode — without this,
trust mode would auto-approve and return empty answers
- PermissionPrompt.tsx: NEVER_AUTO_APPROVE set prevents full_access mode
from auto-approving AskUserQuestion — the UI must render so the user
can answer
The data flow:
Model → AskUserQuestion({ questions }) → permission wrapper intercepts
→ SSE permission_request → frontend AskUserQuestionUI renders
→ user picks options → updatedInput({ questions, answers }) → tool
execute formats answers → model gets "Q: ... A: ..." string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KevinYoung-Kw referenced this pull request in KevinYoung-Kw/CodePilot Apr 15, 2026
**补充修复**
在 #1 斜杠命令保留已有文本的修复基础上,进一步确保选择命令后光标自动定位到输入框尾部,而不是默认的首部。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KevinYoung-Kw referenced this pull request in KevinYoung-Kw/CodePilot Apr 15, 2026
**补充修复**
在 #1 斜杠命令保留已有文本的修复基础上,进一步确保选择命令后光标自动定位到输入框尾部,而不是默认的首部。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
v0.56.x 计划 Phase 1:建立稳定性治理入口,并用当前源码重新核验 Notion/issue 列出的
7 个 issue(不采信 issue 自述根因)。
GitHub 侧(已在仓库生效,非本 commit 内容):
- 创建 milestone #1「v0.56.x Stability / Trust」。
- 创建 9 个治理 label:P0-crash-or-interrupt / P0-data-loss-risk / P1-runtime-session /
P1-context / P1-file-reference / P1-installer-update / P1-performance / needs-repro /
v0.57+ parking-lot。
- 给 #626/#628/#629/#632/#633/#634/#635 按复核结论打 milestone + 优先级 label。
本 commit 文件:
- .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml:bug 表单强制必填
版本/OS/runtime/provider-model/可复现/复现步骤/期望vs实际 + 影响面勾选;feature
表单注明 v0.56.x 冻结新功能 → v0.57+ parking-lot;config 关闭空白 issue + 冻结说明
与 Discussions 入口。
- .github/PULL_REQUEST_TEMPLATE.md:Summary / Repro+root cause / Changes / Tests /
Screenshots-logs / 自查清单(链到 CLAUDE.md 与 AGENTS.md,不复制维护)。
- .github/TRIAGE.md:对外冻结说明、label 体系、issue/PR triage 规则、自动化候选。
- v0.56.x-stability-trust.md:标 Phase 0 完成 + 新增「2026-06-19 Claude Code 源码复核」
表(7 issue 逐条 file:line 证据)。关键复核结论:
* #632 ">100%" 确认是未 clamp 的 ratio*100 显示 bug(RunCockpit.tsx:169 等),分母
contextWindow 不可靠;"跨会话串" 源码不成立。
* #629 空 assistant 已防护,残留真实 gap:is_error result 路径不清坏 sdk_session_id
(claude-client.ts:1908 先置 resultEmitted)。
* #635 截图-only,最强候选 = SDK runtime 无自生成 keepalive(claude-client.ts:1956),
慢 proxy 静默 >330s 被 idle abort(B-019)。
* #628 确认真实风险:@file origin path 在 MessageInput.tsx:161 丢失,body.mentions[]
送达但 route.ts 从不消费 → 写 .codepilot-uploads 副本,AI 改副本。
* #634 根因不成立——5 个 notify/schedule 工具均注册(builtin-tools/index.ts:250),
issue 引用的 UI 串不在当前源码(疑旧版);附带 Plan 模式 list_tasks 泄漏。
* #626 polling 排除(8h 间隔),候选 animate-pulse × backdrop-filter 重绘。
* #633 mac 无法复现;NSIS-only + 未签名 + 无 portable + CI 不验安装启动。
- issue-tracker.md:新增「v0.56.x 治理 issue」看板索引表(指向 plan 复核表,不重复分析)。
验证:docs-drift 通过;npm run test(hook)。Phase 1 验收(milestone/labels/模板/冻结
说明就绪)达成。下一步 Phase 2:按复核结论修 chat 主链路(上下文百分比语义、context-cost
不阻断发送、Codex 多模态发送、发送后清草稿)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: issue #632 报"上下文 >100% / 假百分比 / 压缩后跳变";Phase 1 源码复核确认是
真实显示 bug("跨会话串"不成立)。
Triage(当前源码): 用量百分比 = usage.ratio*100,在 RunCockpit.tsx 与
RunCockpitPopoverContent.tsx 两处直接渲染、未封顶;usage.ratio = used / contextWindow,
而 contextWindow 来自 sdkContextWindow ?? latestSdkContextWindow ?? catalogContextWindow
(useContextUsage.ts)。很多第三方 proxy 不上报 context_window → 落到静态 catalog 兜底
(一个猜测值),used 又会在压缩后跳变 → 百分比蹦到 200%/500%。根因是"拿不可信的分母
算百分比",不是上下文真的超了。
Fix:
- useContextUsage.ts: 新增 ContextUsageData.contextWindowTrusted —— 仅当 SDK/上游真实
上报窗口时为 true(catalog 兜底不算)。三个 return 分支(baseline / snapshot / no-baseline)
都按各自来源正确赋值。不可信时不把窗口喂给 buildContextUsageBreakdown,dot-matrix 退回
按已用 token 的构成比例,不编造容量。
- RunCockpit.tsx: hasFullCtx 增加 && usage.contextWindowTrusted —— 不可信时自动落到既有的
绝对已用 token 显示(触发按钮)/ showUnknownCapacityBlock 分支(浮层,已测试的"容量未知"
路径)。百分比文案 clamp ≤100%。
- RunCockpitPopoverContent.tsx: 浮层 header 百分比同样 clamp ≤100%(防可信窗口被 used 短暂
超过时仍蹦 >100%)。
语义验收: 输入框右下角不可信时只显示已用绝对值;浮层不可信时只显示已用 + 不同种类构成
比例(无百分比/remaining/unused/假总量);可信时百分比封顶 100%。
Verify: typecheck 通过;context-window-trusted.test.ts 6 条 source-pin + 既有
run-cockpit-unknown-capacity / context-dot-matrix / context-usage-walk / context-breakdown
全绿;全量单测 3366/3366。未做:真实 untrusted-window provider 会话的 CDP 视觉走查
(fix 把 untrusted 路由到既有已发布的"容量未知"分支,风险低;视觉走查列为后续)。
Guardrail: context-window-trusted.test.ts 钉死 trusted 派生只认 SDK 来源、不可信时不喂窗口、
hasFullCtx 必须 gate trusted、两处显示 clamp ≤100%,防回退到"拿 catalog 当真实分母算百分比"。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: Codex 复核 fix#1(b842628)后发现 P2 残留——文字已改成"只显示已用 token",
但输入框右下角触发按钮旁的 mini dot-bar 仍用 200K 兜底画出"用了多少/还剩多少"的容量
暗示,与"拿不到总长度就不显示容量"及 commit message 的"不编造容量"不一致。
Triage(当前源码): ContextDotMatrix.tsx 有 FALLBACK_CONTEXT_WINDOW=200_000,
minCellsPerKind=0(mini-bar)在窗口未知时用它当分母(:88);RunCockpit.tsx:200 的触发
按钮无条件渲染这个 mini-bar。所以即使 b842628 把文字降级为绝对已用,小条仍画假容量。
minCellsPerKind=0 全仓只有 RunCockpit 触发按钮一个调用方。
Fix:
- RunCockpit.tsx: mini-bar 用 {hasFullCtx && (...)} 包裹——仅在可信窗口下渲染容量小条;
不可信时触发按钮只剩绝对已用 token 文本(贴合"输入框右下角只显示已用数值")。
- ContextDotMatrix.tsx: 删除 FALLBACK_CONTEXT_WINDOW(200K)。窗口未知时两种模式都按
used+pending 分配(构成视图,非容量%),不再编造容量。
Verify: typecheck 通过;context-dot-matrix.test.ts 旧的"unknown mini-bar 用 200K 兜底
(filled<=2)"语义改为新的"used 构成(filled>=8)";context-window-trusted.test.ts 加 2 条
guardrail(mini-bar gate 在 hasFullCtx + 源码无 200K 兜底残留);全量单测 3368/3368。
Guardrail: 两条 source-pin 钉死"触发按钮 mini-bar 必须 gate 在 hasFullCtx"且"ContextDotMatrix
不得再出现 FALLBACK_CONTEXT_WINDOW/200_000",防回退到拿假容量画小条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
用户复核 fix#1 后明确显示格式:输入框右下角的上下文小标,在有可信窗口时显示
"百分比 + 已用上下文"(如 56.6% 452K),没有可信窗口时只显示已用(如 452K),
不单列"剩余"数字。
改动:RunCockpit.tsx 触发按钮 ratioText 的可信分支由 "{pct}%" 改为
"{pct}% {used}"(1 位小数,匹配用户给的 56.6% 示例);不可信/无数据分支不变。
context-window-trusted.test.ts 的 clamp pin 扩为同时断言"百分比 + 已用"格式。
验证:dev 应用热重载干净(✓ Compiled);context-window-trusted 8/8;typecheck(hook)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: 用户在运行的应用里看到 GLM-5-turbo(Claude Code/Native 会话)仍显示总上下文
200K,指出"这并不是我们知道的部分"。fix#1 本应让 catalog 静态值不可信、只显示已用。
Triage(当前源码,用户 review 驱动): agent-loop.ts:641-651(Native)在 token_usage
没有 context_window 时,从静态 catalog 填 totalUsage.context_window = getContextWindow(modelId)
(GLM-5-turbo 在 catalog 是 z.ai 核实的 202752)。而 context-usage-walk 把
token_usage.context_window 当作 SDK 实报窗口读,fix#1 的 contextWindowTrusted 据此判可信
→ catalog 猜测被"洗白"成可信 → Native GLM 显示 200K。即上游 mutator 打败了 helper 修复
(feedback_fix_all_consumers)。claude-client(Claude Code)只从 SDK modelUsage 写,不洗白;
ContextUsageIndicator 是死组件(无人 import)。
Fix: 删掉 agent-loop 的 catalog 洗白。Native 无 runtime 实报时 context_window 留空 →
useContextUsage 回落 catalog 为不可信 → 只显示已用绝对值,不再有假百分比/假总量。
仅对新 turn 生效(历史消息已存的 context_window 不改写,遵守不改用户数据;旧会话发新消息后转为已用-only)。
Verify: typecheck;context-window-trusted.test.ts 新增 pin 断言 agent-loop 不再
`.context_window = catalogWindow`;该文件 9 测 + agent-loop-error-event 全过。运行中 dev 应用
server 重编译干净(Native GLM 需发新消息验证)。
Guardrail: source-pin 防 Native 再把 catalog 洗进 SDK-authoritative 字段。
设计记录(用户批准"先记计划再实现"): v0.56.x 计划写入 context-window 来源优先级修订设计
(runtime 实报 > provider 配置 contextWindow > 压缩阈值 > catalog 不可信)+ 跨 Runtime 用户
配置源(#1,待实现) + 显示分母对齐压缩阈值(#3,待实现)。本提交是设计第一步(去洗白)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
把"为什么 GLM 显示 200K + 窗口来源该怎么改"写成评审稿放进 v0.56.x Phase 2,按
外部事实 / 本地证据(file:line) / 推断与设计三层分写,供 Codex 核实。
要点:
- Agent SDK v0.2.111 的 modelUsage.contextWindow(sdk.d.ts:945)是未文档化字段,来自
SDK 内置模型目录而非 API;第一方可靠、第三方(经 base_url 的 GLM)返回通用默认值;
无 SDK 设置可覆盖;Anthropic 建议自维护窗口表。
- 实测 GLM 会话 token_usage.context_window=200000 ≠ 本地 catalog 202752,证实来自 SDK
默认而非 catalog/Native 洗白;该会话是 Claude Code(故上一提交的 Native 修复不覆盖它)。
- 修订设计:窗口来源优先级 = 用户覆盖 > 已核实 catalog/provider 配置 > SDK(仅第一方) >
只显示已用;第三方忽略 SDK 默认值;跨 Runtime;显示分母对齐压缩阈值(#3)。
- 列出待定决策(已核实优先 vs 纯手动) + 给 Codex 的 5 个核实点。
未改任何产品代码(纯文档)。#1/#3 实现待 Codex 核实后进行。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Codex 复核设计稿后订正(实现 #1/#3 前必须):
- A:原"官方文档不记载 contextWindow/maxOutputTokens"不准 → 改为 SDK TypeScript
reference 有字段定义,是 cost-tracking 指南未解释来源/可信度。
- B/C:原"catalog 202752 比 SDK 200000 更准且 z.ai 核实"站不住 → z.ai 官方写
200K/128K,catalog 该条来源存疑;结论收敛为"SDK 200000 不可作为 provider 实报采信",
不延伸到"catalog 更准";另标记需单独核 model-context.ts:42 的真实来源。
- D + 决策日志:统一优先级(消除冲突,旧决策日志把第三方 SDK 又洗白成可信)→
用户手动覆盖 > provider/model 配置且来源已验证 > 第一方 runtime 实报 > 只显示已用;
第三方 SDK contextWindow 默认不可信、无明确来源 catalog 不当可信%显示。
- "Anthropic 官方建议自维护表"未核到原文 → 降级为工程结论。
- 澄清:用户实际看到 200K 的 GLM 会话是 Claude Code(SDK 默认 200000),非 Native 洗白
路径(681706b 的 Native 修复有效但治另一条路径)。
- E:决策收敛为一条基线 + 剩余一项请用户定(第一方 SDK 实报是否自动显示百分比)。
Codex 核为真的部分(sdk.d.ts:945 字段、代码写入 token_usage、历史 SDK 窗口被当可信、
Native 洗白已去、显示分母 vs 压缩阈值脱节)保留。纯文档,未动产品代码。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
F 段核实点 #1 还残留旧"官方文档未记载(A)",与已订正的 A 段不一致。改为:
sdk.d.ts:945 的 contextWindow/maxOutputTokens 存在,SDK TypeScript reference 已列,
只是 cost-tracking 指南未解释来源/可信度。纯文档。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
… Phase 2 ①)
Signal: 用户 GLM-5-turbo(Claude Code 经代理)显示总上下文 200K,且 Codex 核实 SDK 的
modelUsage.contextWindow 来自 SDK 内置目录、对第三方是通用默认值、无 SDK 设置可覆盖。
Triage: claude-client.ts extractTokenUsage 把 SDK modelUsage.contextWindow 无条件写入
token_usage.context_window;walk + fix#1 据此判可信 → 第三方代理(GLM)的 SDK 默认 200000
被当可信显示。Native 的 catalog 洗白已于 681706b 去掉;本提交补 SDK 路径。
Fix(Codex 统一口径"第一方 runtime 实报可信、第三方不可信"):
- ai-provider.ts 导出 isFirstPartyAnthropicEndpoint(baseUrl)(空/anthropic.com → 第一方)。
- extractTokenUsage 增 trustContextWindow,仅 true 时写 context_window;两个调用点都传
isFirstPartyAnthropicEndpoint(resolved.provider?.base_url)。第三方(自定义 base_url,如 GLM)
→ 不写 context_window → useContextUsage 回落 catalog 为不可信 → 只显示已用。
效果 + 边界: 第一方 Anthropic 继续显示百分比+已用;第三方代理新 turn 起只显示已用。
仅对新写入生效(历史消息已存的 context_window 不改写,遵守不改用户数据);现有 GLM 会话
仍显示旧值,需新会话/新 turn 验证(walk 会读历史,故旧会话需自然滚动出旧窗口或新建)。
Verify: typecheck;extract-token-usage-context-window.test.ts 增 2 pin(gate + 两调用点传
第一方判别);全量 3371/3371。
Guardrail: source-pin 钉死 context_window 写入受 trustContextWindow 门控 + 两调用点必须传
isFirstPartyAnthropicEndpoint,防回退到无条件信任第三方 SDK 窗口。
remaining(Phase 2 ①/③ 未完): provider/model 配置窗口作为最高优先可信源(用户覆盖) + 渲染层
对现有会话按第一方 gate(治旧会话) + #3 显示分母对齐压缩阈值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
计划文档状态审计修正(决策日志准、但概览层过期):
- frontmatter 状态行:📋 待接手 → 🚧 Phase 0/1 已完成、Phase 2 进行中。
- 「状态总览」表:Phase 1 待开始 → ✅ 已完成(2026-06-19);Phase 2 待开始 → 🚧 进行中。
- Phase 2 加进度 note:Composer/Context 主链路 #1#5 全部收口(含 commit + #3 真实
Codex 冒烟回复 circle);Session/Stream cluster #629/#635 + 终态原因码 + 压缩回滚
+ 诊断导出字段待续。
- Phase 2 执行清单 4 项已完成项 [ ]→[x](上下文 UI 语义 / context-cost 去阻断 /
Codex 多模态发送 / 发送后草稿清理)。
CLAUDE.md 执行计划段新增「完成即回写进度(与 Codex 对齐协作)」:任一 Phase/子项做完
必须立即回写三处且一致——执行清单勾选 / 状态总览表+frontmatter / 决策日志(commit
+验证结论);Claude 实施+回写、Codex 审查+维护;三者不一致视为状态失真须先对齐。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
打回上一条状态同步的一处失真:我把 #4/#5「发送后内容残留」标成完成(checklist [x] +
进度 note 列为 done),但同一文档决策日志(2026-06-20 条)已写明用户再次确认"内容已发出
但文本仍残留输入框"、#615 source-pin 不覆盖该症状、不能算闭环——状态表/清单与决策日志
自相矛盾,违反刚加的"三者必须一致"。
修正(与决策日志对齐):
- checklist「复现并修发送后内容残留」[x] → [ ],标注"待复核/待修复(用户 2026-06-20 再报)"。
- Phase 2 进度 note:拆分——#4/#5 仅失败保留有基础修复(#615),发送成功后文本残留待复核;
note 标题从"主链路已收口"改为"#1#3 收口、#4/#5 待复核";待续列表补回 #4/#5(重新打开)。
- #2 context-cost 非阻断保持完成(checklist [x] + note)不变。
后续修 #4/#5 时重点:PromptInput 受控/非受控清空边界、setInputValue('') 与
controller.textInput.clear() 是否同源、成功 accepted 后 remount/local draft 恢复、
badge/confirm/image 分支与普通 Enter 分支是否一致(决策日志已记排查方向)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
按"完成即回写进度"规则同步三处:
- checklist「复现并修发送后内容残留」[ ]→[x],标注已修 + CDP 验证 + 根因/修法(58c7aad)。
- Phase 2 进度 note:#1#5 全部落地;#4/#5 从"待复核"改为"已定位+修复"(含根因/CDP 结论);
待续列表移除 #4/#5、只留 Session/Stream cluster。
- 决策日志加同日条目:CDP 埋点定位 = 首条消息 accept 布局翻转 remount composer、inputValue
从 sessionStorage 草稿重读;修法 = accept 处清草稿;3401/3401 + CDP 文本/图文首条 800ms 即清。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
用户在浏览器实测不残留、仅桌面 App 残留 → Claude 协助完整重启 electron:dev(kill 整棵
进程树 + 释放 3000 + 后台重启)→ 用户在重启后真实 App 验证发送即清空 → #4/#5 闭环。
根因:58c7aad(page.tsx accept 处清首条草稿)一直是对的;用户残留是 Electron dev 没把
page.tsx 改动热更新进 renderer、窗口刷新无效,得整进程重启。这解释了全程「Claude CDP
浏览器清、用户残留」的矛盾——不是 Electron 行为差异,是构建新鲜度差异(Claude 浏览器硬刷
过有修复、用户 Electron 旧构建没有)。
回写:checklist [x](用户真实 App 验证)、进度 note #1#5 全闭环、验收去 ⚠️、决策日志加
闭环条目 + 教训(UI 修复在桌面 App 验证必须整重启 electron:dev)。Codex P1(prefill/
initialValue 回灌)仍是 58c7aad 的真实独立漏洞、值得单独补,与本次残留无关。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
纯文档同步,无代码改动。目的:让下一个进程打开文档时不从旧状态误判进度。
三处状态表此前已标 Phase 0/1 ✅、决策日志也已确认完成,唯独执行清单 checkbox
与 README 索引、issue-tracker #632 仍停在旧值——三处不一致即状态失真,本次对齐。
README.md:
- v0.56.x 索引行状态列 "📋 待 Phase 0 收束" → "🚧 Phase 0/1 ✅;Phase 2 进行中
(Composer/Context 主链路 #1#5 闭环,Session/Stream cluster #629/#635 待续)",
追上 plan frontmatter 与决策日志。
v0.56.x-stability-trust.md:
- Phase 0 执行清单 8 项 [ ]→[x],逐条带回溯(3360/3360、9c6e772、f99edbb/d00449f)。
A2 计时器项如实标注:按 keyed-remount 构造性消除 + 截图不可判别记录入 Smoke Ledger,
非逐帧视觉确认(反假数据,不谎称做了视觉确认)。
- Phase 1 执行清单 5 项 [ ]→[x],带回溯(milestone #1 / 9 labels / .github/TRIAGE.md)。
issue-tracker.md:
- #632 状态 "🔴 待修" → "🟡 假%已修,item3 分母对齐待续"。核心显示 bug(假百分比/>100%)
已由 effective-base-URL 写入 gate + 渲染期 trusted gate + clamp 修复并经真实 GLM
会话验证;item3(显示分母对齐压缩阈值)是独立待续阶段,故标部分修复而非已修复。
- 顶部"最后更新"同步到 2026-06-26 + #632 同步说明。
验证:git diff 确认仅 3 文档、16/16 行 checkbox 与状态文字,无代码/意外文件。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jul 4, 2026
- docs/research/ai-sdk-7-toolloop-parity-gaps.md: 新增「Phase 5 处置」节,全部 gap
收口——P1×3 关闭(#1/#2 补偿由 parity 8/8 复跑锁定;#3 降级论证:Phase 4 已证
approval HMAC 不需要 SDK toolApproval 停机语义,维持 in-execute 路线),
P2/P3 关闭或 backlog(#4/#5 列为替换路线前置条件,#7 归档 tech-debt #49#8 有 Phase 5 新实证)
- scripts/smoke-ai-sdk7-phase5-decision.ts: 新增决策门对照 smoke——prod runAgentLoop
与 POC runToolLoopAgentPoc 用同一 AgentLoopOptions 逐场景对照(长文本 / approval
批准 / approval 拒绝 / abort→continue),机械比较归一化事件序列 + 尾部契约 +
usage 存在性;DB 只读、数据目录隔离、输出全 scrub。探针注意:approval 批准分支
用 printf(echo 命中 permission-checker 自动放行规则不会触发 ask)
- docs/exec-plans/active/_smoke-evidence/ai-sdk7-phase5-decision-smoke.json:
OpenRouter 真实渠道 4/4 场景 contractMatch=true(input_tokens 逐场景完全相同,
tool_result 逐字相同,中断轮双侧 done 收尾、同 session 续发一次通过);
凭据形态 grep=0
- docs/research/ai-sdk-7-adoption-decision.md: 新增采用决策文档——结论 partial
(依赖升级 go / provider 能力 capability-gated go / Phase 4 外围能力 go /
@ai-sdk/mcp 与默认 loop 替换 no-go-现在),四层 rollback plan(能力开关→
wrapper→runtime switch→known-good version),每项结论标注 Phase 1-5 证据来源;
默认 Runtime 切换留人类闸门
- docs/exec-plans/tech-debt-tracker.md: 新增 #49(tool-error part 被两条 loop
一致吞掉的既有 UX 债,独立于采用决策)
- docs/exec-plans/active/ai-sdk-7-runtime-loop-adoption.md: Phase 5 状态回写 +
决策日志 + Smoke Ledger / Loop Ledger 各一行
- docs/research/README.md: 索引新增决策文档条目
验证: npm run test 3598/3598 全绿;smoke 4/4 contractMatch(1 个 fix cycle 收敛,
两处均为脚本层问题非 loop 差异);src/ 零改动(默认 Runtime/聊天路径零变化)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jul 4, 2026
用户批准 partial(2026-07-04, run issue #10): 采用 ai@7/@ai-sdk/* 依赖升级、
provider 参数能力 capability-gated、openai-chat image wrapper、timeout 原因码/
approval HMAC/trace 脱敏四件套(默认值经用户确认); @ai-sdk/mcp adapter 与
ToolLoopAgent 默认 loop 替换均不采用(留实验路径)。发版前保留官方一方 key
smoke gate。冲突仅 ai-sdk-7 计划决策日志一处,union 双方条目解决。
五个 phase 全部经 hands-off loop 完成并 Codex accepted(issues #1/#6/#7/#8/#10)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ion for Native Runtime
Two feature gaps where Native Runtime didn't match SDK Runtime, both
surfaced during post-hermes-upgrade manual testing:
── op7418#1: Compression notification now human-readable ──
Before: chat/route.ts:402 emitted `message: 'context_compressed'` as
a machine string. useSSEStream's notification branch showed this raw
string in the status bar — users saw "context_compressed" flash by.
After: message is now `"Context compressed: N older messages summarized,
~X tokens saved"` with structured `stats: { messagesCompressed, tokensSaved }`
for future rich UI handling. Added `subtype: 'context_compressed'` for
dedicated frontend handlers.
── op7418#3: AskUserQuestion tool for Native Runtime ──
Before: only SDK Runtime had AskUserQuestion (built into Claude Code CLI).
Native Runtime had no such tool, so the model could never ask structured
questions — the existing AskUserQuestionUI in PermissionPrompt.tsx was
unreachable dead UI code for Native Runtime users.
After:
- New builtin tool `src/lib/builtin-tools/ask-user-question.ts`
registered in index.ts, condition 'always'
- Zod schema: 1-6 questions, each with 1-6 options, optional multiSelect
- Execute receives answers from permission flow (injected by frontend)
and formats as Q/A pairs for the model
- permission-checker.ts: new ALWAYS_ASK_TOOLS set ensures AskUserQuestion
(and ExitPlanMode) always show UI even in trust mode — without this,
trust mode would auto-approve and return empty answers
- PermissionPrompt.tsx: NEVER_AUTO_APPROVE set prevents full_access mode
from auto-approving AskUserQuestion — the UI must render so the user
can answer
The data flow:
Model → AskUserQuestion({ questions }) → permission wrapper intercepts
→ SSE permission_request → frontend AskUserQuestionUI renders
→ user picks options → updatedInput({ questions, answers }) → tool
execute formats answers → model gets "Q: ... A: ..." string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ge generation results
GPT-Image-2.0 skill silent failure had two compounding causes both
on the 'tool result' loop:
P0 op7418#1 — function_call_output translated with sentinel toolName
translate-input.ts wrote toolName: '__from_responses_proxy__' for every
tool-result and the comment claimed 'ai-sdk doesn't use this for
routing'. That was wrong. Anthropic and OpenAI Responses both look
up the tool definition by tool-result.toolName when reconciling the
result with the request's tool surface; with a sentinel they can't
correlate and refuse to produce the continuation turn — exactly the
'tool ran, no follow-up text' the user saw.
Fix: walk the input array once first to build call_id → toolName
from function_call items, then look up the real name when translating
function_call_output. Orphan results (no matching function_call) fall
back to a named sentinel '__orphan_function_call_output__' AND emit
console.warn naming the call_id. The divergence stays loud.
P0 op7418#2 — imageGeneration / imageView silently dropped
event-mapper.ts had both item types in CHAT_ONLY_ITEM_TYPES, which
returns null on item/started + item/completed. That set is correct
for agentMessage/plan/reasoning (they have streaming delta channels
so the content arrives separately), but imageGeneration / imageView
have NO delta channel — their final item is the only surface where
the result reaches the user. Silent drop meant 'tool ran' with no
visible image.
Fix: move both types to TOOL_LIKE_ITEM_TYPES, add explicit
translateItemStarted branches with names image_generation /
image_view, and the existing TOOL_LIKE_ITEM_TYPES completion branch
already packs the full item into output — preserving result,
savedPath, revisedPrompt, path for chat-side rendering.
ThreadItemLike grew matching fields so TS doesn't downgrade access
to (item as { path?: string }).path casts.
Tests (8 new)
src/__tests__/unit/codex-proxy-translators.test.ts (+3):
- toolName resolves from matching function_call (gpt_image_2 case)
- toolName resolves correctly with interleaved out-of-order calls
- orphan function_call_output → named sentinel + console.warn
src/__tests__/unit/codex-event-mapper.test.ts (+4):
- imageGeneration item/started → tool_started(name='image_generation')
- imageGeneration item/completed → tool_completed with full
result + savedPath + revisedPrompt payload
- imageView item/started → tool_started(name='image_view') + path
- imageView item/completed → tool_completed with path preserved
src/__tests__/unit/codex-proxy-tool-contract.test.ts (+1):
- End-to-end continuation: function_call → function_call_output →
streamText(messages) — MockLanguageModelV3 must see toolName
'gpt_image_2' in its prompt, NOT '__from_responses_proxy__'.
Continuation text-delta event fires.
The mapper-side translate also removed the chatOnly array's
imageView / imageGeneration entries from the old 'returns null'
parameterised test; replaced with the new lifecycle describe block.
Closeout doc records round 7 ✅ items; remaining must-haves
unchanged (4-family smoke matrix + codex-sdk POC).
All 2416 tests pass (was 2412 + 8 new − 4 obsolete from the chatOnly
table for imageView/imageGeneration).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ce 2a
Direction approved; three sharpenings folded into the existing
Phase 2 plan structure without restructuring.
1. Widget wire-format single source (review revision op7418#1)
slice 7's WIDGET_SYSTEM_PROMPT template-literal-embeds
WIDGET_WIRE_FORMAT_SPEC. With artifactContracts ordered BEFORE
capabilityFragments in the compiler, the wire spec would land in
the final system prompt twice (once from artifactContract, once
from the capability fragment tail). The plan now declares hard
constraints — CANONICAL_SHOW_WIDGET_JSON, the "FINAL OUTPUT
FORMAT" title, and WIDGET_WIRE_FORMAT_SPEC each must appear
exactly once in the compiled system prompt — and assigns slice
2c a small refactor that strips the wire spec from
WIDGET_SYSTEM_PROMPT so artifactContract becomes the sole holder.
Compile-time sanity check (capability fragment text MUST NOT
contain artifactContract.canonicalJson) added as a defence-in-
depth FAIL path.
2. Expected Differences Ledger (review revision op7418#2)
2b's "compiler output === Runtime current prompt" stance
directly conflicted with slice 2d's plan to canonicalize Native
memory / notify / media-import paraphrases. Equivalence reading
strictly would have locked the old drift in. Plan now introduces
`src/lib/harness/expected-differences.ts` with typed entries
(runtimeId, capability, diff kind, justification,
plannedResolution, compilerSource, runtimeSource). 2b harness
reads "compiler vs runtime diff ⊆ ledger"; unregistered
differences fail. Initial ledger seeded with the four known
Phase 5c slice 7b tech-debt items, three earmarked for slice 2d
and one (image_generation MediaBlock shape) earmarked
follow_up. Slice 2d completion = manual ledger entry removal
(deliberate non-automation, preserves audit trail).
3. runtimeHints boundary (review revision op7418#3)
Plan tightens the runtimeHints type declaration so it cannot
become a fourth prompt-assembly point. Allowed: IDs (mcp server
names, tool keys, builtin tool name set), fragmentIds refs into
CompiledContext, adapter options (stopWhen / stepCount /
passthroughToolTypes). Forbidden: any prompt text string, tool
description paraphrase, capability redefinition. Three test
layers — type-level (string fields ≤ 64 chars, no newline / no
markdown), runtime-level (no template-literal-shaped values),
source-grep level (no multi-line template literals in
runtimeHints assignments) — plus a dangling-reference check
that every fragmentId in runtimeHints resolves in
CompiledContext.
Regression test list extended 9 → 12. Decision log records all
three revisions with rationale.
Plan still in 📋 status. No code; awaiting Codex re-review on the
revised draft, then slice 2a opens.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
User mode change: "internal slice order preserved, external single
delivery; stop only after Phase 2 is done; Codex review takes the
batch." This commit lands slices 2a–2e together with all post-
review hardenings (Widget wire-format single source, Expected
Differences Ledger, runtimeHints prose ban).
Internal slice walk
2a — context-compiler.ts (NEW)
Pure function `compileContext(input): CompiledContext`. No IO,
no provider calls. Resolves enabledCapabilities (null = catalog
live default), looks up exposure for the calling runtime, emits
capabilityFragments + artifactContracts + memory + workspace +
toolDescriptors + runtimeHints + budget + systemPromptText +
diagnostics. Hard contracts: artifactContract before capability
in the assembled prompt; fragmentId uniqueness; cross-runtime
fragment text identity; compile-time FAIL if a capability
fragment text contains an artifact contract canonicalJson
(wire-format dedup); compile-time FAIL if load-bearing fragments
exceed budget. runtimeHints types strictly ID/refs/adapter
options — no prose, no template literals.
2b — expected-differences.ts (NEW)
Drift ledger. Initial 4 entries from slice 7b tech-debt. Three
slice_2d entries consumed by this commit (see 2d below); the
one remaining `follow_up` is image_generation MediaBlock shape
(non-prompt, future slice).
2c — ClaudeCode SDK (claude-client.ts) source-pin only
The SDK path has always imported MCP canonicals directly
(memory-search-mcp, notification-mcp, media-import-mcp,
cli-tools-mcp, dashboard-mcp) — no paraphrase ever existed.
Slice 2c codifies this with a contract test: claude-client.ts
must not import capability prompts from builtin-tools/* and
must not declare its own _SYSTEM_PROMPT scalars.
2d — Native Runtime (builtin-tools/*) re-export MCP canonicals
`memory-search.ts` now `export const MEMORY_SEARCH_SYSTEM_PROMPT =
CANONICAL_MEMORY_SEARCH_SYSTEM_PROMPT` (imported from
memory-search-mcp.ts). Same pattern for `notification.ts`
(NOTIFICATION_SYSTEM_PROMPT = NOTIFICATION_MCP_SYSTEM_PROMPT)
and `media.ts` (MEDIA_SYSTEM_PROMPT = MEDIA_MCP_SYSTEM_PROMPT
from media-import-mcp.ts). Three ledger entries removed in
sync.
2e — Codex bridge (builtin-bridge.ts + unified-adapter.ts)
Bridge no longer holds WIDGET_PROMPT / MEDIA_PROMPT /
MEMORY_PROMPT / NOTIFY_PROMPT scalars (all four declarations
deleted). `createCodePilotBuiltinTools().systemPrompt` is
permanently `''`. `unified-adapter.ts` now calls
`compileContext({ runtimeId: 'codex_runtime', ... })` and feeds
`compiled.systemPromptText` to Codex's `instructions`. A new
helper `capabilitiesFromBridgeToolNames` maps the bridge's
mounted tool names back to capability ids so the compiler's
enabledCapabilities aligns with what the bridge actually
exposes (workspace-gated memory tools naturally drop out when
workspacePath is empty).
Slice 2c Widget wire-format single source (review revision op7418#1)
WIDGET_SYSTEM_PROMPT in widget-guidelines.ts no longer
template-literal-embeds `${WIDGET_WIRE_FORMAT_SPEC}`. The
artifactContract is now the sole holder of the wire-format spec
+ canonical JSON. Compiler's `detectWireFormatDuplication` sanity
check throws at compile time if any capability fragment text
contains the artifact contract canonicalJson — that's the forcing
function preventing the spec from being re-injected.
Three regression pins enforce single occurrence in the compiled
prompt: CANONICAL_SHOW_WIDGET_JSON × 1, "FINAL OUTPUT FORMAT —
non-negotiable" × 1, WIDGET_WIRE_FORMAT_SPEC × 1.
runtimeHints boundary (review revision op7418#3)
ClaudeCodeHints / NativeHints / CodexProxyHints types now carry
only IDs (mcp server names, tool keys, builtin tool name set) +
adapter options (stopWhen, stepCount, passthroughToolTypes).
Tests pin: type-level (no string field > 64 chars, no newline,
no Markdown markers), runtime-level (scan all string values for
prose), source-grep (CodexProxyHints type definition can't
contain `promptOverride` / `promptExtra` / `widgetPrompt` / etc).
Tests
New harness-context-compiler.test.ts (23 pins): catalog hygiene,
Widget wire-format single source (op7418#10), ordering, budget
enforcement, cross-runtime fragment identity (op7418#9), tool
descriptors, runtimeHints boundary (op7418#11), Expected Differences
Ledger consistency (op7418#12), JSON parseability of every artifact
contract.
New harness-context-compiler-equivalence.test.ts (9 pins):
compiler source reachability, runtime drift honesty,
ledger/slice ownership correctness, "post-slice-2d: Native
ledger holds only the follow_up MediaBlock entry".
Updated harness-capability-contract.test.ts: drift pins now
check (a) bridge holds no local _PROMPT scalars, (b) Native
builtin-tools re-export MCP canonicals, (c) unified-adapter
imports compileContext + consumes systemPromptText, (d)
claude-client.ts doesn't import from builtin-tools/* and
doesn't declare own _SYSTEM_PROMPT.
Updated codex-widget-format-contract.test.ts: the "WIDGET_SYSTEM_PROMPT
embeds WIDGET_WIRE_FORMAT_SPEC" and "appears inside
WIDGET_SYSTEM_PROMPT" pins are flipped — slice 2c REMOVED the
embed; the new pins verify the compiler-side import line.
Updated codex-builtin-bridge.test.ts: tests previously asserting
`bridge.systemPrompt` contained capability tags now assert it
equals `''` (bridge is no longer the prompt-assembly point).
Verification
CODEX_DISABLED=1 npx tsx --test \
src/__tests__/unit/harness-context-compiler.test.ts \
src/__tests__/unit/harness-context-compiler-equivalence.test.ts \
src/__tests__/unit/harness-capability-contract.test.ts \
src/__tests__/unit/codex-widget-format-contract.test.ts \
src/__tests__/unit/codex-builtin-bridge.test.ts
→ 74/74 pass
npm run test → 2576/2576 pass
Completion criteria check (per user spec)
[x] npm run test all green (2576/2576)
[x] Context Compiler unit tests all green
[x] equivalence / expected-diff harness all green
[x] harness-capability-contract / codex-widget-format /
codex-builtin-bridge tests all green
[x] no new runtime-local prompt duplicates (Native re-exports
canonical; ClaudeCode imports canonical; bridge holds none)
[x] Codex bridge no longer holds WIDGET_PROMPT / MEDIA_PROMPT /
MEMORY_PROMPT / NOTIFY_PROMPT scalars (all four removed,
drift test pins their absence)
[x] all three Runtimes adapt compiler output, none redefine
capability prompts
Docs
- phase-5d-phase-2-context-compiler.md: slice statuses 2a–2e all
✅ 2026-05-17; note the one-shot delivery mode change.
- phase-5d-harness-capability-contract.md: Phase 2 row ✅, awaiting
Codex review.
- handover/harness-capability-contract.md: new "Context Compiler"
section detailing inputs/outputs/constraints, three-runtime
consumption pattern, Expected Differences Ledger contract.
- refactor-closeout.md: new decision-log entry recording the
Phase 2 delivery shape + completion criteria check.
Phase 5d Phase 2 ✅ pending Codex review. Phase 3 (Runtime
Capability Adapter) / Phase 4 (Artifact Contract) / Phase 5
(new-Runtime Playbook) intentionally NOT opened — stopping per
user instruction.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
… to breakdown
## 用户视角
升级前:popover 的"文件与附件 / 本次待加入"两行永远 0 —— 数据通道没接通。即使 composer 里挂了 4 个 mention 和 2 个目录引用,popover breakdown 显示 0。
升级后:MessageInput → ChatView/page → RunCockpit → useContextUsage → buildContextUsageBreakdown 全链路联通。composer 里的 attachment / mention / directory 实时累加到对应类别。trigger 上的迷你点阵 + popover 主条 + 列表行三处同步更新。
发送消息后 pending 归 0;下一轮 history 里的真实 token_usage 接管 used 部分;conversation 类自动吸收。
## 不做什么
- 不改 hook 其他字段(used / ratio / state / source 等不动)
- 不改 trigger 主结构(百分比文字仍在;只有点阵 cells 在分配时反映 pending)
- 不改 composer text 估算(composerTextTokens 仍 0;那是 Phase 3+ 的事)
## 怎么验收
- npm run test → 2921/2921 pass
- composer 里加附件 / @mention / "+" 目录 → trigger 上 pending 部分立刻有虚线 cells
- 发送消息 → pending 归零;下轮 used cells 更新
## 改动(6 文件)
### src/lib/message-input-logic.ts
新增 `PendingContextSubTotals` interface + `computePendingContextSubTotals()` 函数。逻辑 mirror `computePendingContextTokens`(同样的 null 过滤、同样的迭代顺序),但返回 { attachment, mention, directory } 三键。两个函数加起来 = 等于 computePendingContextTokens 总数。
### src/hooks/useContextUsage.ts
options 加可选 `pending?: { attachmentTokens?, mentionTokens?, directoryTokens?, composerTextTokens? }`。三条返回路径(snapshot / walk / noData)都把 options?.pending 转发给 buildContextUsageBreakdown。useMemo deps 数组加 options?.pending。
### src/components/chat/RunCockpit.tsx
RunCockpitProps 加可选 `pendingContextSubTotals?: { attachment, mention, directory }`。组件内部把它转换成 hook options.pending 形态(attachment → attachmentTokens 等)。可选 prop 默认 undefined → 不破坏现有 callsites。
### src/components/chat/MessageInput.tsx
- import 加 computePendingContextSubTotals + PendingContextSubTotals type
- props 加可选 `onPendingContextSubTotalsChange?` callback(跟现有 onPendingContextTokensChange 并列)
- 新增 useMemo 算 pendingContextSubTotals + useEffect emit callback
- 与现有 pendingContextTokens 走同一份 source 数据,逻辑同步无 divergence
### src/components/chat/ChatView.tsx
- 加 state `pendingContextSubTotals` (PendingContextSubTotals | undefined)
- MessageInput 上 wire `onPendingContextSubTotalsChange={setPendingContextSubTotals}`
- RunCockpit 上传 `pendingContextSubTotals={pendingContextSubTotals}`
### src/app/chat/page.tsx
- 跟 ChatView 完全镜像:state + MessageInput callback + RunCockpit prop
- 两个入口独立持有 state(按 StreamSession guardrail 不变量 op7418#1)
## Scope discipline
- 不新增测试(Codex 负责测试覆盖;用户分工已明确)
- 不动 buildContextUsageBreakdown / computePendingContextTokens 既有签名 → 旧调用 zero-risk
- 不改 chat-static-graph 排除清单 → MessageInput / RunCockpit 改动属于增量 prop,没新依赖链
- composerTextTokens 仍未 wire(composer 纯文本估算属于未来扩展,pending_next_turn 行暂时仍 0)
## StreamSession guardrail 合规
- 双入口(page.tsx 首消息 + ChatView 后续)独立 state — 不变量 op7418#1 ✅
- onSend / onCommand 签名不变 — rewind point 不变量 op7418#2 ✅
- 不动 capability cache — 不变量 op7418#3 ✅
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…18#31)
Codex review second round caught two real P1 inconsistencies introduced by
the Dashboard/CLI split slice plus non-blocking contract drift.
P1.1 — Dashboard injection gate ≠ route auth gate.
runtime.ts injected the dashboard read/write MCPs whenever prompt + working
directory + dashboard keyword matched, but the route's `authorize` requires
`sameRealPath(workspacePath, assistant_workspace_path)`. Mismatch → the model
sees the tool and Codex 403s at call time. Fix: dashboard injection mirrors
memory's gate exactly (same sameRealPath check, same `assistantWorkspacePath`
passed as `workspacePath`) so "inject" and "route-authorize" never disagree.
CLI tools don't need this (no workspace scope).
P1.2 — Matrix promoted only for codex_account; runtime injects for ALL
codex_runtime providers.
The runtime didn't gate injection by provider, so under a CodePilot proxy
provider the dashboard/cli MCPs WERE injected (callable), but the matrix
returned `perception_only` for non-codex_account — the opposite drift from
P1.1 ("model says yes, Settings says no"). Fix per Codex's preferred option:
move the promotion into `capabilityMatrixForRuntime` so it applies to ALL
codex_runtime providers; `capabilityMatrixForRuntimeProvider` now only adds
codex_account-specific overrides (native notes + image/media demotion).
`buildCapabilityMatrix` delegates to `capabilityMatrixForRuntime` so every
matrix entry point stays aligned.
Non-blocking op7418#1 — contract text drift.
capability-contract.ts dashboard/cli `deferredReason` + `codex_proxy.notes`
rewritten — explicit that the LEGACY provider-proxy bridge is unsupported
(true), and that the codex_runtime path now ships via the mutation-level MCP
split + matrix-layer promotion. No schema changes (`kind: 'unsupported'`
stays accurate for the legacy bridge surface); the existing matrix invariant
test gets a `MATRIX_LAYER_PROMOTIONS` exception list documenting why the two
promoted cells are allowed to be executable despite `kind: 'unsupported'`.
Schema cleanup (introduce a new `mcp_server_split` kind, drop the exception
list) tracked as tech-debt op7418#33.
Non-blocking op7418#2 — elicitation policy pins.
codex-mcp-events.test.ts now pins all 4 new server names:
codepilot_{dashboard,cli_tools}_read → auto_accept,
codepilot_{dashboard,cli_tools}_write → user_approval.
Also added a regression guard: `codex_runtime + non-codex_account provider`
must STILL show dashboard/cli_tools executable with mixed trust + the right
noteKey. Updated the two pre-existing tests that asserted the OLD behaviour
(dashboard/cli perception_only on codex_runtime) — they now assert the
promoted state. Also synced the static `CAPABILITY_EXECUTABLE_RUNTIMES` map.
Per Codex review's explicit ask: the "待真账号 smoke" wording stays in the
op7418#31 capability table — this commit fixes the inconsistencies, but the
real-account end-to-end smoke for natural-conversation triggering + write
approval card + Deny blocking is still owed by the user.
Full unit suite 3045/3045. Live route: bad workspace still 403 (auth gate
intact); tools/list subsets unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Codex review 认可方向,按 5 条反馈修订(纯文档,无代码):
- Phase A 增"开工前核验"(Opus 4.8 官方 model id / context window / thinking·effort / 1M beta,不臆测)
- Phase A 实现范围增"泛化 Opus 4.7 专属逻辑"(isOpus47Model / OPUS_4_7_PATTERN / applyContext1mBeta /
effort 门控 / claude-client sanitizer,配回归测试)—— catalog 显示 ≠ 请求正确
- OpenRouter Opus 4.8 改 deferred(不臆测 slug),首轮只接 Anthropic direct
- opus 别名 / 默认先不动(仍 4.7),只新增显式 claude-opus-4-8,切换待 smoke 后用户拍板
- Phase D 拆 D0/D:D0 把 apply-discovery-diff 全量 flake + no-verify 事件记入 tech-debt op7418#30(本提交即 D0);
D 建议先于 A/B/C,代码 phase 不再靠 --no-verify
- Open Questions op7418#1/op7418#2 据上述决议收敛
本提交纯文档;pre-commit 同样因 apply-discovery-diff 全量 flake 用 --no-verify,已确认 docs-drift 绿。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
v0.56.x 计划 Phase 1:建立稳定性治理入口,并用当前源码重新核验 Notion/issue 列出的
7 个 issue(不采信 issue 自述根因)。
GitHub 侧(已在仓库生效,非本 commit 内容):
- 创建 milestone op7418#1「v0.56.x Stability / Trust」。
- 创建 9 个治理 label:P0-crash-or-interrupt / P0-data-loss-risk / P1-runtime-session /
P1-context / P1-file-reference / P1-installer-update / P1-performance / needs-repro /
v0.57+ parking-lot。
- 给 op7418#626/op7418#628/op7418#629/op7418#632/op7418#633/op7418#634/op7418#635 按复核结论打 milestone + 优先级 label。
本 commit 文件:
- .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml:bug 表单强制必填
版本/OS/runtime/provider-model/可复现/复现步骤/期望vs实际 + 影响面勾选;feature
表单注明 v0.56.x 冻结新功能 → v0.57+ parking-lot;config 关闭空白 issue + 冻结说明
与 Discussions 入口。
- .github/PULL_REQUEST_TEMPLATE.md:Summary / Repro+root cause / Changes / Tests /
Screenshots-logs / 自查清单(链到 CLAUDE.md 与 AGENTS.md,不复制维护)。
- .github/TRIAGE.md:对外冻结说明、label 体系、issue/PR triage 规则、自动化候选。
- v0.56.x-stability-trust.md:标 Phase 0 完成 + 新增「2026-06-19 Claude Code 源码复核」
表(7 issue 逐条 file:line 证据)。关键复核结论:
* op7418#632 ">100%" 确认是未 clamp 的 ratio*100 显示 bug(RunCockpit.tsx:169 等),分母
contextWindow 不可靠;"跨会话串" 源码不成立。
* op7418#629 空 assistant 已防护,残留真实 gap:is_error result 路径不清坏 sdk_session_id
(claude-client.ts:1908 先置 resultEmitted)。
* op7418#635 截图-only,最强候选 = SDK runtime 无自生成 keepalive(claude-client.ts:1956),
慢 proxy 静默 >330s 被 idle abort(B-019)。
* op7418#628 确认真实风险:@file origin path 在 MessageInput.tsx:161 丢失,body.mentions[]
送达但 route.ts 从不消费 → 写 .codepilot-uploads 副本,AI 改副本。
* op7418#634 根因不成立——5 个 notify/schedule 工具均注册(builtin-tools/index.ts:250),
issue 引用的 UI 串不在当前源码(疑旧版);附带 Plan 模式 list_tasks 泄漏。
* op7418#626 polling 排除(8h 间隔),候选 animate-pulse × backdrop-filter 重绘。
* op7418#633 mac 无法复现;NSIS-only + 未签名 + 无 portable + CI 不验安装启动。
- issue-tracker.md:新增「v0.56.x 治理 issue」看板索引表(指向 plan 复核表,不重复分析)。
验证:docs-drift 通过;npm run test(hook)。Phase 1 验收(milestone/labels/模板/冻结
说明就绪)达成。下一步 Phase 2:按复核结论修 chat 主链路(上下文百分比语义、context-cost
不阻断发送、Codex 多模态发送、发送后清草稿)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…e 2 op7418#1)
Signal: issue op7418#632 报"上下文 >100% / 假百分比 / 压缩后跳变";Phase 1 源码复核确认是
真实显示 bug("跨会话串"不成立)。
Triage(当前源码): 用量百分比 = usage.ratio*100,在 RunCockpit.tsx 与
RunCockpitPopoverContent.tsx 两处直接渲染、未封顶;usage.ratio = used / contextWindow,
而 contextWindow 来自 sdkContextWindow ?? latestSdkContextWindow ?? catalogContextWindow
(useContextUsage.ts)。很多第三方 proxy 不上报 context_window → 落到静态 catalog 兜底
(一个猜测值),used 又会在压缩后跳变 → 百分比蹦到 200%/500%。根因是"拿不可信的分母
算百分比",不是上下文真的超了。
Fix:
- useContextUsage.ts: 新增 ContextUsageData.contextWindowTrusted —— 仅当 SDK/上游真实
上报窗口时为 true(catalog 兜底不算)。三个 return 分支(baseline / snapshot / no-baseline)
都按各自来源正确赋值。不可信时不把窗口喂给 buildContextUsageBreakdown,dot-matrix 退回
按已用 token 的构成比例,不编造容量。
- RunCockpit.tsx: hasFullCtx 增加 && usage.contextWindowTrusted —— 不可信时自动落到既有的
绝对已用 token 显示(触发按钮)/ showUnknownCapacityBlock 分支(浮层,已测试的"容量未知"
路径)。百分比文案 clamp ≤100%。
- RunCockpitPopoverContent.tsx: 浮层 header 百分比同样 clamp ≤100%(防可信窗口被 used 短暂
超过时仍蹦 >100%)。
语义验收: 输入框右下角不可信时只显示已用绝对值;浮层不可信时只显示已用 + 不同种类构成
比例(无百分比/remaining/unused/假总量);可信时百分比封顶 100%。
Verify: typecheck 通过;context-window-trusted.test.ts 6 条 source-pin + 既有
run-cockpit-unknown-capacity / context-dot-matrix / context-usage-walk / context-breakdown
全绿;全量单测 3366/3366。未做:真实 untrusted-window provider 会话的 CDP 视觉走查
(fix 把 untrusted 路由到既有已发布的"容量未知"分支,风险低;视觉走查列为后续)。
Guardrail: context-window-trusted.test.ts 钉死 trusted 派生只认 SDK 来源、不可信时不喂窗口、
hasFullCtx 必须 gate trusted、两处显示 clamp ≤100%,防回退到"拿 catalog 当真实分母算百分比"。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Signal: Codex 复核 fixop7418#1(9ea29a4)后发现 P2 残留——文字已改成"只显示已用 token",
但输入框右下角触发按钮旁的 mini dot-bar 仍用 200K 兜底画出"用了多少/还剩多少"的容量
暗示,与"拿不到总长度就不显示容量"及 commit message 的"不编造容量"不一致。
Triage(当前源码): ContextDotMatrix.tsx 有 FALLBACK_CONTEXT_WINDOW=200_000,
minCellsPerKind=0(mini-bar)在窗口未知时用它当分母(:88);RunCockpit.tsx:200 的触发
按钮无条件渲染这个 mini-bar。所以即使 9ea29a4 把文字降级为绝对已用,小条仍画假容量。
minCellsPerKind=0 全仓只有 RunCockpit 触发按钮一个调用方。
Fix:
- RunCockpit.tsx: mini-bar 用 {hasFullCtx && (...)} 包裹——仅在可信窗口下渲染容量小条;
不可信时触发按钮只剩绝对已用 token 文本(贴合"输入框右下角只显示已用数值")。
- ContextDotMatrix.tsx: 删除 FALLBACK_CONTEXT_WINDOW(200K)。窗口未知时两种模式都按
used+pending 分配(构成视图,非容量%),不再编造容量。
Verify: typecheck 通过;context-dot-matrix.test.ts 旧的"unknown mini-bar 用 200K 兜底
(filled<=2)"语义改为新的"used 构成(filled>=8)";context-window-trusted.test.ts 加 2 条
guardrail(mini-bar gate 在 hasFullCtx + 源码无 200K 兜底残留);全量单测 3368/3368。
Guardrail: 两条 source-pin 钉死"触发按钮 mini-bar 必须 gate 在 hasFullCtx"且"ContextDotMatrix
不得再出现 FALLBACK_CONTEXT_WINDOW/200_000",防回退到拿假容量画小条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户复核 fixop7418#1 后明确显示格式:输入框右下角的上下文小标,在有可信窗口时显示
"百分比 + 已用上下文"(如 56.6% 452K),没有可信窗口时只显示已用(如 452K),
不单列"剩余"数字。
改动:RunCockpit.tsx 触发按钮 ratioText 的可信分支由 "{pct}%" 改为
"{pct}% {used}"(1 位小数,匹配用户给的 56.6% 示例);不可信/无数据分支不变。
context-window-trusted.test.ts 的 clamp pin 扩为同时断言"百分比 + 已用"格式。
验证:dev 应用热重载干净(✓ Compiled);context-window-trusted 8/8;typecheck(hook)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…llow-up)
Signal: 用户在运行的应用里看到 GLM-5-turbo(Claude Code/Native 会话)仍显示总上下文
200K,指出"这并不是我们知道的部分"。fixop7418#1 本应让 catalog 静态值不可信、只显示已用。
Triage(当前源码,用户 review 驱动): agent-loop.ts:641-651(Native)在 token_usage
没有 context_window 时,从静态 catalog 填 totalUsage.context_window = getContextWindow(modelId)
(GLM-5-turbo 在 catalog 是 z.ai 核实的 202752)。而 context-usage-walk 把
token_usage.context_window 当作 SDK 实报窗口读,fixop7418#1 的 contextWindowTrusted 据此判可信
→ catalog 猜测被"洗白"成可信 → Native GLM 显示 200K。即上游 mutator 打败了 helper 修复
(feedback_fix_all_consumers)。claude-client(Claude Code)只从 SDK modelUsage 写,不洗白;
ContextUsageIndicator 是死组件(无人 import)。
Fix: 删掉 agent-loop 的 catalog 洗白。Native 无 runtime 实报时 context_window 留空 →
useContextUsage 回落 catalog 为不可信 → 只显示已用绝对值,不再有假百分比/假总量。
仅对新 turn 生效(历史消息已存的 context_window 不改写,遵守不改用户数据;旧会话发新消息后转为已用-only)。
Verify: typecheck;context-window-trusted.test.ts 新增 pin 断言 agent-loop 不再
`.context_window = catalogWindow`;该文件 9 测 + agent-loop-error-event 全过。运行中 dev 应用
server 重编译干净(Native GLM 需发新消息验证)。
Guardrail: source-pin 防 Native 再把 catalog 洗进 SDK-authoritative 字段。
设计记录(用户批准"先记计划再实现"): v0.56.x 计划写入 context-window 来源优先级修订设计
(runtime 实报 > provider 配置 contextWindow > 压缩阈值 > catalog 不可信)+ 跨 Runtime 用户
配置源(op7418#1,待实现) + 显示分母对齐压缩阈值(op7418#3,待实现)。本提交是设计第一步(去洗白)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
把"为什么 GLM 显示 200K + 窗口来源该怎么改"写成评审稿放进 v0.56.x Phase 2,按
外部事实 / 本地证据(file:line) / 推断与设计三层分写,供 Codex 核实。
要点:
- Agent SDK v0.2.111 的 modelUsage.contextWindow(sdk.d.ts:945)是未文档化字段,来自
SDK 内置模型目录而非 API;第一方可靠、第三方(经 base_url 的 GLM)返回通用默认值;
无 SDK 设置可覆盖;Anthropic 建议自维护窗口表。
- 实测 GLM 会话 token_usage.context_window=200000 ≠ 本地 catalog 202752,证实来自 SDK
默认而非 catalog/Native 洗白;该会话是 Claude Code(故上一提交的 Native 修复不覆盖它)。
- 修订设计:窗口来源优先级 = 用户覆盖 > 已核实 catalog/provider 配置 > SDK(仅第一方) >
只显示已用;第三方忽略 SDK 默认值;跨 Runtime;显示分母对齐压缩阈值(op7418#3)。
- 列出待定决策(已核实优先 vs 纯手动) + 给 Codex 的 5 个核实点。
未改任何产品代码(纯文档)。op7418#1/op7418#3 实现待 Codex 核实后进行。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Codex 复核设计稿后订正(实现 op7418#1/op7418#3 前必须):
- A:原"官方文档不记载 contextWindow/maxOutputTokens"不准 → 改为 SDK TypeScript
reference 有字段定义,是 cost-tracking 指南未解释来源/可信度。
- B/C:原"catalog 202752 比 SDK 200000 更准且 z.ai 核实"站不住 → z.ai 官方写
200K/128K,catalog 该条来源存疑;结论收敛为"SDK 200000 不可作为 provider 实报采信",
不延伸到"catalog 更准";另标记需单独核 model-context.ts:42 的真实来源。
- D + 决策日志:统一优先级(消除冲突,旧决策日志把第三方 SDK 又洗白成可信)→
用户手动覆盖 > provider/model 配置且来源已验证 > 第一方 runtime 实报 > 只显示已用;
第三方 SDK contextWindow 默认不可信、无明确来源 catalog 不当可信%显示。
- "Anthropic 官方建议自维护表"未核到原文 → 降级为工程结论。
- 澄清:用户实际看到 200K 的 GLM 会话是 Claude Code(SDK 默认 200000),非 Native 洗白
路径(f79fd54 的 Native 修复有效但治另一条路径)。
- E:决策收敛为一条基线 + 剩余一项请用户定(第一方 SDK 实报是否自动显示百分比)。
Codex 核为真的部分(sdk.d.ts:945 字段、代码写入 token_usage、历史 SDK 窗口被当可信、
Native 洗白已去、显示分母 vs 压缩阈值脱节)保留。纯文档,未动产品代码。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
F 段核实点 op7418#1 还残留旧"官方文档未记载(A)",与已订正的 A 段不一致。改为:
sdk.d.ts:945 的 contextWindow/maxOutputTokens 存在,SDK TypeScript reference 已列,
只是 cost-tracking 指南未解释来源/可信度。纯文档。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…#632 / Phase 2 ①)
Signal: 用户 GLM-5-turbo(Claude Code 经代理)显示总上下文 200K,且 Codex 核实 SDK 的
modelUsage.contextWindow 来自 SDK 内置目录、对第三方是通用默认值、无 SDK 设置可覆盖。
Triage: claude-client.ts extractTokenUsage 把 SDK modelUsage.contextWindow 无条件写入
token_usage.context_window;walk + fixop7418#1 据此判可信 → 第三方代理(GLM)的 SDK 默认 200000
被当可信显示。Native 的 catalog 洗白已于 f79fd54 去掉;本提交补 SDK 路径。
Fix(Codex 统一口径"第一方 runtime 实报可信、第三方不可信"):
- ai-provider.ts 导出 isFirstPartyAnthropicEndpoint(baseUrl)(空/anthropic.com → 第一方)。
- extractTokenUsage 增 trustContextWindow,仅 true 时写 context_window;两个调用点都传
isFirstPartyAnthropicEndpoint(resolved.provider?.base_url)。第三方(自定义 base_url,如 GLM)
→ 不写 context_window → useContextUsage 回落 catalog 为不可信 → 只显示已用。
效果 + 边界: 第一方 Anthropic 继续显示百分比+已用;第三方代理新 turn 起只显示已用。
仅对新写入生效(历史消息已存的 context_window 不改写,遵守不改用户数据);现有 GLM 会话
仍显示旧值,需新会话/新 turn 验证(walk 会读历史,故旧会话需自然滚动出旧窗口或新建)。
Verify: typecheck;extract-token-usage-context-window.test.ts 增 2 pin(gate + 两调用点传
第一方判别);全量 3371/3371。
Guardrail: source-pin 钉死 context_window 写入受 trustContextWindow 门控 + 两调用点必须传
isFirstPartyAnthropicEndpoint,防回退到无条件信任第三方 SDK 窗口。
remaining(Phase 2 ①/③ 未完): provider/model 配置窗口作为最高优先可信源(用户覆盖) + 渲染层
对现有会话按第一方 gate(治旧会话) + op7418#3 显示分母对齐压缩阈值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
计划文档状态审计修正(决策日志准、但概览层过期):
- frontmatter 状态行:📋 待接手 → 🚧 Phase 0/1 已完成、Phase 2 进行中。
- 「状态总览」表:Phase 1 待开始 → ✅ 已完成(2026-06-19);Phase 2 待开始 → 🚧 进行中。
- Phase 2 加进度 note:Composer/Context 主链路 op7418#1op7418#5 全部收口(含 commit + op7418#3 真实
Codex 冒烟回复 circle);Session/Stream cluster op7418#629/op7418#635 + 终态原因码 + 压缩回滚
+ 诊断导出字段待续。
- Phase 2 执行清单 4 项已完成项 [ ]→[x](上下文 UI 语义 / context-cost 去阻断 /
Codex 多模态发送 / 发送后草稿清理)。
CLAUDE.md 执行计划段新增「完成即回写进度(与 Codex 对齐协作)」:任一 Phase/子项做完
必须立即回写三处且一致——执行清单勾选 / 状态总览表+frontmatter / 决策日志(commit
+验证结论);Claude 实施+回写、Codex 审查+维护;三者不一致视为状态失真须先对齐。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
打回上一条状态同步的一处失真:我把 op7418#4/op7418#5「发送后内容残留」标成完成(checklist [x] +
进度 note 列为 done),但同一文档决策日志(2026-06-20 条)已写明用户再次确认"内容已发出
但文本仍残留输入框"、op7418#615 source-pin 不覆盖该症状、不能算闭环——状态表/清单与决策日志
自相矛盾,违反刚加的"三者必须一致"。
修正(与决策日志对齐):
- checklist「复现并修发送后内容残留」[x] → [ ],标注"待复核/待修复(用户 2026-06-20 再报)"。
- Phase 2 进度 note:拆分——op7418#4/op7418#5 仅失败保留有基础修复(op7418#615),发送成功后文本残留待复核;
note 标题从"主链路已收口"改为"op7418#1op7418#3 收口、op7418#4/op7418#5 待复核";待续列表补回 op7418#4/op7418#5(重新打开)。
- op7418#2 context-cost 非阻断保持完成(checklist [x] + note)不变。
后续修 op7418#4/op7418#5 时重点:PromptInput 受控/非受控清空边界、setInputValue('') 与
controller.textInput.clear() 是否同源、成功 accepted 后 remount/local draft 恢复、
badge/confirm/image 分支与普通 Enter 分支是否一致(决策日志已记排查方向)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
按"完成即回写进度"规则同步三处:
- checklist「复现并修发送后内容残留」[ ]→[x],标注已修 + CDP 验证 + 根因/修法(de123df)。
- Phase 2 进度 note:op7418#1op7418#5 全部落地;op7418#4/op7418#5 从"待复核"改为"已定位+修复"(含根因/CDP 结论);
待续列表移除 op7418#4/op7418#5、只留 Session/Stream cluster。
- 决策日志加同日条目:CDP 埋点定位 = 首条消息 accept 布局翻转 remount composer、inputValue
从 sessionStorage 草稿重读;修法 = accept 处清草稿;3401/3401 + CDP 文本/图文首条 800ms 即清。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户在浏览器实测不残留、仅桌面 App 残留 → Claude 协助完整重启 electron:dev(kill 整棵
进程树 + 释放 3000 + 后台重启)→ 用户在重启后真实 App 验证发送即清空 → op7418#4/op7418#5 闭环。
根因:de123df(page.tsx accept 处清首条草稿)一直是对的;用户残留是 Electron dev 没把
page.tsx 改动热更新进 renderer、窗口刷新无效,得整进程重启。这解释了全程「Claude CDP
浏览器清、用户残留」的矛盾——不是 Electron 行为差异,是构建新鲜度差异(Claude 浏览器硬刷
过有修复、用户 Electron 旧构建没有)。
回写:checklist [x](用户真实 App 验证)、进度 note op7418#1op7418#5 全闭环、验收去 ⚠️、决策日志加
闭环条目 + 教训(UI 修复在桌面 App 验证必须整重启 electron:dev)。Codex P1(prefill/
initialValue 回灌)仍是 de123df 的真实独立漏洞、值得单独补,与本次残留无关。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
纯文档同步,无代码改动。目的:让下一个进程打开文档时不从旧状态误判进度。
三处状态表此前已标 Phase 0/1 ✅、决策日志也已确认完成,唯独执行清单 checkbox
与 README 索引、issue-tracker op7418#632 仍停在旧值——三处不一致即状态失真,本次对齐。
README.md:
- v0.56.x 索引行状态列 "📋 待 Phase 0 收束" → "🚧 Phase 0/1 ✅;Phase 2 进行中
(Composer/Context 主链路 op7418#1op7418#5 闭环,Session/Stream cluster op7418#629/op7418#635 待续)",
追上 plan frontmatter 与决策日志。
v0.56.x-stability-trust.md:
- Phase 0 执行清单 8 项 [ ]→[x],逐条带回溯(3360/3360、dd4ead4、b853188/2de9c2b)。
A2 计时器项如实标注:按 keyed-remount 构造性消除 + 截图不可判别记录入 Smoke Ledger,
非逐帧视觉确认(反假数据,不谎称做了视觉确认)。
- Phase 1 执行清单 5 项 [ ]→[x],带回溯(milestone op7418#1 / 9 labels / .github/TRIAGE.md)。
issue-tracker.md:
- op7418#632 状态 "🔴 待修" → "🟡 假%已修,item3 分母对齐待续"。核心显示 bug(假百分比/>100%)
已由 effective-base-URL 写入 gate + 渲染期 trusted gate + clamp 修复并经真实 GLM
会话验证;item3(显示分母对齐压缩阈值)是独立待续阶段,故标部分修复而非已修复。
- 顶部"最后更新"同步到 2026-06-26 + op7418#632 同步说明。
验证:git diff 确认仅 3 文档、16/16 行 checkbox 与状态文字,无代码/意外文件。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
- docs/research/ai-sdk-7-toolloop-parity-gaps.md: 新增「Phase 5 处置」节,全部 gap
收口——P1×3 关闭(op7418#1/op7418#2 补偿由 parity 8/8 复跑锁定;op7418#3 降级论证:Phase 4 已证
approval HMAC 不需要 SDK toolApproval 停机语义,维持 in-execute 路线),
P2/P3 关闭或 backlog(op7418#4/op7418#5 列为替换路线前置条件,op7418#7 归档 tech-debt op7418#49op7418#8 有 Phase 5 新实证)
- scripts/smoke-ai-sdk7-phase5-decision.ts: 新增决策门对照 smoke——prod runAgentLoop
与 POC runToolLoopAgentPoc 用同一 AgentLoopOptions 逐场景对照(长文本 / approval
批准 / approval 拒绝 / abort→continue),机械比较归一化事件序列 + 尾部契约 +
usage 存在性;DB 只读、数据目录隔离、输出全 scrub。探针注意:approval 批准分支
用 printf(echo 命中 permission-checker 自动放行规则不会触发 ask)
- docs/exec-plans/active/_smoke-evidence/ai-sdk7-phase5-decision-smoke.json:
OpenRouter 真实渠道 4/4 场景 contractMatch=true(input_tokens 逐场景完全相同,
tool_result 逐字相同,中断轮双侧 done 收尾、同 session 续发一次通过);
凭据形态 grep=0
- docs/research/ai-sdk-7-adoption-decision.md: 新增采用决策文档——结论 partial
(依赖升级 go / provider 能力 capability-gated go / Phase 4 外围能力 go /
@ai-sdk/mcp 与默认 loop 替换 no-go-现在),四层 rollback plan(能力开关→
wrapper→runtime switch→known-good version),每项结论标注 Phase 1-5 证据来源;
默认 Runtime 切换留人类闸门
- docs/exec-plans/tech-debt-tracker.md: 新增 op7418#49(tool-error part 被两条 loop
一致吞掉的既有 UX 债,独立于采用决策)
- docs/exec-plans/active/ai-sdk-7-runtime-loop-adoption.md: Phase 5 状态回写 +
决策日志 + Smoke Ledger / Loop Ledger 各一行
- docs/research/README.md: 索引新增决策文档条目
验证: npm run test 3598/3598 全绿;smoke 4/4 contractMatch(1 个 fix cycle 收敛,
两处均为脚本层问题非 loop 差异);src/ 零改动(默认 Runtime/聊天路径零变化)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户批准 partial(2026-07-04, run issue op7418#10): 采用 ai@7/@ai-sdk/* 依赖升级、
provider 参数能力 capability-gated、openai-chat image wrapper、timeout 原因码/
approval HMAC/trace 脱敏四件套(默认值经用户确认); @ai-sdk/mcp adapter 与
ToolLoopAgent 默认 loop 替换均不采用(留实验路径)。发版前保留官方一方 key
smoke gate。冲突仅 ai-sdk-7 计划决策日志一处,union 双方条目解决。
五个 phase 全部经 hands-off loop 完成并 Codex accepted(issues op7418#1/op7418#6/op7418#7/op7418#8/op7418#10)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
canblmz1 pushed a commit to canblmz1/CodePilot that referenced this pull request Aug 28, 2026
…lease
prefix-safe-json 0.2.0 -> 0.4.3 (exact). 0.4.3 is a security patch
(GHSA-3xpw-9694-2xxp) fixing three root causes in the AI SDK adapter/gate
this integration depends on:
1. AiSdkStreamAdapter.push() used to silently drop every raw event once
it had already observed its own terminal, so late/contradictory
evidence for a call never reached the coordinator at all.
2. takeDecision() used to read a decision snapshot frozen at finish()
time instead of the coordinator's live diagnostics, so evidence
recorded after finish() but before that call's authority was consumed
was never consulted.
3. A raw event carrying conflicting id/toolCallId used to silently
prefer id instead of failing the stream closed.
No public API change - createAiSdkExecutionGuard()/push()/finish()/
takeDecision() and the ExecuteDecision/NonExecutableDecision shapes this
integration reads (action, toolCallId, reason) are unchanged, confirmed
directly against the installed package's .d.ts, not assumed.
Verified against the real 0.4.3 install (resolved version, and lockfile
integrity hash, both confirmed exactly 0.4.3):
- npx tsc --noEmit (full project): clean, 0 errors.
- src/__tests__/unit/execution-guard.test.ts: 16/16 passing, identical
to the 0.2.0 result.
Adds src/__tests__/unit/execution-guard-post-terminal-authority.test.ts,
answering the actual question this bump exists to answer: does this
integration's own code exercise the fix, not just "does the library
still pass its own tests." resolvePendingExecutions() in
execution-guard.ts reads `decisions` directly off guard.finish()'s own
return value in the same statement - it never calls takeDecision().
A fresh guard is created per step and is never reused once its finish()
is read, so there is no async gap between this integration's own
finish() call and its own decision consumption for GHSA-3xpw-9694-2xxp's
literal finish()-to-takeDecision() window to open in here.
What is live in this integration is root cause op7418#1: whether a
late/contradicting raw event that arrives before a step's own
resolvePendingExecutions() call - anywhere in that step's fullStream -
correctly revokes authority instead of being silently dropped by the
adapter. The new test proves that directly, through this repo's real
execution-guard.ts functions (createStepGuard/registerDeferredExecution/
resolvePendingExecutions - the exact call path agent-loop.ts uses), plus
a control case confirming the fix does not overcorrect a genuinely clean
step. A second test exercises the raw prefix-safe-json library
(createAiSdkExecutionGuard directly, real push/finish/takeDecision, no
synthetic decision object) to confirm the literal advisory scenario is
fixed at the library level.
package-lock.json regenerated with `npm install prefix-safe-json@0.4.3
--save-exact`, not hand-edited.
Sign up for freeto 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.

2 participants

@xuxu777xu@op7418
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); feat: Windows platform adaptation by xuxu777xu · Pull Request #1 · op7418/CodePilot · GitHub
Skip to content

feat: Windows platform adaptation - #1

Merged
op7418 merged 2 commits into
op7418:mainfrom
xuxu777xu:feat/windows-drive-switcher
Feb 7, 2026
Merged

feat: Windows platform adaptation#1
op7418 merged 2 commits into
op7418:mainfrom
xuxu777xu:feat/windows-drive-switcher

Conversation

@xuxu777xu

@xuxu777xuxuxu777xu commented Feb 7, 2026

Copy link
Copy Markdown
Contributor

Summary

CodePilot 原本仅支持 macOS,本 PR 添加完整的 Windows 平台适配,使其可以在 Windows 上正常构建、运行和使用。

Changes

跨平台基础设施

  • 新增 src/lib/platform.ts:统一的跨平台工具模块,包含 Claude CLI 发现逻辑(Windows .cmd/.bat shell 处理、where/which 回退)、PATH 扩展(AppData/npm 等 Windows 路径)
  • 重构 src/app/api/claude-status/route.ts:移除硬编码的 Unix 路径,改用共享的 platform 工具
  • 重构 src/lib/claude-client.ts:同上,并确保 USERPROFILE 和扩展 PATH 在 SDK 子进程中可用

Electron 主进程

  • electron/main.ts
    • Windows 进程派生使用 windowsHide 防止控制台窗口闪烁
    • PATH 构建适配 Windows 分隔符(;)和目录结构(AppData/npm)
    • 窗口标题栏适配:macOS hiddenInset / Windows hidden + titleBarOverlay
    • 图标适配:Windows 使用 .ico
    • loadUserShellEnv() 跳过非 macOS 平台

构建配置

  • electron-builder.yml:新增 win + nsis 构建目标,支持自定义安装目录、桌面/开始菜单快捷方式
  • package.json:新增 electron:pack:win 脚本,原 electron:pack 改为平台无关
  • build/icon.ico:Windows 应用图标

UI 适配

  • src/components/chat/FolderPicker.tsx:新增盘符下拉切换器,解决 Windows 盘符根目录无法向上导航的问题
  • src/app/api/files/browse/route.ts:API 返回可用 Windows 盘符列表
  • src/components/skills/SkillsManager.tsx:修复 key 重复警告

Test plan

  • Windows 上 npm run electron:pack:win 构建成功
  • 安装后启动,Claude CLI 自动检测并连接
  • 标题栏样式正确(隐藏标题栏 + overlay 控制按钮)
  • FolderPicker 盘符切换正常工作
  • macOS 上 npm run electron:pack:mac 构建无回归

🤖 Generated with Claude Code

xuxu777xuand others added 2 commits February 7, 2026 13:29
When navigating to a drive root on Windows (e.g. C:\), path.dirname
returns itself, disabling the "go up" button and trapping the user on
that drive. This adds a compact dropdown next to the up button that
lists all available drives (auto-detected via fs.accessSync), allowing
quick switching between drives. macOS/Linux are unaffected (empty array,
dropdown not rendered).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add src/lib/platform.ts: cross-platform Claude CLI discovery
(candidate paths, .cmd/.bat shell handling, where/which fallback)
- Refactor claude-status route and claude-client to use shared platform utils
- Electron main: Windows process spawning (windowsHide), PATH construction
with AppData/npm dirs, titleBarOverlay, .ico icon support
- electron-builder.yml: add win/nsis build targets
- package.json: add electron:pack:win script
- FolderPicker: drive switcher dropdown for navigating between drives
- SkillsManager: fix duplicate key warning with filePath fallback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@xuxu777xuxuxu777xu changed the title feat: add Windows drive switcher in FolderPickerfeat: Windows platform adaptationFeb 7, 2026
@op7418
op7418 merged commit b819eb7 into op7418:mainFeb 7, 2026
op7418 added a commit that referenced this pull request Apr 12, 2026
…ion for Native Runtime
Two feature gaps where Native Runtime didn't match SDK Runtime, both
surfaced during post-hermes-upgrade manual testing:
── #1: Compression notification now human-readable ──
Before: chat/route.ts:402 emitted `message: 'context_compressed'` as
a machine string. useSSEStream's notification branch showed this raw
string in the status bar — users saw "context_compressed" flash by.
After: message is now `"Context compressed: N older messages summarized,
~X tokens saved"` with structured `stats: { messagesCompressed, tokensSaved }`
for future rich UI handling. Added `subtype: 'context_compressed'` for
dedicated frontend handlers.
── #3: AskUserQuestion tool for Native Runtime ──
Before: only SDK Runtime had AskUserQuestion (built into Claude Code CLI).
Native Runtime had no such tool, so the model could never ask structured
questions — the existing AskUserQuestionUI in PermissionPrompt.tsx was
unreachable dead UI code for Native Runtime users.
After:
- New builtin tool `src/lib/builtin-tools/ask-user-question.ts`
registered in index.ts, condition 'always'
- Zod schema: 1-6 questions, each with 1-6 options, optional multiSelect
- Execute receives answers from permission flow (injected by frontend)
and formats as Q/A pairs for the model
- permission-checker.ts: new ALWAYS_ASK_TOOLS set ensures AskUserQuestion
(and ExitPlanMode) always show UI even in trust mode — without this,
trust mode would auto-approve and return empty answers
- PermissionPrompt.tsx: NEVER_AUTO_APPROVE set prevents full_access mode
from auto-approving AskUserQuestion — the UI must render so the user
can answer
The data flow:
Model → AskUserQuestion({ questions }) → permission wrapper intercepts
→ SSE permission_request → frontend AskUserQuestionUI renders
→ user picks options → updatedInput({ questions, answers }) → tool
execute formats answers → model gets "Q: ... A: ..." string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KevinYoung-Kw referenced this pull request in KevinYoung-Kw/CodePilot Apr 15, 2026
**补充修复**
在 #1 斜杠命令保留已有文本的修复基础上,进一步确保选择命令后光标自动定位到输入框尾部,而不是默认的首部。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
KevinYoung-Kw referenced this pull request in KevinYoung-Kw/CodePilot Apr 15, 2026
**补充修复**
在 #1 斜杠命令保留已有文本的修复基础上,进一步确保选择命令后光标自动定位到输入框尾部,而不是默认的首部。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
v0.56.x 计划 Phase 1:建立稳定性治理入口,并用当前源码重新核验 Notion/issue 列出的
7 个 issue(不采信 issue 自述根因)。
GitHub 侧(已在仓库生效,非本 commit 内容):
- 创建 milestone #1「v0.56.x Stability / Trust」。
- 创建 9 个治理 label:P0-crash-or-interrupt / P0-data-loss-risk / P1-runtime-session /
P1-context / P1-file-reference / P1-installer-update / P1-performance / needs-repro /
v0.57+ parking-lot。
- 给 #626/#628/#629/#632/#633/#634/#635 按复核结论打 milestone + 优先级 label。
本 commit 文件:
- .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml:bug 表单强制必填
版本/OS/runtime/provider-model/可复现/复现步骤/期望vs实际 + 影响面勾选;feature
表单注明 v0.56.x 冻结新功能 → v0.57+ parking-lot;config 关闭空白 issue + 冻结说明
与 Discussions 入口。
- .github/PULL_REQUEST_TEMPLATE.md:Summary / Repro+root cause / Changes / Tests /
Screenshots-logs / 自查清单(链到 CLAUDE.md 与 AGENTS.md,不复制维护)。
- .github/TRIAGE.md:对外冻结说明、label 体系、issue/PR triage 规则、自动化候选。
- v0.56.x-stability-trust.md:标 Phase 0 完成 + 新增「2026-06-19 Claude Code 源码复核」
表(7 issue 逐条 file:line 证据)。关键复核结论:
* #632 ">100%" 确认是未 clamp 的 ratio*100 显示 bug(RunCockpit.tsx:169 等),分母
contextWindow 不可靠;"跨会话串" 源码不成立。
* #629 空 assistant 已防护,残留真实 gap:is_error result 路径不清坏 sdk_session_id
(claude-client.ts:1908 先置 resultEmitted)。
* #635 截图-only,最强候选 = SDK runtime 无自生成 keepalive(claude-client.ts:1956),
慢 proxy 静默 >330s 被 idle abort(B-019)。
* #628 确认真实风险:@file origin path 在 MessageInput.tsx:161 丢失,body.mentions[]
送达但 route.ts 从不消费 → 写 .codepilot-uploads 副本,AI 改副本。
* #634 根因不成立——5 个 notify/schedule 工具均注册(builtin-tools/index.ts:250),
issue 引用的 UI 串不在当前源码(疑旧版);附带 Plan 模式 list_tasks 泄漏。
* #626 polling 排除(8h 间隔),候选 animate-pulse × backdrop-filter 重绘。
* #633 mac 无法复现;NSIS-only + 未签名 + 无 portable + CI 不验安装启动。
- issue-tracker.md:新增「v0.56.x 治理 issue」看板索引表(指向 plan 复核表,不重复分析)。
验证:docs-drift 通过;npm run test(hook)。Phase 1 验收(milestone/labels/模板/冻结
说明就绪)达成。下一步 Phase 2:按复核结论修 chat 主链路(上下文百分比语义、context-cost
不阻断发送、Codex 多模态发送、发送后清草稿)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: issue #632 报"上下文 >100% / 假百分比 / 压缩后跳变";Phase 1 源码复核确认是
真实显示 bug("跨会话串"不成立)。
Triage(当前源码): 用量百分比 = usage.ratio*100,在 RunCockpit.tsx 与
RunCockpitPopoverContent.tsx 两处直接渲染、未封顶;usage.ratio = used / contextWindow,
而 contextWindow 来自 sdkContextWindow ?? latestSdkContextWindow ?? catalogContextWindow
(useContextUsage.ts)。很多第三方 proxy 不上报 context_window → 落到静态 catalog 兜底
(一个猜测值),used 又会在压缩后跳变 → 百分比蹦到 200%/500%。根因是"拿不可信的分母
算百分比",不是上下文真的超了。
Fix:
- useContextUsage.ts: 新增 ContextUsageData.contextWindowTrusted —— 仅当 SDK/上游真实
上报窗口时为 true(catalog 兜底不算)。三个 return 分支(baseline / snapshot / no-baseline)
都按各自来源正确赋值。不可信时不把窗口喂给 buildContextUsageBreakdown,dot-matrix 退回
按已用 token 的构成比例,不编造容量。
- RunCockpit.tsx: hasFullCtx 增加 && usage.contextWindowTrusted —— 不可信时自动落到既有的
绝对已用 token 显示(触发按钮)/ showUnknownCapacityBlock 分支(浮层,已测试的"容量未知"
路径)。百分比文案 clamp ≤100%。
- RunCockpitPopoverContent.tsx: 浮层 header 百分比同样 clamp ≤100%(防可信窗口被 used 短暂
超过时仍蹦 >100%)。
语义验收: 输入框右下角不可信时只显示已用绝对值;浮层不可信时只显示已用 + 不同种类构成
比例(无百分比/remaining/unused/假总量);可信时百分比封顶 100%。
Verify: typecheck 通过;context-window-trusted.test.ts 6 条 source-pin + 既有
run-cockpit-unknown-capacity / context-dot-matrix / context-usage-walk / context-breakdown
全绿;全量单测 3366/3366。未做:真实 untrusted-window provider 会话的 CDP 视觉走查
(fix 把 untrusted 路由到既有已发布的"容量未知"分支,风险低;视觉走查列为后续)。
Guardrail: context-window-trusted.test.ts 钉死 trusted 派生只认 SDK 来源、不可信时不喂窗口、
hasFullCtx 必须 gate trusted、两处显示 clamp ≤100%,防回退到"拿 catalog 当真实分母算百分比"。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: Codex 复核 fix#1(b842628)后发现 P2 残留——文字已改成"只显示已用 token",
但输入框右下角触发按钮旁的 mini dot-bar 仍用 200K 兜底画出"用了多少/还剩多少"的容量
暗示,与"拿不到总长度就不显示容量"及 commit message 的"不编造容量"不一致。
Triage(当前源码): ContextDotMatrix.tsx 有 FALLBACK_CONTEXT_WINDOW=200_000,
minCellsPerKind=0(mini-bar)在窗口未知时用它当分母(:88);RunCockpit.tsx:200 的触发
按钮无条件渲染这个 mini-bar。所以即使 b842628 把文字降级为绝对已用,小条仍画假容量。
minCellsPerKind=0 全仓只有 RunCockpit 触发按钮一个调用方。
Fix:
- RunCockpit.tsx: mini-bar 用 {hasFullCtx && (...)} 包裹——仅在可信窗口下渲染容量小条;
不可信时触发按钮只剩绝对已用 token 文本(贴合"输入框右下角只显示已用数值")。
- ContextDotMatrix.tsx: 删除 FALLBACK_CONTEXT_WINDOW(200K)。窗口未知时两种模式都按
used+pending 分配(构成视图,非容量%),不再编造容量。
Verify: typecheck 通过;context-dot-matrix.test.ts 旧的"unknown mini-bar 用 200K 兜底
(filled<=2)"语义改为新的"used 构成(filled>=8)";context-window-trusted.test.ts 加 2 条
guardrail(mini-bar gate 在 hasFullCtx + 源码无 200K 兜底残留);全量单测 3368/3368。
Guardrail: 两条 source-pin 钉死"触发按钮 mini-bar 必须 gate 在 hasFullCtx"且"ContextDotMatrix
不得再出现 FALLBACK_CONTEXT_WINDOW/200_000",防回退到拿假容量画小条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
用户复核 fix#1 后明确显示格式:输入框右下角的上下文小标,在有可信窗口时显示
"百分比 + 已用上下文"(如 56.6% 452K),没有可信窗口时只显示已用(如 452K),
不单列"剩余"数字。
改动:RunCockpit.tsx 触发按钮 ratioText 的可信分支由 "{pct}%" 改为
"{pct}% {used}"(1 位小数,匹配用户给的 56.6% 示例);不可信/无数据分支不变。
context-window-trusted.test.ts 的 clamp pin 扩为同时断言"百分比 + 已用"格式。
验证:dev 应用热重载干净(✓ Compiled);context-window-trusted 8/8;typecheck(hook)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Signal: 用户在运行的应用里看到 GLM-5-turbo(Claude Code/Native 会话)仍显示总上下文
200K,指出"这并不是我们知道的部分"。fix#1 本应让 catalog 静态值不可信、只显示已用。
Triage(当前源码,用户 review 驱动): agent-loop.ts:641-651(Native)在 token_usage
没有 context_window 时,从静态 catalog 填 totalUsage.context_window = getContextWindow(modelId)
(GLM-5-turbo 在 catalog 是 z.ai 核实的 202752)。而 context-usage-walk 把
token_usage.context_window 当作 SDK 实报窗口读,fix#1 的 contextWindowTrusted 据此判可信
→ catalog 猜测被"洗白"成可信 → Native GLM 显示 200K。即上游 mutator 打败了 helper 修复
(feedback_fix_all_consumers)。claude-client(Claude Code)只从 SDK modelUsage 写,不洗白;
ContextUsageIndicator 是死组件(无人 import)。
Fix: 删掉 agent-loop 的 catalog 洗白。Native 无 runtime 实报时 context_window 留空 →
useContextUsage 回落 catalog 为不可信 → 只显示已用绝对值,不再有假百分比/假总量。
仅对新 turn 生效(历史消息已存的 context_window 不改写,遵守不改用户数据;旧会话发新消息后转为已用-only)。
Verify: typecheck;context-window-trusted.test.ts 新增 pin 断言 agent-loop 不再
`.context_window = catalogWindow`;该文件 9 测 + agent-loop-error-event 全过。运行中 dev 应用
server 重编译干净(Native GLM 需发新消息验证)。
Guardrail: source-pin 防 Native 再把 catalog 洗进 SDK-authoritative 字段。
设计记录(用户批准"先记计划再实现"): v0.56.x 计划写入 context-window 来源优先级修订设计
(runtime 实报 > provider 配置 contextWindow > 压缩阈值 > catalog 不可信)+ 跨 Runtime 用户
配置源(#1,待实现) + 显示分母对齐压缩阈值(#3,待实现)。本提交是设计第一步(去洗白)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
把"为什么 GLM 显示 200K + 窗口来源该怎么改"写成评审稿放进 v0.56.x Phase 2,按
外部事实 / 本地证据(file:line) / 推断与设计三层分写,供 Codex 核实。
要点:
- Agent SDK v0.2.111 的 modelUsage.contextWindow(sdk.d.ts:945)是未文档化字段,来自
SDK 内置模型目录而非 API;第一方可靠、第三方(经 base_url 的 GLM)返回通用默认值;
无 SDK 设置可覆盖;Anthropic 建议自维护窗口表。
- 实测 GLM 会话 token_usage.context_window=200000 ≠ 本地 catalog 202752,证实来自 SDK
默认而非 catalog/Native 洗白;该会话是 Claude Code(故上一提交的 Native 修复不覆盖它)。
- 修订设计:窗口来源优先级 = 用户覆盖 > 已核实 catalog/provider 配置 > SDK(仅第一方) >
只显示已用;第三方忽略 SDK 默认值;跨 Runtime;显示分母对齐压缩阈值(#3)。
- 列出待定决策(已核实优先 vs 纯手动) + 给 Codex 的 5 个核实点。
未改任何产品代码(纯文档)。#1/#3 实现待 Codex 核实后进行。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
Codex 复核设计稿后订正(实现 #1/#3 前必须):
- A:原"官方文档不记载 contextWindow/maxOutputTokens"不准 → 改为 SDK TypeScript
reference 有字段定义,是 cost-tracking 指南未解释来源/可信度。
- B/C:原"catalog 202752 比 SDK 200000 更准且 z.ai 核实"站不住 → z.ai 官方写
200K/128K,catalog 该条来源存疑;结论收敛为"SDK 200000 不可作为 provider 实报采信",
不延伸到"catalog 更准";另标记需单独核 model-context.ts:42 的真实来源。
- D + 决策日志:统一优先级(消除冲突,旧决策日志把第三方 SDK 又洗白成可信)→
用户手动覆盖 > provider/model 配置且来源已验证 > 第一方 runtime 实报 > 只显示已用;
第三方 SDK contextWindow 默认不可信、无明确来源 catalog 不当可信%显示。
- "Anthropic 官方建议自维护表"未核到原文 → 降级为工程结论。
- 澄清:用户实际看到 200K 的 GLM 会话是 Claude Code(SDK 默认 200000),非 Native 洗白
路径(681706b 的 Native 修复有效但治另一条路径)。
- E:决策收敛为一条基线 + 剩余一项请用户定(第一方 SDK 实报是否自动显示百分比)。
Codex 核为真的部分(sdk.d.ts:945 字段、代码写入 token_usage、历史 SDK 窗口被当可信、
Native 洗白已去、显示分母 vs 压缩阈值脱节)保留。纯文档,未动产品代码。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
F 段核实点 #1 还残留旧"官方文档未记载(A)",与已订正的 A 段不一致。改为:
sdk.d.ts:945 的 contextWindow/maxOutputTokens 存在,SDK TypeScript reference 已列,
只是 cost-tracking 指南未解释来源/可信度。纯文档。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
… Phase 2 ①)
Signal: 用户 GLM-5-turbo(Claude Code 经代理)显示总上下文 200K,且 Codex 核实 SDK 的
modelUsage.contextWindow 来自 SDK 内置目录、对第三方是通用默认值、无 SDK 设置可覆盖。
Triage: claude-client.ts extractTokenUsage 把 SDK modelUsage.contextWindow 无条件写入
token_usage.context_window;walk + fix#1 据此判可信 → 第三方代理(GLM)的 SDK 默认 200000
被当可信显示。Native 的 catalog 洗白已于 681706b 去掉;本提交补 SDK 路径。
Fix(Codex 统一口径"第一方 runtime 实报可信、第三方不可信"):
- ai-provider.ts 导出 isFirstPartyAnthropicEndpoint(baseUrl)(空/anthropic.com → 第一方)。
- extractTokenUsage 增 trustContextWindow,仅 true 时写 context_window;两个调用点都传
isFirstPartyAnthropicEndpoint(resolved.provider?.base_url)。第三方(自定义 base_url,如 GLM)
→ 不写 context_window → useContextUsage 回落 catalog 为不可信 → 只显示已用。
效果 + 边界: 第一方 Anthropic 继续显示百分比+已用;第三方代理新 turn 起只显示已用。
仅对新写入生效(历史消息已存的 context_window 不改写,遵守不改用户数据);现有 GLM 会话
仍显示旧值,需新会话/新 turn 验证(walk 会读历史,故旧会话需自然滚动出旧窗口或新建)。
Verify: typecheck;extract-token-usage-context-window.test.ts 增 2 pin(gate + 两调用点传
第一方判别);全量 3371/3371。
Guardrail: source-pin 钉死 context_window 写入受 trustContextWindow 门控 + 两调用点必须传
isFirstPartyAnthropicEndpoint,防回退到无条件信任第三方 SDK 窗口。
remaining(Phase 2 ①/③ 未完): provider/model 配置窗口作为最高优先可信源(用户覆盖) + 渲染层
对现有会话按第一方 gate(治旧会话) + #3 显示分母对齐压缩阈值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
计划文档状态审计修正(决策日志准、但概览层过期):
- frontmatter 状态行:📋 待接手 → 🚧 Phase 0/1 已完成、Phase 2 进行中。
- 「状态总览」表:Phase 1 待开始 → ✅ 已完成(2026-06-19);Phase 2 待开始 → 🚧 进行中。
- Phase 2 加进度 note:Composer/Context 主链路 #1#5 全部收口(含 commit + #3 真实
Codex 冒烟回复 circle);Session/Stream cluster #629/#635 + 终态原因码 + 压缩回滚
+ 诊断导出字段待续。
- Phase 2 执行清单 4 项已完成项 [ ]→[x](上下文 UI 语义 / context-cost 去阻断 /
Codex 多模态发送 / 发送后草稿清理)。
CLAUDE.md 执行计划段新增「完成即回写进度(与 Codex 对齐协作)」:任一 Phase/子项做完
必须立即回写三处且一致——执行清单勾选 / 状态总览表+frontmatter / 决策日志(commit
+验证结论);Claude 实施+回写、Codex 审查+维护;三者不一致视为状态失真须先对齐。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
打回上一条状态同步的一处失真:我把 #4/#5「发送后内容残留」标成完成(checklist [x] +
进度 note 列为 done),但同一文档决策日志(2026-06-20 条)已写明用户再次确认"内容已发出
但文本仍残留输入框"、#615 source-pin 不覆盖该症状、不能算闭环——状态表/清单与决策日志
自相矛盾,违反刚加的"三者必须一致"。
修正(与决策日志对齐):
- checklist「复现并修发送后内容残留」[x] → [ ],标注"待复核/待修复(用户 2026-06-20 再报)"。
- Phase 2 进度 note:拆分——#4/#5 仅失败保留有基础修复(#615),发送成功后文本残留待复核;
note 标题从"主链路已收口"改为"#1#3 收口、#4/#5 待复核";待续列表补回 #4/#5(重新打开)。
- #2 context-cost 非阻断保持完成(checklist [x] + note)不变。
后续修 #4/#5 时重点:PromptInput 受控/非受控清空边界、setInputValue('') 与
controller.textInput.clear() 是否同源、成功 accepted 后 remount/local draft 恢复、
badge/confirm/image 分支与普通 Enter 分支是否一致(决策日志已记排查方向)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
按"完成即回写进度"规则同步三处:
- checklist「复现并修发送后内容残留」[ ]→[x],标注已修 + CDP 验证 + 根因/修法(58c7aad)。
- Phase 2 进度 note:#1#5 全部落地;#4/#5 从"待复核"改为"已定位+修复"(含根因/CDP 结论);
待续列表移除 #4/#5、只留 Session/Stream cluster。
- 决策日志加同日条目:CDP 埋点定位 = 首条消息 accept 布局翻转 remount composer、inputValue
从 sessionStorage 草稿重读;修法 = accept 处清草稿;3401/3401 + CDP 文本/图文首条 800ms 即清。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
用户在浏览器实测不残留、仅桌面 App 残留 → Claude 协助完整重启 electron:dev(kill 整棵
进程树 + 释放 3000 + 后台重启)→ 用户在重启后真实 App 验证发送即清空 → #4/#5 闭环。
根因:58c7aad(page.tsx accept 处清首条草稿)一直是对的;用户残留是 Electron dev 没把
page.tsx 改动热更新进 renderer、窗口刷新无效,得整进程重启。这解释了全程「Claude CDP
浏览器清、用户残留」的矛盾——不是 Electron 行为差异,是构建新鲜度差异(Claude 浏览器硬刷
过有修复、用户 Electron 旧构建没有)。
回写:checklist [x](用户真实 App 验证)、进度 note #1#5 全闭环、验收去 ⚠️、决策日志加
闭环条目 + 教训(UI 修复在桌面 App 验证必须整重启 electron:dev)。Codex P1(prefill/
initialValue 回灌)仍是 58c7aad 的真实独立漏洞、值得单独补,与本次残留无关。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 28, 2026
纯文档同步,无代码改动。目的:让下一个进程打开文档时不从旧状态误判进度。
三处状态表此前已标 Phase 0/1 ✅、决策日志也已确认完成,唯独执行清单 checkbox
与 README 索引、issue-tracker #632 仍停在旧值——三处不一致即状态失真,本次对齐。
README.md:
- v0.56.x 索引行状态列 "📋 待 Phase 0 收束" → "🚧 Phase 0/1 ✅;Phase 2 进行中
(Composer/Context 主链路 #1#5 闭环,Session/Stream cluster #629/#635 待续)",
追上 plan frontmatter 与决策日志。
v0.56.x-stability-trust.md:
- Phase 0 执行清单 8 项 [ ]→[x],逐条带回溯(3360/3360、9c6e772、f99edbb/d00449f)。
A2 计时器项如实标注:按 keyed-remount 构造性消除 + 截图不可判别记录入 Smoke Ledger,
非逐帧视觉确认(反假数据,不谎称做了视觉确认)。
- Phase 1 执行清单 5 项 [ ]→[x],带回溯(milestone #1 / 9 labels / .github/TRIAGE.md)。
issue-tracker.md:
- #632 状态 "🔴 待修" → "🟡 假%已修,item3 分母对齐待续"。核心显示 bug(假百分比/>100%)
已由 effective-base-URL 写入 gate + 渲染期 trusted gate + clamp 修复并经真实 GLM
会话验证;item3(显示分母对齐压缩阈值)是独立待续阶段,故标部分修复而非已修复。
- 顶部"最后更新"同步到 2026-06-26 + #632 同步说明。
验证:git diff 确认仅 3 文档、16/16 行 checkbox 与状态文字,无代码/意外文件。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jul 4, 2026
- docs/research/ai-sdk-7-toolloop-parity-gaps.md: 新增「Phase 5 处置」节,全部 gap
收口——P1×3 关闭(#1/#2 补偿由 parity 8/8 复跑锁定;#3 降级论证:Phase 4 已证
approval HMAC 不需要 SDK toolApproval 停机语义,维持 in-execute 路线),
P2/P3 关闭或 backlog(#4/#5 列为替换路线前置条件,#7 归档 tech-debt #49#8 有 Phase 5 新实证)
- scripts/smoke-ai-sdk7-phase5-decision.ts: 新增决策门对照 smoke——prod runAgentLoop
与 POC runToolLoopAgentPoc 用同一 AgentLoopOptions 逐场景对照(长文本 / approval
批准 / approval 拒绝 / abort→continue),机械比较归一化事件序列 + 尾部契约 +
usage 存在性;DB 只读、数据目录隔离、输出全 scrub。探针注意:approval 批准分支
用 printf(echo 命中 permission-checker 自动放行规则不会触发 ask)
- docs/exec-plans/active/_smoke-evidence/ai-sdk7-phase5-decision-smoke.json:
OpenRouter 真实渠道 4/4 场景 contractMatch=true(input_tokens 逐场景完全相同,
tool_result 逐字相同,中断轮双侧 done 收尾、同 session 续发一次通过);
凭据形态 grep=0
- docs/research/ai-sdk-7-adoption-decision.md: 新增采用决策文档——结论 partial
(依赖升级 go / provider 能力 capability-gated go / Phase 4 外围能力 go /
@ai-sdk/mcp 与默认 loop 替换 no-go-现在),四层 rollback plan(能力开关→
wrapper→runtime switch→known-good version),每项结论标注 Phase 1-5 证据来源;
默认 Runtime 切换留人类闸门
- docs/exec-plans/tech-debt-tracker.md: 新增 #49(tool-error part 被两条 loop
一致吞掉的既有 UX 债,独立于采用决策)
- docs/exec-plans/active/ai-sdk-7-runtime-loop-adoption.md: Phase 5 状态回写 +
决策日志 + Smoke Ledger / Loop Ledger 各一行
- docs/research/README.md: 索引新增决策文档条目
验证: npm run test 3598/3598 全绿;smoke 4/4 contractMatch(1 个 fix cycle 收敛,
两处均为脚本层问题非 loop 差异);src/ 零改动(默认 Runtime/聊天路径零变化)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jul 4, 2026
用户批准 partial(2026-07-04, run issue #10): 采用 ai@7/@ai-sdk/* 依赖升级、
provider 参数能力 capability-gated、openai-chat image wrapper、timeout 原因码/
approval HMAC/trace 脱敏四件套(默认值经用户确认); @ai-sdk/mcp adapter 与
ToolLoopAgent 默认 loop 替换均不采用(留实验路径)。发版前保留官方一方 key
smoke gate。冲突仅 ai-sdk-7 计划决策日志一处,union 双方条目解决。
五个 phase 全部经 hands-off loop 完成并 Codex accepted(issues #1/#6/#7/#8/#10)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ion for Native Runtime
Two feature gaps where Native Runtime didn't match SDK Runtime, both
surfaced during post-hermes-upgrade manual testing:
── op7418#1: Compression notification now human-readable ──
Before: chat/route.ts:402 emitted `message: 'context_compressed'` as
a machine string. useSSEStream's notification branch showed this raw
string in the status bar — users saw "context_compressed" flash by.
After: message is now `"Context compressed: N older messages summarized,
~X tokens saved"` with structured `stats: { messagesCompressed, tokensSaved }`
for future rich UI handling. Added `subtype: 'context_compressed'` for
dedicated frontend handlers.
── op7418#3: AskUserQuestion tool for Native Runtime ──
Before: only SDK Runtime had AskUserQuestion (built into Claude Code CLI).
Native Runtime had no such tool, so the model could never ask structured
questions — the existing AskUserQuestionUI in PermissionPrompt.tsx was
unreachable dead UI code for Native Runtime users.
After:
- New builtin tool `src/lib/builtin-tools/ask-user-question.ts`
registered in index.ts, condition 'always'
- Zod schema: 1-6 questions, each with 1-6 options, optional multiSelect
- Execute receives answers from permission flow (injected by frontend)
and formats as Q/A pairs for the model
- permission-checker.ts: new ALWAYS_ASK_TOOLS set ensures AskUserQuestion
(and ExitPlanMode) always show UI even in trust mode — without this,
trust mode would auto-approve and return empty answers
- PermissionPrompt.tsx: NEVER_AUTO_APPROVE set prevents full_access mode
from auto-approving AskUserQuestion — the UI must render so the user
can answer
The data flow:
Model → AskUserQuestion({ questions }) → permission wrapper intercepts
→ SSE permission_request → frontend AskUserQuestionUI renders
→ user picks options → updatedInput({ questions, answers }) → tool
execute formats answers → model gets "Q: ... A: ..." string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ge generation results
GPT-Image-2.0 skill silent failure had two compounding causes both
on the 'tool result' loop:
P0 op7418#1 — function_call_output translated with sentinel toolName
translate-input.ts wrote toolName: '__from_responses_proxy__' for every
tool-result and the comment claimed 'ai-sdk doesn't use this for
routing'. That was wrong. Anthropic and OpenAI Responses both look
up the tool definition by tool-result.toolName when reconciling the
result with the request's tool surface; with a sentinel they can't
correlate and refuse to produce the continuation turn — exactly the
'tool ran, no follow-up text' the user saw.
Fix: walk the input array once first to build call_id → toolName
from function_call items, then look up the real name when translating
function_call_output. Orphan results (no matching function_call) fall
back to a named sentinel '__orphan_function_call_output__' AND emit
console.warn naming the call_id. The divergence stays loud.
P0 op7418#2 — imageGeneration / imageView silently dropped
event-mapper.ts had both item types in CHAT_ONLY_ITEM_TYPES, which
returns null on item/started + item/completed. That set is correct
for agentMessage/plan/reasoning (they have streaming delta channels
so the content arrives separately), but imageGeneration / imageView
have NO delta channel — their final item is the only surface where
the result reaches the user. Silent drop meant 'tool ran' with no
visible image.
Fix: move both types to TOOL_LIKE_ITEM_TYPES, add explicit
translateItemStarted branches with names image_generation /
image_view, and the existing TOOL_LIKE_ITEM_TYPES completion branch
already packs the full item into output — preserving result,
savedPath, revisedPrompt, path for chat-side rendering.
ThreadItemLike grew matching fields so TS doesn't downgrade access
to (item as { path?: string }).path casts.
Tests (8 new)
src/__tests__/unit/codex-proxy-translators.test.ts (+3):
- toolName resolves from matching function_call (gpt_image_2 case)
- toolName resolves correctly with interleaved out-of-order calls
- orphan function_call_output → named sentinel + console.warn
src/__tests__/unit/codex-event-mapper.test.ts (+4):
- imageGeneration item/started → tool_started(name='image_generation')
- imageGeneration item/completed → tool_completed with full
result + savedPath + revisedPrompt payload
- imageView item/started → tool_started(name='image_view') + path
- imageView item/completed → tool_completed with path preserved
src/__tests__/unit/codex-proxy-tool-contract.test.ts (+1):
- End-to-end continuation: function_call → function_call_output →
streamText(messages) — MockLanguageModelV3 must see toolName
'gpt_image_2' in its prompt, NOT '__from_responses_proxy__'.
Continuation text-delta event fires.
The mapper-side translate also removed the chatOnly array's
imageView / imageGeneration entries from the old 'returns null'
parameterised test; replaced with the new lifecycle describe block.
Closeout doc records round 7 ✅ items; remaining must-haves
unchanged (4-family smoke matrix + codex-sdk POC).
All 2416 tests pass (was 2412 + 8 new − 4 obsolete from the chatOnly
table for imageView/imageGeneration).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…ce 2a
Direction approved; three sharpenings folded into the existing
Phase 2 plan structure without restructuring.
1. Widget wire-format single source (review revision op7418#1)
slice 7's WIDGET_SYSTEM_PROMPT template-literal-embeds
WIDGET_WIRE_FORMAT_SPEC. With artifactContracts ordered BEFORE
capabilityFragments in the compiler, the wire spec would land in
the final system prompt twice (once from artifactContract, once
from the capability fragment tail). The plan now declares hard
constraints — CANONICAL_SHOW_WIDGET_JSON, the "FINAL OUTPUT
FORMAT" title, and WIDGET_WIRE_FORMAT_SPEC each must appear
exactly once in the compiled system prompt — and assigns slice
2c a small refactor that strips the wire spec from
WIDGET_SYSTEM_PROMPT so artifactContract becomes the sole holder.
Compile-time sanity check (capability fragment text MUST NOT
contain artifactContract.canonicalJson) added as a defence-in-
depth FAIL path.
2. Expected Differences Ledger (review revision op7418#2)
2b's "compiler output === Runtime current prompt" stance
directly conflicted with slice 2d's plan to canonicalize Native
memory / notify / media-import paraphrases. Equivalence reading
strictly would have locked the old drift in. Plan now introduces
`src/lib/harness/expected-differences.ts` with typed entries
(runtimeId, capability, diff kind, justification,
plannedResolution, compilerSource, runtimeSource). 2b harness
reads "compiler vs runtime diff ⊆ ledger"; unregistered
differences fail. Initial ledger seeded with the four known
Phase 5c slice 7b tech-debt items, three earmarked for slice 2d
and one (image_generation MediaBlock shape) earmarked
follow_up. Slice 2d completion = manual ledger entry removal
(deliberate non-automation, preserves audit trail).
3. runtimeHints boundary (review revision op7418#3)
Plan tightens the runtimeHints type declaration so it cannot
become a fourth prompt-assembly point. Allowed: IDs (mcp server
names, tool keys, builtin tool name set), fragmentIds refs into
CompiledContext, adapter options (stopWhen / stepCount /
passthroughToolTypes). Forbidden: any prompt text string, tool
description paraphrase, capability redefinition. Three test
layers — type-level (string fields ≤ 64 chars, no newline / no
markdown), runtime-level (no template-literal-shaped values),
source-grep level (no multi-line template literals in
runtimeHints assignments) — plus a dangling-reference check
that every fragmentId in runtimeHints resolves in
CompiledContext.
Regression test list extended 9 → 12. Decision log records all
three revisions with rationale.
Plan still in 📋 status. No code; awaiting Codex re-review on the
revised draft, then slice 2a opens.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
User mode change: "internal slice order preserved, external single
delivery; stop only after Phase 2 is done; Codex review takes the
batch." This commit lands slices 2a–2e together with all post-
review hardenings (Widget wire-format single source, Expected
Differences Ledger, runtimeHints prose ban).
Internal slice walk
2a — context-compiler.ts (NEW)
Pure function `compileContext(input): CompiledContext`. No IO,
no provider calls. Resolves enabledCapabilities (null = catalog
live default), looks up exposure for the calling runtime, emits
capabilityFragments + artifactContracts + memory + workspace +
toolDescriptors + runtimeHints + budget + systemPromptText +
diagnostics. Hard contracts: artifactContract before capability
in the assembled prompt; fragmentId uniqueness; cross-runtime
fragment text identity; compile-time FAIL if a capability
fragment text contains an artifact contract canonicalJson
(wire-format dedup); compile-time FAIL if load-bearing fragments
exceed budget. runtimeHints types strictly ID/refs/adapter
options — no prose, no template literals.
2b — expected-differences.ts (NEW)
Drift ledger. Initial 4 entries from slice 7b tech-debt. Three
slice_2d entries consumed by this commit (see 2d below); the
one remaining `follow_up` is image_generation MediaBlock shape
(non-prompt, future slice).
2c — ClaudeCode SDK (claude-client.ts) source-pin only
The SDK path has always imported MCP canonicals directly
(memory-search-mcp, notification-mcp, media-import-mcp,
cli-tools-mcp, dashboard-mcp) — no paraphrase ever existed.
Slice 2c codifies this with a contract test: claude-client.ts
must not import capability prompts from builtin-tools/* and
must not declare its own _SYSTEM_PROMPT scalars.
2d — Native Runtime (builtin-tools/*) re-export MCP canonicals
`memory-search.ts` now `export const MEMORY_SEARCH_SYSTEM_PROMPT =
CANONICAL_MEMORY_SEARCH_SYSTEM_PROMPT` (imported from
memory-search-mcp.ts). Same pattern for `notification.ts`
(NOTIFICATION_SYSTEM_PROMPT = NOTIFICATION_MCP_SYSTEM_PROMPT)
and `media.ts` (MEDIA_SYSTEM_PROMPT = MEDIA_MCP_SYSTEM_PROMPT
from media-import-mcp.ts). Three ledger entries removed in
sync.
2e — Codex bridge (builtin-bridge.ts + unified-adapter.ts)
Bridge no longer holds WIDGET_PROMPT / MEDIA_PROMPT /
MEMORY_PROMPT / NOTIFY_PROMPT scalars (all four declarations
deleted). `createCodePilotBuiltinTools().systemPrompt` is
permanently `''`. `unified-adapter.ts` now calls
`compileContext({ runtimeId: 'codex_runtime', ... })` and feeds
`compiled.systemPromptText` to Codex's `instructions`. A new
helper `capabilitiesFromBridgeToolNames` maps the bridge's
mounted tool names back to capability ids so the compiler's
enabledCapabilities aligns with what the bridge actually
exposes (workspace-gated memory tools naturally drop out when
workspacePath is empty).
Slice 2c Widget wire-format single source (review revision op7418#1)
WIDGET_SYSTEM_PROMPT in widget-guidelines.ts no longer
template-literal-embeds `${WIDGET_WIRE_FORMAT_SPEC}`. The
artifactContract is now the sole holder of the wire-format spec
+ canonical JSON. Compiler's `detectWireFormatDuplication` sanity
check throws at compile time if any capability fragment text
contains the artifact contract canonicalJson — that's the forcing
function preventing the spec from being re-injected.
Three regression pins enforce single occurrence in the compiled
prompt: CANONICAL_SHOW_WIDGET_JSON × 1, "FINAL OUTPUT FORMAT —
non-negotiable" × 1, WIDGET_WIRE_FORMAT_SPEC × 1.
runtimeHints boundary (review revision op7418#3)
ClaudeCodeHints / NativeHints / CodexProxyHints types now carry
only IDs (mcp server names, tool keys, builtin tool name set) +
adapter options (stopWhen, stepCount, passthroughToolTypes).
Tests pin: type-level (no string field > 64 chars, no newline,
no Markdown markers), runtime-level (scan all string values for
prose), source-grep (CodexProxyHints type definition can't
contain `promptOverride` / `promptExtra` / `widgetPrompt` / etc).
Tests
New harness-context-compiler.test.ts (23 pins): catalog hygiene,
Widget wire-format single source (op7418#10), ordering, budget
enforcement, cross-runtime fragment identity (op7418#9), tool
descriptors, runtimeHints boundary (op7418#11), Expected Differences
Ledger consistency (op7418#12), JSON parseability of every artifact
contract.
New harness-context-compiler-equivalence.test.ts (9 pins):
compiler source reachability, runtime drift honesty,
ledger/slice ownership correctness, "post-slice-2d: Native
ledger holds only the follow_up MediaBlock entry".
Updated harness-capability-contract.test.ts: drift pins now
check (a) bridge holds no local _PROMPT scalars, (b) Native
builtin-tools re-export MCP canonicals, (c) unified-adapter
imports compileContext + consumes systemPromptText, (d)
claude-client.ts doesn't import from builtin-tools/* and
doesn't declare own _SYSTEM_PROMPT.
Updated codex-widget-format-contract.test.ts: the "WIDGET_SYSTEM_PROMPT
embeds WIDGET_WIRE_FORMAT_SPEC" and "appears inside
WIDGET_SYSTEM_PROMPT" pins are flipped — slice 2c REMOVED the
embed; the new pins verify the compiler-side import line.
Updated codex-builtin-bridge.test.ts: tests previously asserting
`bridge.systemPrompt` contained capability tags now assert it
equals `''` (bridge is no longer the prompt-assembly point).
Verification
CODEX_DISABLED=1 npx tsx --test \
src/__tests__/unit/harness-context-compiler.test.ts \
src/__tests__/unit/harness-context-compiler-equivalence.test.ts \
src/__tests__/unit/harness-capability-contract.test.ts \
src/__tests__/unit/codex-widget-format-contract.test.ts \
src/__tests__/unit/codex-builtin-bridge.test.ts
→ 74/74 pass
npm run test → 2576/2576 pass
Completion criteria check (per user spec)
[x] npm run test all green (2576/2576)
[x] Context Compiler unit tests all green
[x] equivalence / expected-diff harness all green
[x] harness-capability-contract / codex-widget-format /
codex-builtin-bridge tests all green
[x] no new runtime-local prompt duplicates (Native re-exports
canonical; ClaudeCode imports canonical; bridge holds none)
[x] Codex bridge no longer holds WIDGET_PROMPT / MEDIA_PROMPT /
MEMORY_PROMPT / NOTIFY_PROMPT scalars (all four removed,
drift test pins their absence)
[x] all three Runtimes adapt compiler output, none redefine
capability prompts
Docs
- phase-5d-phase-2-context-compiler.md: slice statuses 2a–2e all
✅ 2026-05-17; note the one-shot delivery mode change.
- phase-5d-harness-capability-contract.md: Phase 2 row ✅, awaiting
Codex review.
- handover/harness-capability-contract.md: new "Context Compiler"
section detailing inputs/outputs/constraints, three-runtime
consumption pattern, Expected Differences Ledger contract.
- refactor-closeout.md: new decision-log entry recording the
Phase 2 delivery shape + completion criteria check.
Phase 5d Phase 2 ✅ pending Codex review. Phase 3 (Runtime
Capability Adapter) / Phase 4 (Artifact Contract) / Phase 5
(new-Runtime Playbook) intentionally NOT opened — stopping per
user instruction.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
… to breakdown
## 用户视角
升级前:popover 的"文件与附件 / 本次待加入"两行永远 0 —— 数据通道没接通。即使 composer 里挂了 4 个 mention 和 2 个目录引用,popover breakdown 显示 0。
升级后:MessageInput → ChatView/page → RunCockpit → useContextUsage → buildContextUsageBreakdown 全链路联通。composer 里的 attachment / mention / directory 实时累加到对应类别。trigger 上的迷你点阵 + popover 主条 + 列表行三处同步更新。
发送消息后 pending 归 0;下一轮 history 里的真实 token_usage 接管 used 部分;conversation 类自动吸收。
## 不做什么
- 不改 hook 其他字段(used / ratio / state / source 等不动)
- 不改 trigger 主结构(百分比文字仍在;只有点阵 cells 在分配时反映 pending)
- 不改 composer text 估算(composerTextTokens 仍 0;那是 Phase 3+ 的事)
## 怎么验收
- npm run test → 2921/2921 pass
- composer 里加附件 / @mention / "+" 目录 → trigger 上 pending 部分立刻有虚线 cells
- 发送消息 → pending 归零;下轮 used cells 更新
## 改动(6 文件)
### src/lib/message-input-logic.ts
新增 `PendingContextSubTotals` interface + `computePendingContextSubTotals()` 函数。逻辑 mirror `computePendingContextTokens`(同样的 null 过滤、同样的迭代顺序),但返回 { attachment, mention, directory } 三键。两个函数加起来 = 等于 computePendingContextTokens 总数。
### src/hooks/useContextUsage.ts
options 加可选 `pending?: { attachmentTokens?, mentionTokens?, directoryTokens?, composerTextTokens? }`。三条返回路径(snapshot / walk / noData)都把 options?.pending 转发给 buildContextUsageBreakdown。useMemo deps 数组加 options?.pending。
### src/components/chat/RunCockpit.tsx
RunCockpitProps 加可选 `pendingContextSubTotals?: { attachment, mention, directory }`。组件内部把它转换成 hook options.pending 形态(attachment → attachmentTokens 等)。可选 prop 默认 undefined → 不破坏现有 callsites。
### src/components/chat/MessageInput.tsx
- import 加 computePendingContextSubTotals + PendingContextSubTotals type
- props 加可选 `onPendingContextSubTotalsChange?` callback(跟现有 onPendingContextTokensChange 并列)
- 新增 useMemo 算 pendingContextSubTotals + useEffect emit callback
- 与现有 pendingContextTokens 走同一份 source 数据,逻辑同步无 divergence
### src/components/chat/ChatView.tsx
- 加 state `pendingContextSubTotals` (PendingContextSubTotals | undefined)
- MessageInput 上 wire `onPendingContextSubTotalsChange={setPendingContextSubTotals}`
- RunCockpit 上传 `pendingContextSubTotals={pendingContextSubTotals}`
### src/app/chat/page.tsx
- 跟 ChatView 完全镜像:state + MessageInput callback + RunCockpit prop
- 两个入口独立持有 state(按 StreamSession guardrail 不变量 op7418#1)
## Scope discipline
- 不新增测试(Codex 负责测试覆盖;用户分工已明确)
- 不动 buildContextUsageBreakdown / computePendingContextTokens 既有签名 → 旧调用 zero-risk
- 不改 chat-static-graph 排除清单 → MessageInput / RunCockpit 改动属于增量 prop,没新依赖链
- composerTextTokens 仍未 wire(composer 纯文本估算属于未来扩展,pending_next_turn 行暂时仍 0)
## StreamSession guardrail 合规
- 双入口(page.tsx 首消息 + ChatView 后续)独立 state — 不变量 op7418#1 ✅
- onSend / onCommand 签名不变 — rewind point 不变量 op7418#2 ✅
- 不动 capability cache — 不变量 op7418#3 ✅
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…18#31)
Codex review second round caught two real P1 inconsistencies introduced by
the Dashboard/CLI split slice plus non-blocking contract drift.
P1.1 — Dashboard injection gate ≠ route auth gate.
runtime.ts injected the dashboard read/write MCPs whenever prompt + working
directory + dashboard keyword matched, but the route's `authorize` requires
`sameRealPath(workspacePath, assistant_workspace_path)`. Mismatch → the model
sees the tool and Codex 403s at call time. Fix: dashboard injection mirrors
memory's gate exactly (same sameRealPath check, same `assistantWorkspacePath`
passed as `workspacePath`) so "inject" and "route-authorize" never disagree.
CLI tools don't need this (no workspace scope).
P1.2 — Matrix promoted only for codex_account; runtime injects for ALL
codex_runtime providers.
The runtime didn't gate injection by provider, so under a CodePilot proxy
provider the dashboard/cli MCPs WERE injected (callable), but the matrix
returned `perception_only` for non-codex_account — the opposite drift from
P1.1 ("model says yes, Settings says no"). Fix per Codex's preferred option:
move the promotion into `capabilityMatrixForRuntime` so it applies to ALL
codex_runtime providers; `capabilityMatrixForRuntimeProvider` now only adds
codex_account-specific overrides (native notes + image/media demotion).
`buildCapabilityMatrix` delegates to `capabilityMatrixForRuntime` so every
matrix entry point stays aligned.
Non-blocking op7418#1 — contract text drift.
capability-contract.ts dashboard/cli `deferredReason` + `codex_proxy.notes`
rewritten — explicit that the LEGACY provider-proxy bridge is unsupported
(true), and that the codex_runtime path now ships via the mutation-level MCP
split + matrix-layer promotion. No schema changes (`kind: 'unsupported'`
stays accurate for the legacy bridge surface); the existing matrix invariant
test gets a `MATRIX_LAYER_PROMOTIONS` exception list documenting why the two
promoted cells are allowed to be executable despite `kind: 'unsupported'`.
Schema cleanup (introduce a new `mcp_server_split` kind, drop the exception
list) tracked as tech-debt op7418#33.
Non-blocking op7418#2 — elicitation policy pins.
codex-mcp-events.test.ts now pins all 4 new server names:
codepilot_{dashboard,cli_tools}_read → auto_accept,
codepilot_{dashboard,cli_tools}_write → user_approval.
Also added a regression guard: `codex_runtime + non-codex_account provider`
must STILL show dashboard/cli_tools executable with mixed trust + the right
noteKey. Updated the two pre-existing tests that asserted the OLD behaviour
(dashboard/cli perception_only on codex_runtime) — they now assert the
promoted state. Also synced the static `CAPABILITY_EXECUTABLE_RUNTIMES` map.
Per Codex review's explicit ask: the "待真账号 smoke" wording stays in the
op7418#31 capability table — this commit fixes the inconsistencies, but the
real-account end-to-end smoke for natural-conversation triggering + write
approval card + Deny blocking is still owed by the user.
Full unit suite 3045/3045. Live route: bad workspace still 403 (auth gate
intact); tools/list subsets unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Codex review 认可方向,按 5 条反馈修订(纯文档,无代码):
- Phase A 增"开工前核验"(Opus 4.8 官方 model id / context window / thinking·effort / 1M beta,不臆测)
- Phase A 实现范围增"泛化 Opus 4.7 专属逻辑"(isOpus47Model / OPUS_4_7_PATTERN / applyContext1mBeta /
effort 门控 / claude-client sanitizer,配回归测试)—— catalog 显示 ≠ 请求正确
- OpenRouter Opus 4.8 改 deferred(不臆测 slug),首轮只接 Anthropic direct
- opus 别名 / 默认先不动(仍 4.7),只新增显式 claude-opus-4-8,切换待 smoke 后用户拍板
- Phase D 拆 D0/D:D0 把 apply-discovery-diff 全量 flake + no-verify 事件记入 tech-debt op7418#30(本提交即 D0);
D 建议先于 A/B/C,代码 phase 不再靠 --no-verify
- Open Questions op7418#1/op7418#2 据上述决议收敛
本提交纯文档;pre-commit 同样因 apply-discovery-diff 全量 flake 用 --no-verify,已确认 docs-drift 绿。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
v0.56.x 计划 Phase 1:建立稳定性治理入口,并用当前源码重新核验 Notion/issue 列出的
7 个 issue(不采信 issue 自述根因)。
GitHub 侧(已在仓库生效,非本 commit 内容):
- 创建 milestone op7418#1「v0.56.x Stability / Trust」。
- 创建 9 个治理 label:P0-crash-or-interrupt / P0-data-loss-risk / P1-runtime-session /
P1-context / P1-file-reference / P1-installer-update / P1-performance / needs-repro /
v0.57+ parking-lot。
- 给 op7418#626/op7418#628/op7418#629/op7418#632/op7418#633/op7418#634/op7418#635 按复核结论打 milestone + 优先级 label。
本 commit 文件:
- .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml:bug 表单强制必填
版本/OS/runtime/provider-model/可复现/复现步骤/期望vs实际 + 影响面勾选;feature
表单注明 v0.56.x 冻结新功能 → v0.57+ parking-lot;config 关闭空白 issue + 冻结说明
与 Discussions 入口。
- .github/PULL_REQUEST_TEMPLATE.md:Summary / Repro+root cause / Changes / Tests /
Screenshots-logs / 自查清单(链到 CLAUDE.md 与 AGENTS.md,不复制维护)。
- .github/TRIAGE.md:对外冻结说明、label 体系、issue/PR triage 规则、自动化候选。
- v0.56.x-stability-trust.md:标 Phase 0 完成 + 新增「2026-06-19 Claude Code 源码复核」
表(7 issue 逐条 file:line 证据)。关键复核结论:
* op7418#632 ">100%" 确认是未 clamp 的 ratio*100 显示 bug(RunCockpit.tsx:169 等),分母
contextWindow 不可靠;"跨会话串" 源码不成立。
* op7418#629 空 assistant 已防护,残留真实 gap:is_error result 路径不清坏 sdk_session_id
(claude-client.ts:1908 先置 resultEmitted)。
* op7418#635 截图-only,最强候选 = SDK runtime 无自生成 keepalive(claude-client.ts:1956),
慢 proxy 静默 >330s 被 idle abort(B-019)。
* op7418#628 确认真实风险:@file origin path 在 MessageInput.tsx:161 丢失,body.mentions[]
送达但 route.ts 从不消费 → 写 .codepilot-uploads 副本,AI 改副本。
* op7418#634 根因不成立——5 个 notify/schedule 工具均注册(builtin-tools/index.ts:250),
issue 引用的 UI 串不在当前源码(疑旧版);附带 Plan 模式 list_tasks 泄漏。
* op7418#626 polling 排除(8h 间隔),候选 animate-pulse × backdrop-filter 重绘。
* op7418#633 mac 无法复现;NSIS-only + 未签名 + 无 portable + CI 不验安装启动。
- issue-tracker.md:新增「v0.56.x 治理 issue」看板索引表(指向 plan 复核表,不重复分析)。
验证:docs-drift 通过;npm run test(hook)。Phase 1 验收(milestone/labels/模板/冻结
说明就绪)达成。下一步 Phase 2:按复核结论修 chat 主链路(上下文百分比语义、context-cost
不阻断发送、Codex 多模态发送、发送后清草稿)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…e 2 op7418#1)
Signal: issue op7418#632 报"上下文 >100% / 假百分比 / 压缩后跳变";Phase 1 源码复核确认是
真实显示 bug("跨会话串"不成立)。
Triage(当前源码): 用量百分比 = usage.ratio*100,在 RunCockpit.tsx 与
RunCockpitPopoverContent.tsx 两处直接渲染、未封顶;usage.ratio = used / contextWindow,
而 contextWindow 来自 sdkContextWindow ?? latestSdkContextWindow ?? catalogContextWindow
(useContextUsage.ts)。很多第三方 proxy 不上报 context_window → 落到静态 catalog 兜底
(一个猜测值),used 又会在压缩后跳变 → 百分比蹦到 200%/500%。根因是"拿不可信的分母
算百分比",不是上下文真的超了。
Fix:
- useContextUsage.ts: 新增 ContextUsageData.contextWindowTrusted —— 仅当 SDK/上游真实
上报窗口时为 true(catalog 兜底不算)。三个 return 分支(baseline / snapshot / no-baseline)
都按各自来源正确赋值。不可信时不把窗口喂给 buildContextUsageBreakdown,dot-matrix 退回
按已用 token 的构成比例,不编造容量。
- RunCockpit.tsx: hasFullCtx 增加 && usage.contextWindowTrusted —— 不可信时自动落到既有的
绝对已用 token 显示(触发按钮)/ showUnknownCapacityBlock 分支(浮层,已测试的"容量未知"
路径)。百分比文案 clamp ≤100%。
- RunCockpitPopoverContent.tsx: 浮层 header 百分比同样 clamp ≤100%(防可信窗口被 used 短暂
超过时仍蹦 >100%)。
语义验收: 输入框右下角不可信时只显示已用绝对值;浮层不可信时只显示已用 + 不同种类构成
比例(无百分比/remaining/unused/假总量);可信时百分比封顶 100%。
Verify: typecheck 通过;context-window-trusted.test.ts 6 条 source-pin + 既有
run-cockpit-unknown-capacity / context-dot-matrix / context-usage-walk / context-breakdown
全绿;全量单测 3366/3366。未做:真实 untrusted-window provider 会话的 CDP 视觉走查
(fix 把 untrusted 路由到既有已发布的"容量未知"分支,风险低;视觉走查列为后续)。
Guardrail: context-window-trusted.test.ts 钉死 trusted 派生只认 SDK 来源、不可信时不喂窗口、
hasFullCtx 必须 gate trusted、两处显示 clamp ≤100%,防回退到"拿 catalog 当真实分母算百分比"。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Signal: Codex 复核 fixop7418#1(9ea29a4)后发现 P2 残留——文字已改成"只显示已用 token",
但输入框右下角触发按钮旁的 mini dot-bar 仍用 200K 兜底画出"用了多少/还剩多少"的容量
暗示,与"拿不到总长度就不显示容量"及 commit message 的"不编造容量"不一致。
Triage(当前源码): ContextDotMatrix.tsx 有 FALLBACK_CONTEXT_WINDOW=200_000,
minCellsPerKind=0(mini-bar)在窗口未知时用它当分母(:88);RunCockpit.tsx:200 的触发
按钮无条件渲染这个 mini-bar。所以即使 9ea29a4 把文字降级为绝对已用,小条仍画假容量。
minCellsPerKind=0 全仓只有 RunCockpit 触发按钮一个调用方。
Fix:
- RunCockpit.tsx: mini-bar 用 {hasFullCtx && (...)} 包裹——仅在可信窗口下渲染容量小条;
不可信时触发按钮只剩绝对已用 token 文本(贴合"输入框右下角只显示已用数值")。
- ContextDotMatrix.tsx: 删除 FALLBACK_CONTEXT_WINDOW(200K)。窗口未知时两种模式都按
used+pending 分配(构成视图,非容量%),不再编造容量。
Verify: typecheck 通过;context-dot-matrix.test.ts 旧的"unknown mini-bar 用 200K 兜底
(filled<=2)"语义改为新的"used 构成(filled>=8)";context-window-trusted.test.ts 加 2 条
guardrail(mini-bar gate 在 hasFullCtx + 源码无 200K 兜底残留);全量单测 3368/3368。
Guardrail: 两条 source-pin 钉死"触发按钮 mini-bar 必须 gate 在 hasFullCtx"且"ContextDotMatrix
不得再出现 FALLBACK_CONTEXT_WINDOW/200_000",防回退到拿假容量画小条。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户复核 fixop7418#1 后明确显示格式:输入框右下角的上下文小标,在有可信窗口时显示
"百分比 + 已用上下文"(如 56.6% 452K),没有可信窗口时只显示已用(如 452K),
不单列"剩余"数字。
改动:RunCockpit.tsx 触发按钮 ratioText 的可信分支由 "{pct}%" 改为
"{pct}% {used}"(1 位小数,匹配用户给的 56.6% 示例);不可信/无数据分支不变。
context-window-trusted.test.ts 的 clamp pin 扩为同时断言"百分比 + 已用"格式。
验证:dev 应用热重载干净(✓ Compiled);context-window-trusted 8/8;typecheck(hook)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…llow-up)
Signal: 用户在运行的应用里看到 GLM-5-turbo(Claude Code/Native 会话)仍显示总上下文
200K,指出"这并不是我们知道的部分"。fixop7418#1 本应让 catalog 静态值不可信、只显示已用。
Triage(当前源码,用户 review 驱动): agent-loop.ts:641-651(Native)在 token_usage
没有 context_window 时,从静态 catalog 填 totalUsage.context_window = getContextWindow(modelId)
(GLM-5-turbo 在 catalog 是 z.ai 核实的 202752)。而 context-usage-walk 把
token_usage.context_window 当作 SDK 实报窗口读,fixop7418#1 的 contextWindowTrusted 据此判可信
→ catalog 猜测被"洗白"成可信 → Native GLM 显示 200K。即上游 mutator 打败了 helper 修复
(feedback_fix_all_consumers)。claude-client(Claude Code)只从 SDK modelUsage 写,不洗白;
ContextUsageIndicator 是死组件(无人 import)。
Fix: 删掉 agent-loop 的 catalog 洗白。Native 无 runtime 实报时 context_window 留空 →
useContextUsage 回落 catalog 为不可信 → 只显示已用绝对值,不再有假百分比/假总量。
仅对新 turn 生效(历史消息已存的 context_window 不改写,遵守不改用户数据;旧会话发新消息后转为已用-only)。
Verify: typecheck;context-window-trusted.test.ts 新增 pin 断言 agent-loop 不再
`.context_window = catalogWindow`;该文件 9 测 + agent-loop-error-event 全过。运行中 dev 应用
server 重编译干净(Native GLM 需发新消息验证)。
Guardrail: source-pin 防 Native 再把 catalog 洗进 SDK-authoritative 字段。
设计记录(用户批准"先记计划再实现"): v0.56.x 计划写入 context-window 来源优先级修订设计
(runtime 实报 > provider 配置 contextWindow > 压缩阈值 > catalog 不可信)+ 跨 Runtime 用户
配置源(op7418#1,待实现) + 显示分母对齐压缩阈值(op7418#3,待实现)。本提交是设计第一步(去洗白)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
把"为什么 GLM 显示 200K + 窗口来源该怎么改"写成评审稿放进 v0.56.x Phase 2,按
外部事实 / 本地证据(file:line) / 推断与设计三层分写,供 Codex 核实。
要点:
- Agent SDK v0.2.111 的 modelUsage.contextWindow(sdk.d.ts:945)是未文档化字段,来自
SDK 内置模型目录而非 API;第一方可靠、第三方(经 base_url 的 GLM)返回通用默认值;
无 SDK 设置可覆盖;Anthropic 建议自维护窗口表。
- 实测 GLM 会话 token_usage.context_window=200000 ≠ 本地 catalog 202752,证实来自 SDK
默认而非 catalog/Native 洗白;该会话是 Claude Code(故上一提交的 Native 修复不覆盖它)。
- 修订设计:窗口来源优先级 = 用户覆盖 > 已核实 catalog/provider 配置 > SDK(仅第一方) >
只显示已用;第三方忽略 SDK 默认值;跨 Runtime;显示分母对齐压缩阈值(op7418#3)。
- 列出待定决策(已核实优先 vs 纯手动) + 给 Codex 的 5 个核实点。
未改任何产品代码(纯文档)。op7418#1/op7418#3 实现待 Codex 核实后进行。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
Codex 复核设计稿后订正(实现 op7418#1/op7418#3 前必须):
- A:原"官方文档不记载 contextWindow/maxOutputTokens"不准 → 改为 SDK TypeScript
reference 有字段定义,是 cost-tracking 指南未解释来源/可信度。
- B/C:原"catalog 202752 比 SDK 200000 更准且 z.ai 核实"站不住 → z.ai 官方写
200K/128K,catalog 该条来源存疑;结论收敛为"SDK 200000 不可作为 provider 实报采信",
不延伸到"catalog 更准";另标记需单独核 model-context.ts:42 的真实来源。
- D + 决策日志:统一优先级(消除冲突,旧决策日志把第三方 SDK 又洗白成可信)→
用户手动覆盖 > provider/model 配置且来源已验证 > 第一方 runtime 实报 > 只显示已用;
第三方 SDK contextWindow 默认不可信、无明确来源 catalog 不当可信%显示。
- "Anthropic 官方建议自维护表"未核到原文 → 降级为工程结论。
- 澄清:用户实际看到 200K 的 GLM 会话是 Claude Code(SDK 默认 200000),非 Native 洗白
路径(f79fd54 的 Native 修复有效但治另一条路径)。
- E:决策收敛为一条基线 + 剩余一项请用户定(第一方 SDK 实报是否自动显示百分比)。
Codex 核为真的部分(sdk.d.ts:945 字段、代码写入 token_usage、历史 SDK 窗口被当可信、
Native 洗白已去、显示分母 vs 压缩阈值脱节)保留。纯文档,未动产品代码。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
F 段核实点 op7418#1 还残留旧"官方文档未记载(A)",与已订正的 A 段不一致。改为:
sdk.d.ts:945 的 contextWindow/maxOutputTokens 存在,SDK TypeScript reference 已列,
只是 cost-tracking 指南未解释来源/可信度。纯文档。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
…#632 / Phase 2 ①)
Signal: 用户 GLM-5-turbo(Claude Code 经代理)显示总上下文 200K,且 Codex 核实 SDK 的
modelUsage.contextWindow 来自 SDK 内置目录、对第三方是通用默认值、无 SDK 设置可覆盖。
Triage: claude-client.ts extractTokenUsage 把 SDK modelUsage.contextWindow 无条件写入
token_usage.context_window;walk + fixop7418#1 据此判可信 → 第三方代理(GLM)的 SDK 默认 200000
被当可信显示。Native 的 catalog 洗白已于 f79fd54 去掉;本提交补 SDK 路径。
Fix(Codex 统一口径"第一方 runtime 实报可信、第三方不可信"):
- ai-provider.ts 导出 isFirstPartyAnthropicEndpoint(baseUrl)(空/anthropic.com → 第一方)。
- extractTokenUsage 增 trustContextWindow,仅 true 时写 context_window;两个调用点都传
isFirstPartyAnthropicEndpoint(resolved.provider?.base_url)。第三方(自定义 base_url,如 GLM)
→ 不写 context_window → useContextUsage 回落 catalog 为不可信 → 只显示已用。
效果 + 边界: 第一方 Anthropic 继续显示百分比+已用;第三方代理新 turn 起只显示已用。
仅对新写入生效(历史消息已存的 context_window 不改写,遵守不改用户数据);现有 GLM 会话
仍显示旧值,需新会话/新 turn 验证(walk 会读历史,故旧会话需自然滚动出旧窗口或新建)。
Verify: typecheck;extract-token-usage-context-window.test.ts 增 2 pin(gate + 两调用点传
第一方判别);全量 3371/3371。
Guardrail: source-pin 钉死 context_window 写入受 trustContextWindow 门控 + 两调用点必须传
isFirstPartyAnthropicEndpoint,防回退到无条件信任第三方 SDK 窗口。
remaining(Phase 2 ①/③ 未完): provider/model 配置窗口作为最高优先可信源(用户覆盖) + 渲染层
对现有会话按第一方 gate(治旧会话) + op7418#3 显示分母对齐压缩阈值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
计划文档状态审计修正(决策日志准、但概览层过期):
- frontmatter 状态行:📋 待接手 → 🚧 Phase 0/1 已完成、Phase 2 进行中。
- 「状态总览」表:Phase 1 待开始 → ✅ 已完成(2026-06-19);Phase 2 待开始 → 🚧 进行中。
- Phase 2 加进度 note:Composer/Context 主链路 op7418#1op7418#5 全部收口(含 commit + op7418#3 真实
Codex 冒烟回复 circle);Session/Stream cluster op7418#629/op7418#635 + 终态原因码 + 压缩回滚
+ 诊断导出字段待续。
- Phase 2 执行清单 4 项已完成项 [ ]→[x](上下文 UI 语义 / context-cost 去阻断 /
Codex 多模态发送 / 发送后草稿清理)。
CLAUDE.md 执行计划段新增「完成即回写进度(与 Codex 对齐协作)」:任一 Phase/子项做完
必须立即回写三处且一致——执行清单勾选 / 状态总览表+frontmatter / 决策日志(commit
+验证结论);Claude 实施+回写、Codex 审查+维护;三者不一致视为状态失真须先对齐。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
打回上一条状态同步的一处失真:我把 op7418#4/op7418#5「发送后内容残留」标成完成(checklist [x] +
进度 note 列为 done),但同一文档决策日志(2026-06-20 条)已写明用户再次确认"内容已发出
但文本仍残留输入框"、op7418#615 source-pin 不覆盖该症状、不能算闭环——状态表/清单与决策日志
自相矛盾,违反刚加的"三者必须一致"。
修正(与决策日志对齐):
- checklist「复现并修发送后内容残留」[x] → [ ],标注"待复核/待修复(用户 2026-06-20 再报)"。
- Phase 2 进度 note:拆分——op7418#4/op7418#5 仅失败保留有基础修复(op7418#615),发送成功后文本残留待复核;
note 标题从"主链路已收口"改为"op7418#1op7418#3 收口、op7418#4/op7418#5 待复核";待续列表补回 op7418#4/op7418#5(重新打开)。
- op7418#2 context-cost 非阻断保持完成(checklist [x] + note)不变。
后续修 op7418#4/op7418#5 时重点:PromptInput 受控/非受控清空边界、setInputValue('') 与
controller.textInput.clear() 是否同源、成功 accepted 后 remount/local draft 恢复、
badge/confirm/image 分支与普通 Enter 分支是否一致(决策日志已记排查方向)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
按"完成即回写进度"规则同步三处:
- checklist「复现并修发送后内容残留」[ ]→[x],标注已修 + CDP 验证 + 根因/修法(de123df)。
- Phase 2 进度 note:op7418#1op7418#5 全部落地;op7418#4/op7418#5 从"待复核"改为"已定位+修复"(含根因/CDP 结论);
待续列表移除 op7418#4/op7418#5、只留 Session/Stream cluster。
- 决策日志加同日条目:CDP 埋点定位 = 首条消息 accept 布局翻转 remount composer、inputValue
从 sessionStorage 草稿重读;修法 = accept 处清草稿;3401/3401 + CDP 文本/图文首条 800ms 即清。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户在浏览器实测不残留、仅桌面 App 残留 → Claude 协助完整重启 electron:dev(kill 整棵
进程树 + 释放 3000 + 后台重启)→ 用户在重启后真实 App 验证发送即清空 → op7418#4/op7418#5 闭环。
根因:de123df(page.tsx accept 处清首条草稿)一直是对的;用户残留是 Electron dev 没把
page.tsx 改动热更新进 renderer、窗口刷新无效,得整进程重启。这解释了全程「Claude CDP
浏览器清、用户残留」的矛盾——不是 Electron 行为差异,是构建新鲜度差异(Claude 浏览器硬刷
过有修复、用户 Electron 旧构建没有)。
回写:checklist [x](用户真实 App 验证)、进度 note op7418#1op7418#5 全闭环、验收去 ⚠️、决策日志加
闭环条目 + 教训(UI 修复在桌面 App 验证必须整重启 electron:dev)。Codex P1(prefill/
initialValue 回灌)仍是 de123df 的真实独立漏洞、值得单独补,与本次残留无关。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
纯文档同步,无代码改动。目的:让下一个进程打开文档时不从旧状态误判进度。
三处状态表此前已标 Phase 0/1 ✅、决策日志也已确认完成,唯独执行清单 checkbox
与 README 索引、issue-tracker op7418#632 仍停在旧值——三处不一致即状态失真,本次对齐。
README.md:
- v0.56.x 索引行状态列 "📋 待 Phase 0 收束" → "🚧 Phase 0/1 ✅;Phase 2 进行中
(Composer/Context 主链路 op7418#1op7418#5 闭环,Session/Stream cluster op7418#629/op7418#635 待续)",
追上 plan frontmatter 与决策日志。
v0.56.x-stability-trust.md:
- Phase 0 执行清单 8 项 [ ]→[x],逐条带回溯(3360/3360、dd4ead4、b853188/2de9c2b)。
A2 计时器项如实标注:按 keyed-remount 构造性消除 + 截图不可判别记录入 Smoke Ledger,
非逐帧视觉确认(反假数据,不谎称做了视觉确认)。
- Phase 1 执行清单 5 项 [ ]→[x],带回溯(milestone op7418#1 / 9 labels / .github/TRIAGE.md)。
issue-tracker.md:
- op7418#632 状态 "🔴 待修" → "🟡 假%已修,item3 分母对齐待续"。核心显示 bug(假百分比/>100%)
已由 effective-base-URL 写入 gate + 渲染期 trusted gate + clamp 修复并经真实 GLM
会话验证;item3(显示分母对齐压缩阈值)是独立待续阶段,故标部分修复而非已修复。
- 顶部"最后更新"同步到 2026-06-26 + op7418#632 同步说明。
验证:git diff 确认仅 3 文档、16/16 行 checkbox 与状态文字,无代码/意外文件。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
- docs/research/ai-sdk-7-toolloop-parity-gaps.md: 新增「Phase 5 处置」节,全部 gap
收口——P1×3 关闭(op7418#1/op7418#2 补偿由 parity 8/8 复跑锁定;op7418#3 降级论证:Phase 4 已证
approval HMAC 不需要 SDK toolApproval 停机语义,维持 in-execute 路线),
P2/P3 关闭或 backlog(op7418#4/op7418#5 列为替换路线前置条件,op7418#7 归档 tech-debt op7418#49op7418#8 有 Phase 5 新实证)
- scripts/smoke-ai-sdk7-phase5-decision.ts: 新增决策门对照 smoke——prod runAgentLoop
与 POC runToolLoopAgentPoc 用同一 AgentLoopOptions 逐场景对照(长文本 / approval
批准 / approval 拒绝 / abort→continue),机械比较归一化事件序列 + 尾部契约 +
usage 存在性;DB 只读、数据目录隔离、输出全 scrub。探针注意:approval 批准分支
用 printf(echo 命中 permission-checker 自动放行规则不会触发 ask)
- docs/exec-plans/active/_smoke-evidence/ai-sdk7-phase5-decision-smoke.json:
OpenRouter 真实渠道 4/4 场景 contractMatch=true(input_tokens 逐场景完全相同,
tool_result 逐字相同,中断轮双侧 done 收尾、同 session 续发一次通过);
凭据形态 grep=0
- docs/research/ai-sdk-7-adoption-decision.md: 新增采用决策文档——结论 partial
(依赖升级 go / provider 能力 capability-gated go / Phase 4 外围能力 go /
@ai-sdk/mcp 与默认 loop 替换 no-go-现在),四层 rollback plan(能力开关→
wrapper→runtime switch→known-good version),每项结论标注 Phase 1-5 证据来源;
默认 Runtime 切换留人类闸门
- docs/exec-plans/tech-debt-tracker.md: 新增 op7418#49(tool-error part 被两条 loop
一致吞掉的既有 UX 债,独立于采用决策)
- docs/exec-plans/active/ai-sdk-7-runtime-loop-adoption.md: Phase 5 状态回写 +
决策日志 + Smoke Ledger / Loop Ledger 各一行
- docs/research/README.md: 索引新增决策文档条目
验证: npm run test 3598/3598 全绿;smoke 4/4 contractMatch(1 个 fix cycle 收敛,
两处均为脚本层问题非 loop 差异);src/ 零改动(默认 Runtime/聊天路径零变化)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
用户批准 partial(2026-07-04, run issue op7418#10): 采用 ai@7/@ai-sdk/* 依赖升级、
provider 参数能力 capability-gated、openai-chat image wrapper、timeout 原因码/
approval HMAC/trace 脱敏四件套(默认值经用户确认); @ai-sdk/mcp adapter 与
ToolLoopAgent 默认 loop 替换均不采用(留实验路径)。发版前保留官方一方 key
smoke gate。冲突仅 ai-sdk-7 计划决策日志一处,union 双方条目解决。
五个 phase 全部经 hands-off loop 完成并 Codex accepted(issues op7418#1/op7418#6/op7418#7/op7418#8/op7418#10)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
canblmz1 pushed a commit to canblmz1/CodePilot that referenced this pull request Aug 28, 2026
…lease
prefix-safe-json 0.2.0 -> 0.4.3 (exact). 0.4.3 is a security patch
(GHSA-3xpw-9694-2xxp) fixing three root causes in the AI SDK adapter/gate
this integration depends on:
1. AiSdkStreamAdapter.push() used to silently drop every raw event once
it had already observed its own terminal, so late/contradictory
evidence for a call never reached the coordinator at all.
2. takeDecision() used to read a decision snapshot frozen at finish()
time instead of the coordinator's live diagnostics, so evidence
recorded after finish() but before that call's authority was consumed
was never consulted.
3. A raw event carrying conflicting id/toolCallId used to silently
prefer id instead of failing the stream closed.
No public API change - createAiSdkExecutionGuard()/push()/finish()/
takeDecision() and the ExecuteDecision/NonExecutableDecision shapes this
integration reads (action, toolCallId, reason) are unchanged, confirmed
directly against the installed package's .d.ts, not assumed.
Verified against the real 0.4.3 install (resolved version, and lockfile
integrity hash, both confirmed exactly 0.4.3):
- npx tsc --noEmit (full project): clean, 0 errors.
- src/__tests__/unit/execution-guard.test.ts: 16/16 passing, identical
to the 0.2.0 result.
Adds src/__tests__/unit/execution-guard-post-terminal-authority.test.ts,
answering the actual question this bump exists to answer: does this
integration's own code exercise the fix, not just "does the library
still pass its own tests." resolvePendingExecutions() in
execution-guard.ts reads `decisions` directly off guard.finish()'s own
return value in the same statement - it never calls takeDecision().
A fresh guard is created per step and is never reused once its finish()
is read, so there is no async gap between this integration's own
finish() call and its own decision consumption for GHSA-3xpw-9694-2xxp's
literal finish()-to-takeDecision() window to open in here.
What is live in this integration is root cause op7418#1: whether a
late/contradicting raw event that arrives before a step's own
resolvePendingExecutions() call - anywhere in that step's fullStream -
correctly revokes authority instead of being silently dropped by the
adapter. The new test proves that directly, through this repo's real
execution-guard.ts functions (createStepGuard/registerDeferredExecution/
resolvePendingExecutions - the exact call path agent-loop.ts uses), plus
a control case confirming the fix does not overcorrect a genuinely clean
step. A second test exercises the raw prefix-safe-json library
(createAiSdkExecutionGuard directly, real push/finish/takeDecision, no
synthetic decision object) to confirm the literal advisory scenario is
fixed at the library level.
package-lock.json regenerated with `npm install prefix-safe-json@0.4.3
--save-exact`, not hand-edited.
Sign up for freeto 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.

2 participants

@xuxu777xu@op7418