Skip to content

fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题 - #2

Closed
arthurlee116 wants to merge 1 commit into
op7418:mainfrom
arthurlee116:fix/build-rmsync-recursive
Closed

fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题#2
arthurlee116 wants to merge 1 commit into
op7418:mainfrom
arthurlee116:fix/build-rmsync-recursive

Conversation

@arthurlee116

Copy link
Copy Markdown

问题

执行 npm run electron:build 时,scripts/build-electron.mjs 在解析 .next/standalone/.next/node_modules/ 中的符号链接时报错:

Error: Path is a directory: .next/standalone/.next/node_modules/better-sqlite3-90e2652d1716b047
at Object.rmSync (node:fs:1236:18)
at resolveStandaloneSymlinks (file:///...CodePilot/scripts/build-electron.mjs:18:12)

部分条目(如 better-sqlite3-90e2652d1716b047)是指向目录的符号链接,fs.rmSync() 在未传入 { recursive: true } 时会抛出 ERR_FS_EISDIR 错误。

修复

fs.rmSync() 添加 { recursive: true, force: true } 参数。

CopilotAI review requested due to automatic review settings February 7, 2026 07:00

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

该 PR 修复 Electron 构建脚本在处理 Next.js standalone 输出中的“指向目录的符号链接”时,因 fs.rmSync() 未开启递归删除而报错的问题,保证 npm run electron:build 可正常执行并为后续 electron-builder 打包准备好可复制的目录结构。

Changes:

  • 为删除 standalone 目录下的符号链接时的 fs.rmSync() 增加 { recursive: true, force: true } 参数,避免遇到目录型符号链接时报 ERR_FS_EISDIR

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@op7418

Copy link
Copy Markdown
Owner

Thanks for the fix! This change was already included in PR #7 which has been merged. Closing as duplicate.

@op7418op7418 closed this Feb 7, 2026
op7418 pushed a commit that referenced this pull request Mar 2, 2026
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 #2 补充连续水位推进机制
- 新增决策 #9(图片接收)和 #10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 1, 2026
在用户本机做隔离 POC + 端到端 POC(findCodexBinary 解析到的 .app codex
0.133.0 + 真实 ~/.codex),证伪了原日志推断「xhigh 配置让 app-server 挂掉」:
- .app codex 0.133.0 原生接受 model_reasoning_effort=xhigh(initialize +
model/list 全 OK,不退出);对 max/垃圾值只警告不致命。
- 端到端:当前二进制 + 真实含 xhigh 的 ~/.codex → initialize OK + model/list
返回 6 个真实模型 → 用户 Codex 现在就是通的。
- 日志里失败的是 /opt/homebrew/bin/codex(现已卸载),更旧/更严、只认 4 档且
把配置反序列化失败当致命退出。login shell PATH 已无任何 codex,打包 app 只会
解析到 .app 0.133.0。
修正:
- 顶部新增「POC 实测修正」权威段(外部事实 pin 0.133.0 / 仓库 file:line / 推断三层)。
- 标注下方「日志确认」claim #2 与修复表 row1 为已更正,指向新段,保留推断留痕。
- 修复方向改判:立即动作=重启 CodePilot(不用改 config);P0=app-server init 期
退出时立即 reject pending init(不等 30s,这才是三症状变慢的真因);P1=clamp
CodePilot 发给 Codex 的 effort;否决 spawn -c 覆盖(no-op+覆盖用户配置+不可验证)。
- 同步 research/README.md 索引。
op7418 added a commit that referenced this pull request Jun 28, 2026
f99edbb 把侧栏"需要批准"徽章的清理放在 useStreamSubscription,但它依赖当前会话的
ChatView 挂载:用户切到别的会话后该 hook 退订(useStreamSubscription cleanup),
后续 timeout 的 snapshot-updated 不再触发清理。AppShell 的全局 handler 会从所有
active stream 重算 pendingApprovalSessionIds(Set 源,已正确排除超时),但没有清全局
单值 pendingApprovalSessionId;侧栏 needsApproval 仍 OR 这两个来源(ChatListPanel)
→ 切走后单值残留,徽章不灭直到 stream 结束。
改动:
- src/components/layout/AppShell.tsx:全局 stream-session-event handler 改为接收
event,重算 approvals 后,若 pendingApprovalSessionId === detail.sessionId 且该
session 不在 approvals,就清单值(函数式更新 + 守卫)。这不依赖 ChatView 挂载
(覆盖"切走后超时"),且精确——不会误清仍 pending 的 peer 或 /chat inline 新会话。
- src/hooks/useStreamSubscription.ts:移除 f99edbb 那条无条件清理(已被 AppShell
完整且更安全地取代;无条件版在分屏下会误清 peer 的全局单值,虽被 Set 源掩盖)。
- 入口1(/chat inline)不走 stream-session-manager 的 window event,保留 page.tsx
自身 permission_resolved case 的清理。
验证:tsc --noEmit exit 0;全量单测 3360/3360。React 状态接线无 hook-test harness,
靠 typecheck + AppShell Set 源独立保护 + 代码审查。
guardrail:徽章单值清理收敛到 AppShell 全局 handler 这一处(不依赖任何 ChatView
挂载),与 Set 源对超时 / resolved 态一致。
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: 用户反馈 + 计划 Phase 2——图片/文件等普通上下文过大时弹"上下文太多,发送前
请确认"的阻断式横幅,必须再点一次才能发;图片发送被二次确认卡住。
Triage(当前源码): run-checkpoint.ts 的 context-cost-change reason 设了
requiresConfirm:true + confirm-context-cost 动作;两个聊天入口(page.tsx:288 /
ChatView.tsx:368)都用 `checkpointReasons.filter(r => r.requiresConfirm)` 派生
blockingReasonIds,MessageInput:511 据此 throw 'run-checkpoint-blocked' 阻断发送。
即估算型上下文大小被做成了二次确认阻断——违反"非破坏性、用户主动发起的发送不得因
估算风险被阻断"。注:context-cost 是当前唯一的 requiresConfirm reason。
Fix:
- run-checkpoint.ts: context-cost-change 去掉 requiresConfirm + confirm 动作 →
纯 info-tone 非阻断 heads-up,永不进入 blockingReasonIds,图片/文件首个 Enter 即发。
- i18n en/zh: 文案去掉"Confirm before sending / 发送前请确认"的确认框架,改为纯提示。
- 阻断/bypass 基建(blockingReasonIds + MessageInput 'run-checkpoint-blocked' throw +
PromptInput 截图保留契约 + confirm→bypass 桥)**保留**:它保护任何被拒提交、且按计划
留给未来真实危险动作(写/删/执行/提权——那些走权限系统)。两入口的 confirm-context-cost
处理器改注释为 dormant,逻辑不动。
语义验收: 普通上下文过大只出非阻断提示;阻断只留给真实危险动作;图片发送不再二次确认。
Verify: typecheck 通过;run-checkpoint.test.ts 把"requiresConfirm=true + confirm action"
断言翻为"info-tone 非阻断、无 requiresConfirm、无 action",scope-guard 的"每个 reason 必有
action"放宽为"context-cost info-only 无 action、其余有";run-checkpoint-blocking.test.ts
更新前提(无 reason 当前 requiresConfirm)+ bypass-machine 样例 id 改假想值,保留通用机器与
截图保留契约;全量单测 3368/3368。
Guardrail: run-checkpoint.test.ts 钉死 context-cost 非阻断(notEqual requiresConfirm true
+ action undefined),防回退到把估算上下文做成阻断确认。
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 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>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 op7418#2 补充连续水位推进机制
- 新增决策 op7418#9(图片接收)和 op7418#10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <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
… 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
[P1] /api/providers/models route: DEFAULT_MODELS.sonnet + ENV_ALIAS_TO_UPSTREAM.sonnet
claude-sonnet-4-20250514 → claude-sonnet-4-6(API 层 op7418#23 之前未闭环)
[P1] /api/media/jobs/plan fallback + /api/skills/search MODEL_MAP: 旧 Sonnet → claude-sonnet-4-6;
skills/search 的 opus(4.6) / 旧 haiku 一并修正 → claude-opus-4-7 / claude-haiku-4-5-20251001
[P2] isOpusAdaptiveThinkingModel regex /opus-?4-?[78]/ → /opus-?4[-.]?[78]/,同时匹配 dotted
OpenRouter slug anthropic/claude-opus-4.8(不再依赖"dotted 不走此 sanitizer"的假设)
[P2] post-refactor-cleanup.md Open Question op7418#2:OpenRouter Opus 4.8 不再写 deferred(已接入)
测试: opus-4-8-sonnet-4-6.test.ts 扩到 18 断言(+dotted slug +路由层 op7418#23 source-pin 含 skills opus/haiku)。
验证: tsc exit 0、targeted 18/18、业务代码无 claude-sonnet-4-20250514 残留。
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
用户 2026-05-29 跑通三条真实凭据 smoke(Smoke Ledger 已记):
- OpenRouter Opus 4.8 (opus-4-8 → anthropic/claude-opus-4.8): OPENROUTER_OPUS48_OK
- Anthropic direct Opus 4.8 (Claude Code 账户): OPUS48_CLAUDE_ACCOUNT_A/B_OK
- Sonnet 4.6 op7418#23 反例路径: SONNET46_SMOKE_A/B_OK
状态表 Phase A → 完成;Open Question op7418#2 smoke 标已通过。
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
在用户本机做隔离 POC + 端到端 POC(findCodexBinary 解析到的 .app codex
0.133.0 + 真实 ~/.codex),证伪了原日志推断「xhigh 配置让 app-server 挂掉」:
- .app codex 0.133.0 原生接受 model_reasoning_effort=xhigh(initialize +
model/list 全 OK,不退出);对 max/垃圾值只警告不致命。
- 端到端:当前二进制 + 真实含 xhigh 的 ~/.codex → initialize OK + model/list
返回 6 个真实模型 → 用户 Codex 现在就是通的。
- 日志里失败的是 /opt/homebrew/bin/codex(现已卸载),更旧/更严、只认 4 档且
把配置反序列化失败当致命退出。login shell PATH 已无任何 codex,打包 app 只会
解析到 .app 0.133.0。
修正:
- 顶部新增「POC 实测修正」权威段(外部事实 pin 0.133.0 / 仓库 file:line / 推断三层)。
- 标注下方「日志确认」claim op7418#2 与修复表 row1 为已更正,指向新段,保留推断留痕。
- 修复方向改判:立即动作=重启 CodePilot(不用改 config);P0=app-server init 期
退出时立即 reject pending init(不等 30s,这才是三症状变慢的真因);P1=clamp
CodePilot 发给 Codex 的 effort;否决 spawn -c 覆盖(no-op+覆盖用户配置+不可验证)。
- 同步 research/README.md 索引。
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
b853188 把侧栏"需要批准"徽章的清理放在 useStreamSubscription,但它依赖当前会话的
ChatView 挂载:用户切到别的会话后该 hook 退订(useStreamSubscription cleanup),
后续 timeout 的 snapshot-updated 不再触发清理。AppShell 的全局 handler 会从所有
active stream 重算 pendingApprovalSessionIds(Set 源,已正确排除超时),但没有清全局
单值 pendingApprovalSessionId;侧栏 needsApproval 仍 OR 这两个来源(ChatListPanel)
→ 切走后单值残留,徽章不灭直到 stream 结束。
改动:
- src/components/layout/AppShell.tsx:全局 stream-session-event handler 改为接收
event,重算 approvals 后,若 pendingApprovalSessionId === detail.sessionId 且该
session 不在 approvals,就清单值(函数式更新 + 守卫)。这不依赖 ChatView 挂载
(覆盖"切走后超时"),且精确——不会误清仍 pending 的 peer 或 /chat inline 新会话。
- src/hooks/useStreamSubscription.ts:移除 b853188 那条无条件清理(已被 AppShell
完整且更安全地取代;无条件版在分屏下会误清 peer 的全局单值,虽被 Set 源掩盖)。
- 入口1(/chat inline)不走 stream-session-manager 的 window event,保留 page.tsx
自身 permission_resolved case 的清理。
验证:tsc --noEmit exit 0;全量单测 3360/3360。React 状态接线无 hook-test harness,
靠 typecheck + AppShell Set 源独立保护 + 代码审查。
guardrail:徽章单值清理收敛到 AppShell 全局 handler 这一处(不依赖任何 ChatView
挂载),与 Set 源对超时 / resolved 态一致。
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: 用户反馈 + 计划 Phase 2——图片/文件等普通上下文过大时弹"上下文太多,发送前
请确认"的阻断式横幅,必须再点一次才能发;图片发送被二次确认卡住。
Triage(当前源码): run-checkpoint.ts 的 context-cost-change reason 设了
requiresConfirm:true + confirm-context-cost 动作;两个聊天入口(page.tsx:288 /
ChatView.tsx:368)都用 `checkpointReasons.filter(r => r.requiresConfirm)` 派生
blockingReasonIds,MessageInput:511 据此 throw 'run-checkpoint-blocked' 阻断发送。
即估算型上下文大小被做成了二次确认阻断——违反"非破坏性、用户主动发起的发送不得因
估算风险被阻断"。注:context-cost 是当前唯一的 requiresConfirm reason。
Fix:
- run-checkpoint.ts: context-cost-change 去掉 requiresConfirm + confirm 动作 →
纯 info-tone 非阻断 heads-up,永不进入 blockingReasonIds,图片/文件首个 Enter 即发。
- i18n en/zh: 文案去掉"Confirm before sending / 发送前请确认"的确认框架,改为纯提示。
- 阻断/bypass 基建(blockingReasonIds + MessageInput 'run-checkpoint-blocked' throw +
PromptInput 截图保留契约 + confirm→bypass 桥)**保留**:它保护任何被拒提交、且按计划
留给未来真实危险动作(写/删/执行/提权——那些走权限系统)。两入口的 confirm-context-cost
处理器改注释为 dormant,逻辑不动。
语义验收: 普通上下文过大只出非阻断提示;阻断只留给真实危险动作;图片发送不再二次确认。
Verify: typecheck 通过;run-checkpoint.test.ts 把"requiresConfirm=true + confirm action"
断言翻为"info-tone 非阻断、无 requiresConfirm、无 action",scope-guard 的"每个 reason 必有
action"放宽为"context-cost info-only 无 action、其余有";run-checkpoint-blocking.test.ts
更新前提(无 reason 当前 requiresConfirm)+ bypass-machine 样例 id 改假想值,保留通用机器与
截图保留契约;全量单测 3368/3368。
Guardrail: run-checkpoint.test.ts 钉死 context-cost 非阻断(notEqual requiresConfirm true
+ action undefined),防回退到把估算上下文做成阻断确认。
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
- 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>
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.

3 participants

@arthurlee116@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" + '
fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题 by arthurlee116 · Pull Request #2 · op7418/CodePilot · GitHub
Skip to content

fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题 - #2

Closed
arthurlee116 wants to merge 1 commit into
op7418:mainfrom
arthurlee116:fix/build-rmsync-recursive
Closed

fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题#2
arthurlee116 wants to merge 1 commit into
op7418:mainfrom
arthurlee116:fix/build-rmsync-recursive

Conversation

@arthurlee116

Copy link
Copy Markdown

问题

执行 npm run electron:build 时,scripts/build-electron.mjs 在解析 .next/standalone/.next/node_modules/ 中的符号链接时报错:

Error: Path is a directory: .next/standalone/.next/node_modules/better-sqlite3-90e2652d1716b047
at Object.rmSync (node:fs:1236:18)
at resolveStandaloneSymlinks (file:///...CodePilot/scripts/build-electron.mjs:18:12)

部分条目(如 better-sqlite3-90e2652d1716b047)是指向目录的符号链接,fs.rmSync() 在未传入 { recursive: true } 时会抛出 ERR_FS_EISDIR 错误。

修复

fs.rmSync() 添加 { recursive: true, force: true } 参数。

CopilotAI review requested due to automatic review settings February 7, 2026 07:00

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

该 PR 修复 Electron 构建脚本在处理 Next.js standalone 输出中的“指向目录的符号链接”时,因 fs.rmSync() 未开启递归删除而报错的问题,保证 npm run electron:build 可正常执行并为后续 electron-builder 打包准备好可复制的目录结构。

Changes:

  • 为删除 standalone 目录下的符号链接时的 fs.rmSync() 增加 { recursive: true, force: true } 参数,避免遇到目录型符号链接时报 ERR_FS_EISDIR

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@op7418

Copy link
Copy Markdown
Owner

Thanks for the fix! This change was already included in PR #7 which has been merged. Closing as duplicate.

@op7418op7418 closed this Feb 7, 2026
op7418 pushed a commit that referenced this pull request Mar 2, 2026
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 #2 补充连续水位推进机制
- 新增决策 #9(图片接收)和 #10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 1, 2026
在用户本机做隔离 POC + 端到端 POC(findCodexBinary 解析到的 .app codex
0.133.0 + 真实 ~/.codex),证伪了原日志推断「xhigh 配置让 app-server 挂掉」:
- .app codex 0.133.0 原生接受 model_reasoning_effort=xhigh(initialize +
model/list 全 OK,不退出);对 max/垃圾值只警告不致命。
- 端到端:当前二进制 + 真实含 xhigh 的 ~/.codex → initialize OK + model/list
返回 6 个真实模型 → 用户 Codex 现在就是通的。
- 日志里失败的是 /opt/homebrew/bin/codex(现已卸载),更旧/更严、只认 4 档且
把配置反序列化失败当致命退出。login shell PATH 已无任何 codex,打包 app 只会
解析到 .app 0.133.0。
修正:
- 顶部新增「POC 实测修正」权威段(外部事实 pin 0.133.0 / 仓库 file:line / 推断三层)。
- 标注下方「日志确认」claim #2 与修复表 row1 为已更正,指向新段,保留推断留痕。
- 修复方向改判:立即动作=重启 CodePilot(不用改 config);P0=app-server init 期
退出时立即 reject pending init(不等 30s,这才是三症状变慢的真因);P1=clamp
CodePilot 发给 Codex 的 effort;否决 spawn -c 覆盖(no-op+覆盖用户配置+不可验证)。
- 同步 research/README.md 索引。
op7418 added a commit that referenced this pull request Jun 28, 2026
f99edbb 把侧栏"需要批准"徽章的清理放在 useStreamSubscription,但它依赖当前会话的
ChatView 挂载:用户切到别的会话后该 hook 退订(useStreamSubscription cleanup),
后续 timeout 的 snapshot-updated 不再触发清理。AppShell 的全局 handler 会从所有
active stream 重算 pendingApprovalSessionIds(Set 源,已正确排除超时),但没有清全局
单值 pendingApprovalSessionId;侧栏 needsApproval 仍 OR 这两个来源(ChatListPanel)
→ 切走后单值残留,徽章不灭直到 stream 结束。
改动:
- src/components/layout/AppShell.tsx:全局 stream-session-event handler 改为接收
event,重算 approvals 后,若 pendingApprovalSessionId === detail.sessionId 且该
session 不在 approvals,就清单值(函数式更新 + 守卫)。这不依赖 ChatView 挂载
(覆盖"切走后超时"),且精确——不会误清仍 pending 的 peer 或 /chat inline 新会话。
- src/hooks/useStreamSubscription.ts:移除 f99edbb 那条无条件清理(已被 AppShell
完整且更安全地取代;无条件版在分屏下会误清 peer 的全局单值,虽被 Set 源掩盖)。
- 入口1(/chat inline)不走 stream-session-manager 的 window event,保留 page.tsx
自身 permission_resolved case 的清理。
验证:tsc --noEmit exit 0;全量单测 3360/3360。React 状态接线无 hook-test harness,
靠 typecheck + AppShell Set 源独立保护 + 代码审查。
guardrail:徽章单值清理收敛到 AppShell 全局 handler 这一处(不依赖任何 ChatView
挂载),与 Set 源对超时 / resolved 态一致。
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: 用户反馈 + 计划 Phase 2——图片/文件等普通上下文过大时弹"上下文太多,发送前
请确认"的阻断式横幅,必须再点一次才能发;图片发送被二次确认卡住。
Triage(当前源码): run-checkpoint.ts 的 context-cost-change reason 设了
requiresConfirm:true + confirm-context-cost 动作;两个聊天入口(page.tsx:288 /
ChatView.tsx:368)都用 `checkpointReasons.filter(r => r.requiresConfirm)` 派生
blockingReasonIds,MessageInput:511 据此 throw 'run-checkpoint-blocked' 阻断发送。
即估算型上下文大小被做成了二次确认阻断——违反"非破坏性、用户主动发起的发送不得因
估算风险被阻断"。注:context-cost 是当前唯一的 requiresConfirm reason。
Fix:
- run-checkpoint.ts: context-cost-change 去掉 requiresConfirm + confirm 动作 →
纯 info-tone 非阻断 heads-up,永不进入 blockingReasonIds,图片/文件首个 Enter 即发。
- i18n en/zh: 文案去掉"Confirm before sending / 发送前请确认"的确认框架,改为纯提示。
- 阻断/bypass 基建(blockingReasonIds + MessageInput 'run-checkpoint-blocked' throw +
PromptInput 截图保留契约 + confirm→bypass 桥)**保留**:它保护任何被拒提交、且按计划
留给未来真实危险动作(写/删/执行/提权——那些走权限系统)。两入口的 confirm-context-cost
处理器改注释为 dormant,逻辑不动。
语义验收: 普通上下文过大只出非阻断提示;阻断只留给真实危险动作;图片发送不再二次确认。
Verify: typecheck 通过;run-checkpoint.test.ts 把"requiresConfirm=true + confirm action"
断言翻为"info-tone 非阻断、无 requiresConfirm、无 action",scope-guard 的"每个 reason 必有
action"放宽为"context-cost info-only 无 action、其余有";run-checkpoint-blocking.test.ts
更新前提(无 reason 当前 requiresConfirm)+ bypass-machine 样例 id 改假想值,保留通用机器与
截图保留契约;全量单测 3368/3368。
Guardrail: run-checkpoint.test.ts 钉死 context-cost 非阻断(notEqual requiresConfirm true
+ action undefined),防回退到把估算上下文做成阻断确认。
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 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>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 op7418#2 补充连续水位推进机制
- 新增决策 op7418#9(图片接收)和 op7418#10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <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
… 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
[P1] /api/providers/models route: DEFAULT_MODELS.sonnet + ENV_ALIAS_TO_UPSTREAM.sonnet
claude-sonnet-4-20250514 → claude-sonnet-4-6(API 层 op7418#23 之前未闭环)
[P1] /api/media/jobs/plan fallback + /api/skills/search MODEL_MAP: 旧 Sonnet → claude-sonnet-4-6;
skills/search 的 opus(4.6) / 旧 haiku 一并修正 → claude-opus-4-7 / claude-haiku-4-5-20251001
[P2] isOpusAdaptiveThinkingModel regex /opus-?4-?[78]/ → /opus-?4[-.]?[78]/,同时匹配 dotted
OpenRouter slug anthropic/claude-opus-4.8(不再依赖"dotted 不走此 sanitizer"的假设)
[P2] post-refactor-cleanup.md Open Question op7418#2:OpenRouter Opus 4.8 不再写 deferred(已接入)
测试: opus-4-8-sonnet-4-6.test.ts 扩到 18 断言(+dotted slug +路由层 op7418#23 source-pin 含 skills opus/haiku)。
验证: tsc exit 0、targeted 18/18、业务代码无 claude-sonnet-4-20250514 残留。
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
用户 2026-05-29 跑通三条真实凭据 smoke(Smoke Ledger 已记):
- OpenRouter Opus 4.8 (opus-4-8 → anthropic/claude-opus-4.8): OPENROUTER_OPUS48_OK
- Anthropic direct Opus 4.8 (Claude Code 账户): OPUS48_CLAUDE_ACCOUNT_A/B_OK
- Sonnet 4.6 op7418#23 反例路径: SONNET46_SMOKE_A/B_OK
状态表 Phase A → 完成;Open Question op7418#2 smoke 标已通过。
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
在用户本机做隔离 POC + 端到端 POC(findCodexBinary 解析到的 .app codex
0.133.0 + 真实 ~/.codex),证伪了原日志推断「xhigh 配置让 app-server 挂掉」:
- .app codex 0.133.0 原生接受 model_reasoning_effort=xhigh(initialize +
model/list 全 OK,不退出);对 max/垃圾值只警告不致命。
- 端到端:当前二进制 + 真实含 xhigh 的 ~/.codex → initialize OK + model/list
返回 6 个真实模型 → 用户 Codex 现在就是通的。
- 日志里失败的是 /opt/homebrew/bin/codex(现已卸载),更旧/更严、只认 4 档且
把配置反序列化失败当致命退出。login shell PATH 已无任何 codex,打包 app 只会
解析到 .app 0.133.0。
修正:
- 顶部新增「POC 实测修正」权威段(外部事实 pin 0.133.0 / 仓库 file:line / 推断三层)。
- 标注下方「日志确认」claim op7418#2 与修复表 row1 为已更正,指向新段,保留推断留痕。
- 修复方向改判:立即动作=重启 CodePilot(不用改 config);P0=app-server init 期
退出时立即 reject pending init(不等 30s,这才是三症状变慢的真因);P1=clamp
CodePilot 发给 Codex 的 effort;否决 spawn -c 覆盖(no-op+覆盖用户配置+不可验证)。
- 同步 research/README.md 索引。
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
b853188 把侧栏"需要批准"徽章的清理放在 useStreamSubscription,但它依赖当前会话的
ChatView 挂载:用户切到别的会话后该 hook 退订(useStreamSubscription cleanup),
后续 timeout 的 snapshot-updated 不再触发清理。AppShell 的全局 handler 会从所有
active stream 重算 pendingApprovalSessionIds(Set 源,已正确排除超时),但没有清全局
单值 pendingApprovalSessionId;侧栏 needsApproval 仍 OR 这两个来源(ChatListPanel)
→ 切走后单值残留,徽章不灭直到 stream 结束。
改动:
- src/components/layout/AppShell.tsx:全局 stream-session-event handler 改为接收
event,重算 approvals 后,若 pendingApprovalSessionId === detail.sessionId 且该
session 不在 approvals,就清单值(函数式更新 + 守卫)。这不依赖 ChatView 挂载
(覆盖"切走后超时"),且精确——不会误清仍 pending 的 peer 或 /chat inline 新会话。
- src/hooks/useStreamSubscription.ts:移除 b853188 那条无条件清理(已被 AppShell
完整且更安全地取代;无条件版在分屏下会误清 peer 的全局单值,虽被 Set 源掩盖)。
- 入口1(/chat inline)不走 stream-session-manager 的 window event,保留 page.tsx
自身 permission_resolved case 的清理。
验证:tsc --noEmit exit 0;全量单测 3360/3360。React 状态接线无 hook-test harness,
靠 typecheck + AppShell Set 源独立保护 + 代码审查。
guardrail:徽章单值清理收敛到 AppShell 全局 handler 这一处(不依赖任何 ChatView
挂载),与 Set 源对超时 / resolved 态一致。
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: 用户反馈 + 计划 Phase 2——图片/文件等普通上下文过大时弹"上下文太多,发送前
请确认"的阻断式横幅,必须再点一次才能发;图片发送被二次确认卡住。
Triage(当前源码): run-checkpoint.ts 的 context-cost-change reason 设了
requiresConfirm:true + confirm-context-cost 动作;两个聊天入口(page.tsx:288 /
ChatView.tsx:368)都用 `checkpointReasons.filter(r => r.requiresConfirm)` 派生
blockingReasonIds,MessageInput:511 据此 throw 'run-checkpoint-blocked' 阻断发送。
即估算型上下文大小被做成了二次确认阻断——违反"非破坏性、用户主动发起的发送不得因
估算风险被阻断"。注:context-cost 是当前唯一的 requiresConfirm reason。
Fix:
- run-checkpoint.ts: context-cost-change 去掉 requiresConfirm + confirm 动作 →
纯 info-tone 非阻断 heads-up,永不进入 blockingReasonIds,图片/文件首个 Enter 即发。
- i18n en/zh: 文案去掉"Confirm before sending / 发送前请确认"的确认框架,改为纯提示。
- 阻断/bypass 基建(blockingReasonIds + MessageInput 'run-checkpoint-blocked' throw +
PromptInput 截图保留契约 + confirm→bypass 桥)**保留**:它保护任何被拒提交、且按计划
留给未来真实危险动作(写/删/执行/提权——那些走权限系统)。两入口的 confirm-context-cost
处理器改注释为 dormant,逻辑不动。
语义验收: 普通上下文过大只出非阻断提示;阻断只留给真实危险动作;图片发送不再二次确认。
Verify: typecheck 通过;run-checkpoint.test.ts 把"requiresConfirm=true + confirm action"
断言翻为"info-tone 非阻断、无 requiresConfirm、无 action",scope-guard 的"每个 reason 必有
action"放宽为"context-cost info-only 无 action、其余有";run-checkpoint-blocking.test.ts
更新前提(无 reason 当前 requiresConfirm)+ bypass-machine 样例 id 改假想值,保留通用机器与
截图保留契约;全量单测 3368/3368。
Guardrail: run-checkpoint.test.ts 钉死 context-cost 非阻断(notEqual requiresConfirm true
+ action undefined),防回退到把估算上下文做成阻断确认。
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
- 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>
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.

3 participants

@arthurlee116@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('^' + ".*" + ' fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题 by arthurlee116 · Pull Request #2 · op7418/CodePilot · GitHub
Skip to content

fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题 - #2

Closed
arthurlee116 wants to merge 1 commit into
op7418:mainfrom
arthurlee116:fix/build-rmsync-recursive
Closed

fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题#2
arthurlee116 wants to merge 1 commit into
op7418:mainfrom
arthurlee116:fix/build-rmsync-recursive

Conversation

@arthurlee116

Copy link
Copy Markdown

问题

执行 npm run electron:build 时,scripts/build-electron.mjs 在解析 .next/standalone/.next/node_modules/ 中的符号链接时报错:

Error: Path is a directory: .next/standalone/.next/node_modules/better-sqlite3-90e2652d1716b047
at Object.rmSync (node:fs:1236:18)
at resolveStandaloneSymlinks (file:///...CodePilot/scripts/build-electron.mjs:18:12)

部分条目(如 better-sqlite3-90e2652d1716b047)是指向目录的符号链接,fs.rmSync() 在未传入 { recursive: true } 时会抛出 ERR_FS_EISDIR 错误。

修复

fs.rmSync() 添加 { recursive: true, force: true } 参数。

CopilotAI review requested due to automatic review settings February 7, 2026 07:00

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

该 PR 修复 Electron 构建脚本在处理 Next.js standalone 输出中的“指向目录的符号链接”时,因 fs.rmSync() 未开启递归删除而报错的问题,保证 npm run electron:build 可正常执行并为后续 electron-builder 打包准备好可复制的目录结构。

Changes:

  • 为删除 standalone 目录下的符号链接时的 fs.rmSync() 增加 { recursive: true, force: true } 参数,避免遇到目录型符号链接时报 ERR_FS_EISDIR

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@op7418

Copy link
Copy Markdown
Owner

Thanks for the fix! This change was already included in PR #7 which has been merged. Closing as duplicate.

@op7418op7418 closed this Feb 7, 2026
op7418 pushed a commit that referenced this pull request Mar 2, 2026
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 #2 补充连续水位推进机制
- 新增决策 #9(图片接收)和 #10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 1, 2026
在用户本机做隔离 POC + 端到端 POC(findCodexBinary 解析到的 .app codex
0.133.0 + 真实 ~/.codex),证伪了原日志推断「xhigh 配置让 app-server 挂掉」:
- .app codex 0.133.0 原生接受 model_reasoning_effort=xhigh(initialize +
model/list 全 OK,不退出);对 max/垃圾值只警告不致命。
- 端到端:当前二进制 + 真实含 xhigh 的 ~/.codex → initialize OK + model/list
返回 6 个真实模型 → 用户 Codex 现在就是通的。
- 日志里失败的是 /opt/homebrew/bin/codex(现已卸载),更旧/更严、只认 4 档且
把配置反序列化失败当致命退出。login shell PATH 已无任何 codex,打包 app 只会
解析到 .app 0.133.0。
修正:
- 顶部新增「POC 实测修正」权威段(外部事实 pin 0.133.0 / 仓库 file:line / 推断三层)。
- 标注下方「日志确认」claim #2 与修复表 row1 为已更正,指向新段,保留推断留痕。
- 修复方向改判:立即动作=重启 CodePilot(不用改 config);P0=app-server init 期
退出时立即 reject pending init(不等 30s,这才是三症状变慢的真因);P1=clamp
CodePilot 发给 Codex 的 effort;否决 spawn -c 覆盖(no-op+覆盖用户配置+不可验证)。
- 同步 research/README.md 索引。
op7418 added a commit that referenced this pull request Jun 28, 2026
f99edbb 把侧栏"需要批准"徽章的清理放在 useStreamSubscription,但它依赖当前会话的
ChatView 挂载:用户切到别的会话后该 hook 退订(useStreamSubscription cleanup),
后续 timeout 的 snapshot-updated 不再触发清理。AppShell 的全局 handler 会从所有
active stream 重算 pendingApprovalSessionIds(Set 源,已正确排除超时),但没有清全局
单值 pendingApprovalSessionId;侧栏 needsApproval 仍 OR 这两个来源(ChatListPanel)
→ 切走后单值残留,徽章不灭直到 stream 结束。
改动:
- src/components/layout/AppShell.tsx:全局 stream-session-event handler 改为接收
event,重算 approvals 后,若 pendingApprovalSessionId === detail.sessionId 且该
session 不在 approvals,就清单值(函数式更新 + 守卫)。这不依赖 ChatView 挂载
(覆盖"切走后超时"),且精确——不会误清仍 pending 的 peer 或 /chat inline 新会话。
- src/hooks/useStreamSubscription.ts:移除 f99edbb 那条无条件清理(已被 AppShell
完整且更安全地取代;无条件版在分屏下会误清 peer 的全局单值,虽被 Set 源掩盖)。
- 入口1(/chat inline)不走 stream-session-manager 的 window event,保留 page.tsx
自身 permission_resolved case 的清理。
验证:tsc --noEmit exit 0;全量单测 3360/3360。React 状态接线无 hook-test harness,
靠 typecheck + AppShell Set 源独立保护 + 代码审查。
guardrail:徽章单值清理收敛到 AppShell 全局 handler 这一处(不依赖任何 ChatView
挂载),与 Set 源对超时 / resolved 态一致。
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: 用户反馈 + 计划 Phase 2——图片/文件等普通上下文过大时弹"上下文太多,发送前
请确认"的阻断式横幅,必须再点一次才能发;图片发送被二次确认卡住。
Triage(当前源码): run-checkpoint.ts 的 context-cost-change reason 设了
requiresConfirm:true + confirm-context-cost 动作;两个聊天入口(page.tsx:288 /
ChatView.tsx:368)都用 `checkpointReasons.filter(r => r.requiresConfirm)` 派生
blockingReasonIds,MessageInput:511 据此 throw 'run-checkpoint-blocked' 阻断发送。
即估算型上下文大小被做成了二次确认阻断——违反"非破坏性、用户主动发起的发送不得因
估算风险被阻断"。注:context-cost 是当前唯一的 requiresConfirm reason。
Fix:
- run-checkpoint.ts: context-cost-change 去掉 requiresConfirm + confirm 动作 →
纯 info-tone 非阻断 heads-up,永不进入 blockingReasonIds,图片/文件首个 Enter 即发。
- i18n en/zh: 文案去掉"Confirm before sending / 发送前请确认"的确认框架,改为纯提示。
- 阻断/bypass 基建(blockingReasonIds + MessageInput 'run-checkpoint-blocked' throw +
PromptInput 截图保留契约 + confirm→bypass 桥)**保留**:它保护任何被拒提交、且按计划
留给未来真实危险动作(写/删/执行/提权——那些走权限系统)。两入口的 confirm-context-cost
处理器改注释为 dormant,逻辑不动。
语义验收: 普通上下文过大只出非阻断提示;阻断只留给真实危险动作;图片发送不再二次确认。
Verify: typecheck 通过;run-checkpoint.test.ts 把"requiresConfirm=true + confirm action"
断言翻为"info-tone 非阻断、无 requiresConfirm、无 action",scope-guard 的"每个 reason 必有
action"放宽为"context-cost info-only 无 action、其余有";run-checkpoint-blocking.test.ts
更新前提(无 reason 当前 requiresConfirm)+ bypass-machine 样例 id 改假想值,保留通用机器与
截图保留契约;全量单测 3368/3368。
Guardrail: run-checkpoint.test.ts 钉死 context-cost 非阻断(notEqual requiresConfirm true
+ action undefined),防回退到把估算上下文做成阻断确认。
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 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>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 op7418#2 补充连续水位推进机制
- 新增决策 op7418#9(图片接收)和 op7418#10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <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
… 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
[P1] /api/providers/models route: DEFAULT_MODELS.sonnet + ENV_ALIAS_TO_UPSTREAM.sonnet
claude-sonnet-4-20250514 → claude-sonnet-4-6(API 层 op7418#23 之前未闭环)
[P1] /api/media/jobs/plan fallback + /api/skills/search MODEL_MAP: 旧 Sonnet → claude-sonnet-4-6;
skills/search 的 opus(4.6) / 旧 haiku 一并修正 → claude-opus-4-7 / claude-haiku-4-5-20251001
[P2] isOpusAdaptiveThinkingModel regex /opus-?4-?[78]/ → /opus-?4[-.]?[78]/,同时匹配 dotted
OpenRouter slug anthropic/claude-opus-4.8(不再依赖"dotted 不走此 sanitizer"的假设)
[P2] post-refactor-cleanup.md Open Question op7418#2:OpenRouter Opus 4.8 不再写 deferred(已接入)
测试: opus-4-8-sonnet-4-6.test.ts 扩到 18 断言(+dotted slug +路由层 op7418#23 source-pin 含 skills opus/haiku)。
验证: tsc exit 0、targeted 18/18、业务代码无 claude-sonnet-4-20250514 残留。
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
用户 2026-05-29 跑通三条真实凭据 smoke(Smoke Ledger 已记):
- OpenRouter Opus 4.8 (opus-4-8 → anthropic/claude-opus-4.8): OPENROUTER_OPUS48_OK
- Anthropic direct Opus 4.8 (Claude Code 账户): OPUS48_CLAUDE_ACCOUNT_A/B_OK
- Sonnet 4.6 op7418#23 反例路径: SONNET46_SMOKE_A/B_OK
状态表 Phase A → 完成;Open Question op7418#2 smoke 标已通过。
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
在用户本机做隔离 POC + 端到端 POC(findCodexBinary 解析到的 .app codex
0.133.0 + 真实 ~/.codex),证伪了原日志推断「xhigh 配置让 app-server 挂掉」:
- .app codex 0.133.0 原生接受 model_reasoning_effort=xhigh(initialize +
model/list 全 OK,不退出);对 max/垃圾值只警告不致命。
- 端到端:当前二进制 + 真实含 xhigh 的 ~/.codex → initialize OK + model/list
返回 6 个真实模型 → 用户 Codex 现在就是通的。
- 日志里失败的是 /opt/homebrew/bin/codex(现已卸载),更旧/更严、只认 4 档且
把配置反序列化失败当致命退出。login shell PATH 已无任何 codex,打包 app 只会
解析到 .app 0.133.0。
修正:
- 顶部新增「POC 实测修正」权威段(外部事实 pin 0.133.0 / 仓库 file:line / 推断三层)。
- 标注下方「日志确认」claim op7418#2 与修复表 row1 为已更正,指向新段,保留推断留痕。
- 修复方向改判:立即动作=重启 CodePilot(不用改 config);P0=app-server init 期
退出时立即 reject pending init(不等 30s,这才是三症状变慢的真因);P1=clamp
CodePilot 发给 Codex 的 effort;否决 spawn -c 覆盖(no-op+覆盖用户配置+不可验证)。
- 同步 research/README.md 索引。
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
b853188 把侧栏"需要批准"徽章的清理放在 useStreamSubscription,但它依赖当前会话的
ChatView 挂载:用户切到别的会话后该 hook 退订(useStreamSubscription cleanup),
后续 timeout 的 snapshot-updated 不再触发清理。AppShell 的全局 handler 会从所有
active stream 重算 pendingApprovalSessionIds(Set 源,已正确排除超时),但没有清全局
单值 pendingApprovalSessionId;侧栏 needsApproval 仍 OR 这两个来源(ChatListPanel)
→ 切走后单值残留,徽章不灭直到 stream 结束。
改动:
- src/components/layout/AppShell.tsx:全局 stream-session-event handler 改为接收
event,重算 approvals 后,若 pendingApprovalSessionId === detail.sessionId 且该
session 不在 approvals,就清单值(函数式更新 + 守卫)。这不依赖 ChatView 挂载
(覆盖"切走后超时"),且精确——不会误清仍 pending 的 peer 或 /chat inline 新会话。
- src/hooks/useStreamSubscription.ts:移除 b853188 那条无条件清理(已被 AppShell
完整且更安全地取代;无条件版在分屏下会误清 peer 的全局单值,虽被 Set 源掩盖)。
- 入口1(/chat inline)不走 stream-session-manager 的 window event,保留 page.tsx
自身 permission_resolved case 的清理。
验证:tsc --noEmit exit 0;全量单测 3360/3360。React 状态接线无 hook-test harness,
靠 typecheck + AppShell Set 源独立保护 + 代码审查。
guardrail:徽章单值清理收敛到 AppShell 全局 handler 这一处(不依赖任何 ChatView
挂载),与 Set 源对超时 / resolved 态一致。
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: 用户反馈 + 计划 Phase 2——图片/文件等普通上下文过大时弹"上下文太多,发送前
请确认"的阻断式横幅,必须再点一次才能发;图片发送被二次确认卡住。
Triage(当前源码): run-checkpoint.ts 的 context-cost-change reason 设了
requiresConfirm:true + confirm-context-cost 动作;两个聊天入口(page.tsx:288 /
ChatView.tsx:368)都用 `checkpointReasons.filter(r => r.requiresConfirm)` 派生
blockingReasonIds,MessageInput:511 据此 throw 'run-checkpoint-blocked' 阻断发送。
即估算型上下文大小被做成了二次确认阻断——违反"非破坏性、用户主动发起的发送不得因
估算风险被阻断"。注:context-cost 是当前唯一的 requiresConfirm reason。
Fix:
- run-checkpoint.ts: context-cost-change 去掉 requiresConfirm + confirm 动作 →
纯 info-tone 非阻断 heads-up,永不进入 blockingReasonIds,图片/文件首个 Enter 即发。
- i18n en/zh: 文案去掉"Confirm before sending / 发送前请确认"的确认框架,改为纯提示。
- 阻断/bypass 基建(blockingReasonIds + MessageInput 'run-checkpoint-blocked' throw +
PromptInput 截图保留契约 + confirm→bypass 桥)**保留**:它保护任何被拒提交、且按计划
留给未来真实危险动作(写/删/执行/提权——那些走权限系统)。两入口的 confirm-context-cost
处理器改注释为 dormant,逻辑不动。
语义验收: 普通上下文过大只出非阻断提示;阻断只留给真实危险动作;图片发送不再二次确认。
Verify: typecheck 通过;run-checkpoint.test.ts 把"requiresConfirm=true + confirm action"
断言翻为"info-tone 非阻断、无 requiresConfirm、无 action",scope-guard 的"每个 reason 必有
action"放宽为"context-cost info-only 无 action、其余有";run-checkpoint-blocking.test.ts
更新前提(无 reason 当前 requiresConfirm)+ bypass-machine 样例 id 改假想值,保留通用机器与
截图保留契约;全量单测 3368/3368。
Guardrail: run-checkpoint.test.ts 钉死 context-cost 非阻断(notEqual requiresConfirm true
+ action undefined),防回退到把估算上下文做成阻断确认。
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
- 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>
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.

3 participants

@arthurlee116@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('^' + ".*" + ' fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题 by arthurlee116 · Pull Request #2 · op7418/CodePilot · GitHub
Skip to content

fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题 - #2

Closed
arthurlee116 wants to merge 1 commit into
op7418:mainfrom
arthurlee116:fix/build-rmsync-recursive
Closed

fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题#2
arthurlee116 wants to merge 1 commit into
op7418:mainfrom
arthurlee116:fix/build-rmsync-recursive

Conversation

@arthurlee116

Copy link
Copy Markdown

问题

执行 npm run electron:build 时,scripts/build-electron.mjs 在解析 .next/standalone/.next/node_modules/ 中的符号链接时报错:

Error: Path is a directory: .next/standalone/.next/node_modules/better-sqlite3-90e2652d1716b047
at Object.rmSync (node:fs:1236:18)
at resolveStandaloneSymlinks (file:///...CodePilot/scripts/build-electron.mjs:18:12)

部分条目(如 better-sqlite3-90e2652d1716b047)是指向目录的符号链接,fs.rmSync() 在未传入 { recursive: true } 时会抛出 ERR_FS_EISDIR 错误。

修复

fs.rmSync() 添加 { recursive: true, force: true } 参数。

CopilotAI review requested due to automatic review settings February 7, 2026 07:00

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

该 PR 修复 Electron 构建脚本在处理 Next.js standalone 输出中的“指向目录的符号链接”时,因 fs.rmSync() 未开启递归删除而报错的问题,保证 npm run electron:build 可正常执行并为后续 electron-builder 打包准备好可复制的目录结构。

Changes:

  • 为删除 standalone 目录下的符号链接时的 fs.rmSync() 增加 { recursive: true, force: true } 参数,避免遇到目录型符号链接时报 ERR_FS_EISDIR

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@op7418

Copy link
Copy Markdown
Owner

Thanks for the fix! This change was already included in PR #7 which has been merged. Closing as duplicate.

@op7418op7418 closed this Feb 7, 2026
op7418 pushed a commit that referenced this pull request Mar 2, 2026
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 #2 补充连续水位推进机制
- 新增决策 #9(图片接收)和 #10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 1, 2026
在用户本机做隔离 POC + 端到端 POC(findCodexBinary 解析到的 .app codex
0.133.0 + 真实 ~/.codex),证伪了原日志推断「xhigh 配置让 app-server 挂掉」:
- .app codex 0.133.0 原生接受 model_reasoning_effort=xhigh(initialize +
model/list 全 OK,不退出);对 max/垃圾值只警告不致命。
- 端到端:当前二进制 + 真实含 xhigh 的 ~/.codex → initialize OK + model/list
返回 6 个真实模型 → 用户 Codex 现在就是通的。
- 日志里失败的是 /opt/homebrew/bin/codex(现已卸载),更旧/更严、只认 4 档且
把配置反序列化失败当致命退出。login shell PATH 已无任何 codex,打包 app 只会
解析到 .app 0.133.0。
修正:
- 顶部新增「POC 实测修正」权威段(外部事实 pin 0.133.0 / 仓库 file:line / 推断三层)。
- 标注下方「日志确认」claim #2 与修复表 row1 为已更正,指向新段,保留推断留痕。
- 修复方向改判:立即动作=重启 CodePilot(不用改 config);P0=app-server init 期
退出时立即 reject pending init(不等 30s,这才是三症状变慢的真因);P1=clamp
CodePilot 发给 Codex 的 effort;否决 spawn -c 覆盖(no-op+覆盖用户配置+不可验证)。
- 同步 research/README.md 索引。
op7418 added a commit that referenced this pull request Jun 28, 2026
f99edbb 把侧栏"需要批准"徽章的清理放在 useStreamSubscription,但它依赖当前会话的
ChatView 挂载:用户切到别的会话后该 hook 退订(useStreamSubscription cleanup),
后续 timeout 的 snapshot-updated 不再触发清理。AppShell 的全局 handler 会从所有
active stream 重算 pendingApprovalSessionIds(Set 源,已正确排除超时),但没有清全局
单值 pendingApprovalSessionId;侧栏 needsApproval 仍 OR 这两个来源(ChatListPanel)
→ 切走后单值残留,徽章不灭直到 stream 结束。
改动:
- src/components/layout/AppShell.tsx:全局 stream-session-event handler 改为接收
event,重算 approvals 后,若 pendingApprovalSessionId === detail.sessionId 且该
session 不在 approvals,就清单值(函数式更新 + 守卫)。这不依赖 ChatView 挂载
(覆盖"切走后超时"),且精确——不会误清仍 pending 的 peer 或 /chat inline 新会话。
- src/hooks/useStreamSubscription.ts:移除 f99edbb 那条无条件清理(已被 AppShell
完整且更安全地取代;无条件版在分屏下会误清 peer 的全局单值,虽被 Set 源掩盖)。
- 入口1(/chat inline)不走 stream-session-manager 的 window event,保留 page.tsx
自身 permission_resolved case 的清理。
验证:tsc --noEmit exit 0;全量单测 3360/3360。React 状态接线无 hook-test harness,
靠 typecheck + AppShell Set 源独立保护 + 代码审查。
guardrail:徽章单值清理收敛到 AppShell 全局 handler 这一处(不依赖任何 ChatView
挂载),与 Set 源对超时 / resolved 态一致。
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: 用户反馈 + 计划 Phase 2——图片/文件等普通上下文过大时弹"上下文太多,发送前
请确认"的阻断式横幅,必须再点一次才能发;图片发送被二次确认卡住。
Triage(当前源码): run-checkpoint.ts 的 context-cost-change reason 设了
requiresConfirm:true + confirm-context-cost 动作;两个聊天入口(page.tsx:288 /
ChatView.tsx:368)都用 `checkpointReasons.filter(r => r.requiresConfirm)` 派生
blockingReasonIds,MessageInput:511 据此 throw 'run-checkpoint-blocked' 阻断发送。
即估算型上下文大小被做成了二次确认阻断——违反"非破坏性、用户主动发起的发送不得因
估算风险被阻断"。注:context-cost 是当前唯一的 requiresConfirm reason。
Fix:
- run-checkpoint.ts: context-cost-change 去掉 requiresConfirm + confirm 动作 →
纯 info-tone 非阻断 heads-up,永不进入 blockingReasonIds,图片/文件首个 Enter 即发。
- i18n en/zh: 文案去掉"Confirm before sending / 发送前请确认"的确认框架,改为纯提示。
- 阻断/bypass 基建(blockingReasonIds + MessageInput 'run-checkpoint-blocked' throw +
PromptInput 截图保留契约 + confirm→bypass 桥)**保留**:它保护任何被拒提交、且按计划
留给未来真实危险动作(写/删/执行/提权——那些走权限系统)。两入口的 confirm-context-cost
处理器改注释为 dormant,逻辑不动。
语义验收: 普通上下文过大只出非阻断提示;阻断只留给真实危险动作;图片发送不再二次确认。
Verify: typecheck 通过;run-checkpoint.test.ts 把"requiresConfirm=true + confirm action"
断言翻为"info-tone 非阻断、无 requiresConfirm、无 action",scope-guard 的"每个 reason 必有
action"放宽为"context-cost info-only 无 action、其余有";run-checkpoint-blocking.test.ts
更新前提(无 reason 当前 requiresConfirm)+ bypass-machine 样例 id 改假想值,保留通用机器与
截图保留契约;全量单测 3368/3368。
Guardrail: run-checkpoint.test.ts 钉死 context-cost 非阻断(notEqual requiresConfirm true
+ action undefined),防回退到把估算上下文做成阻断确认。
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 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>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 op7418#2 补充连续水位推进机制
- 新增决策 op7418#9(图片接收)和 op7418#10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <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
… 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
[P1] /api/providers/models route: DEFAULT_MODELS.sonnet + ENV_ALIAS_TO_UPSTREAM.sonnet
claude-sonnet-4-20250514 → claude-sonnet-4-6(API 层 op7418#23 之前未闭环)
[P1] /api/media/jobs/plan fallback + /api/skills/search MODEL_MAP: 旧 Sonnet → claude-sonnet-4-6;
skills/search 的 opus(4.6) / 旧 haiku 一并修正 → claude-opus-4-7 / claude-haiku-4-5-20251001
[P2] isOpusAdaptiveThinkingModel regex /opus-?4-?[78]/ → /opus-?4[-.]?[78]/,同时匹配 dotted
OpenRouter slug anthropic/claude-opus-4.8(不再依赖"dotted 不走此 sanitizer"的假设)
[P2] post-refactor-cleanup.md Open Question op7418#2:OpenRouter Opus 4.8 不再写 deferred(已接入)
测试: opus-4-8-sonnet-4-6.test.ts 扩到 18 断言(+dotted slug +路由层 op7418#23 source-pin 含 skills opus/haiku)。
验证: tsc exit 0、targeted 18/18、业务代码无 claude-sonnet-4-20250514 残留。
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
用户 2026-05-29 跑通三条真实凭据 smoke(Smoke Ledger 已记):
- OpenRouter Opus 4.8 (opus-4-8 → anthropic/claude-opus-4.8): OPENROUTER_OPUS48_OK
- Anthropic direct Opus 4.8 (Claude Code 账户): OPUS48_CLAUDE_ACCOUNT_A/B_OK
- Sonnet 4.6 op7418#23 反例路径: SONNET46_SMOKE_A/B_OK
状态表 Phase A → 完成;Open Question op7418#2 smoke 标已通过。
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
在用户本机做隔离 POC + 端到端 POC(findCodexBinary 解析到的 .app codex
0.133.0 + 真实 ~/.codex),证伪了原日志推断「xhigh 配置让 app-server 挂掉」:
- .app codex 0.133.0 原生接受 model_reasoning_effort=xhigh(initialize +
model/list 全 OK,不退出);对 max/垃圾值只警告不致命。
- 端到端:当前二进制 + 真实含 xhigh 的 ~/.codex → initialize OK + model/list
返回 6 个真实模型 → 用户 Codex 现在就是通的。
- 日志里失败的是 /opt/homebrew/bin/codex(现已卸载),更旧/更严、只认 4 档且
把配置反序列化失败当致命退出。login shell PATH 已无任何 codex,打包 app 只会
解析到 .app 0.133.0。
修正:
- 顶部新增「POC 实测修正」权威段(外部事实 pin 0.133.0 / 仓库 file:line / 推断三层)。
- 标注下方「日志确认」claim op7418#2 与修复表 row1 为已更正,指向新段,保留推断留痕。
- 修复方向改判:立即动作=重启 CodePilot(不用改 config);P0=app-server init 期
退出时立即 reject pending init(不等 30s,这才是三症状变慢的真因);P1=clamp
CodePilot 发给 Codex 的 effort;否决 spawn -c 覆盖(no-op+覆盖用户配置+不可验证)。
- 同步 research/README.md 索引。
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
b853188 把侧栏"需要批准"徽章的清理放在 useStreamSubscription,但它依赖当前会话的
ChatView 挂载:用户切到别的会话后该 hook 退订(useStreamSubscription cleanup),
后续 timeout 的 snapshot-updated 不再触发清理。AppShell 的全局 handler 会从所有
active stream 重算 pendingApprovalSessionIds(Set 源,已正确排除超时),但没有清全局
单值 pendingApprovalSessionId;侧栏 needsApproval 仍 OR 这两个来源(ChatListPanel)
→ 切走后单值残留,徽章不灭直到 stream 结束。
改动:
- src/components/layout/AppShell.tsx:全局 stream-session-event handler 改为接收
event,重算 approvals 后,若 pendingApprovalSessionId === detail.sessionId 且该
session 不在 approvals,就清单值(函数式更新 + 守卫)。这不依赖 ChatView 挂载
(覆盖"切走后超时"),且精确——不会误清仍 pending 的 peer 或 /chat inline 新会话。
- src/hooks/useStreamSubscription.ts:移除 b853188 那条无条件清理(已被 AppShell
完整且更安全地取代;无条件版在分屏下会误清 peer 的全局单值,虽被 Set 源掩盖)。
- 入口1(/chat inline)不走 stream-session-manager 的 window event,保留 page.tsx
自身 permission_resolved case 的清理。
验证:tsc --noEmit exit 0;全量单测 3360/3360。React 状态接线无 hook-test harness,
靠 typecheck + AppShell Set 源独立保护 + 代码审查。
guardrail:徽章单值清理收敛到 AppShell 全局 handler 这一处(不依赖任何 ChatView
挂载),与 Set 源对超时 / resolved 态一致。
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: 用户反馈 + 计划 Phase 2——图片/文件等普通上下文过大时弹"上下文太多,发送前
请确认"的阻断式横幅,必须再点一次才能发;图片发送被二次确认卡住。
Triage(当前源码): run-checkpoint.ts 的 context-cost-change reason 设了
requiresConfirm:true + confirm-context-cost 动作;两个聊天入口(page.tsx:288 /
ChatView.tsx:368)都用 `checkpointReasons.filter(r => r.requiresConfirm)` 派生
blockingReasonIds,MessageInput:511 据此 throw 'run-checkpoint-blocked' 阻断发送。
即估算型上下文大小被做成了二次确认阻断——违反"非破坏性、用户主动发起的发送不得因
估算风险被阻断"。注:context-cost 是当前唯一的 requiresConfirm reason。
Fix:
- run-checkpoint.ts: context-cost-change 去掉 requiresConfirm + confirm 动作 →
纯 info-tone 非阻断 heads-up,永不进入 blockingReasonIds,图片/文件首个 Enter 即发。
- i18n en/zh: 文案去掉"Confirm before sending / 发送前请确认"的确认框架,改为纯提示。
- 阻断/bypass 基建(blockingReasonIds + MessageInput 'run-checkpoint-blocked' throw +
PromptInput 截图保留契约 + confirm→bypass 桥)**保留**:它保护任何被拒提交、且按计划
留给未来真实危险动作(写/删/执行/提权——那些走权限系统)。两入口的 confirm-context-cost
处理器改注释为 dormant,逻辑不动。
语义验收: 普通上下文过大只出非阻断提示;阻断只留给真实危险动作;图片发送不再二次确认。
Verify: typecheck 通过;run-checkpoint.test.ts 把"requiresConfirm=true + confirm action"
断言翻为"info-tone 非阻断、无 requiresConfirm、无 action",scope-guard 的"每个 reason 必有
action"放宽为"context-cost info-only 无 action、其余有";run-checkpoint-blocking.test.ts
更新前提(无 reason 当前 requiresConfirm)+ bypass-machine 样例 id 改假想值,保留通用机器与
截图保留契约;全量单测 3368/3368。
Guardrail: run-checkpoint.test.ts 钉死 context-cost 非阻断(notEqual requiresConfirm true
+ action undefined),防回退到把估算上下文做成阻断确认。
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
- 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>
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.

3 participants

@arthurlee116@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" + ' fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题 by arthurlee116 · Pull Request #2 · op7418/CodePilot · GitHub
Skip to content

fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题 - #2

Closed
arthurlee116 wants to merge 1 commit into
op7418:mainfrom
arthurlee116:fix/build-rmsync-recursive
Closed

fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题#2
arthurlee116 wants to merge 1 commit into
op7418:mainfrom
arthurlee116:fix/build-rmsync-recursive

Conversation

@arthurlee116

Copy link
Copy Markdown

问题

执行 npm run electron:build 时,scripts/build-electron.mjs 在解析 .next/standalone/.next/node_modules/ 中的符号链接时报错:

Error: Path is a directory: .next/standalone/.next/node_modules/better-sqlite3-90e2652d1716b047
at Object.rmSync (node:fs:1236:18)
at resolveStandaloneSymlinks (file:///...CodePilot/scripts/build-electron.mjs:18:12)

部分条目(如 better-sqlite3-90e2652d1716b047)是指向目录的符号链接,fs.rmSync() 在未传入 { recursive: true } 时会抛出 ERR_FS_EISDIR 错误。

修复

fs.rmSync() 添加 { recursive: true, force: true } 参数。

CopilotAI review requested due to automatic review settings February 7, 2026 07:00

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

该 PR 修复 Electron 构建脚本在处理 Next.js standalone 输出中的“指向目录的符号链接”时,因 fs.rmSync() 未开启递归删除而报错的问题,保证 npm run electron:build 可正常执行并为后续 electron-builder 打包准备好可复制的目录结构。

Changes:

  • 为删除 standalone 目录下的符号链接时的 fs.rmSync() 增加 { recursive: true, force: true } 参数,避免遇到目录型符号链接时报 ERR_FS_EISDIR

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@op7418

Copy link
Copy Markdown
Owner

Thanks for the fix! This change was already included in PR #7 which has been merged. Closing as duplicate.

@op7418op7418 closed this Feb 7, 2026
op7418 pushed a commit that referenced this pull request Mar 2, 2026
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 #2 补充连续水位推进机制
- 新增决策 #9(图片接收)和 #10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 1, 2026
在用户本机做隔离 POC + 端到端 POC(findCodexBinary 解析到的 .app codex
0.133.0 + 真实 ~/.codex),证伪了原日志推断「xhigh 配置让 app-server 挂掉」:
- .app codex 0.133.0 原生接受 model_reasoning_effort=xhigh(initialize +
model/list 全 OK,不退出);对 max/垃圾值只警告不致命。
- 端到端:当前二进制 + 真实含 xhigh 的 ~/.codex → initialize OK + model/list
返回 6 个真实模型 → 用户 Codex 现在就是通的。
- 日志里失败的是 /opt/homebrew/bin/codex(现已卸载),更旧/更严、只认 4 档且
把配置反序列化失败当致命退出。login shell PATH 已无任何 codex,打包 app 只会
解析到 .app 0.133.0。
修正:
- 顶部新增「POC 实测修正」权威段(外部事实 pin 0.133.0 / 仓库 file:line / 推断三层)。
- 标注下方「日志确认」claim #2 与修复表 row1 为已更正,指向新段,保留推断留痕。
- 修复方向改判:立即动作=重启 CodePilot(不用改 config);P0=app-server init 期
退出时立即 reject pending init(不等 30s,这才是三症状变慢的真因);P1=clamp
CodePilot 发给 Codex 的 effort;否决 spawn -c 覆盖(no-op+覆盖用户配置+不可验证)。
- 同步 research/README.md 索引。
op7418 added a commit that referenced this pull request Jun 28, 2026
f99edbb 把侧栏"需要批准"徽章的清理放在 useStreamSubscription,但它依赖当前会话的
ChatView 挂载:用户切到别的会话后该 hook 退订(useStreamSubscription cleanup),
后续 timeout 的 snapshot-updated 不再触发清理。AppShell 的全局 handler 会从所有
active stream 重算 pendingApprovalSessionIds(Set 源,已正确排除超时),但没有清全局
单值 pendingApprovalSessionId;侧栏 needsApproval 仍 OR 这两个来源(ChatListPanel)
→ 切走后单值残留,徽章不灭直到 stream 结束。
改动:
- src/components/layout/AppShell.tsx:全局 stream-session-event handler 改为接收
event,重算 approvals 后,若 pendingApprovalSessionId === detail.sessionId 且该
session 不在 approvals,就清单值(函数式更新 + 守卫)。这不依赖 ChatView 挂载
(覆盖"切走后超时"),且精确——不会误清仍 pending 的 peer 或 /chat inline 新会话。
- src/hooks/useStreamSubscription.ts:移除 f99edbb 那条无条件清理(已被 AppShell
完整且更安全地取代;无条件版在分屏下会误清 peer 的全局单值,虽被 Set 源掩盖)。
- 入口1(/chat inline)不走 stream-session-manager 的 window event,保留 page.tsx
自身 permission_resolved case 的清理。
验证:tsc --noEmit exit 0;全量单测 3360/3360。React 状态接线无 hook-test harness,
靠 typecheck + AppShell Set 源独立保护 + 代码审查。
guardrail:徽章单值清理收敛到 AppShell 全局 handler 这一处(不依赖任何 ChatView
挂载),与 Set 源对超时 / resolved 态一致。
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: 用户反馈 + 计划 Phase 2——图片/文件等普通上下文过大时弹"上下文太多,发送前
请确认"的阻断式横幅,必须再点一次才能发;图片发送被二次确认卡住。
Triage(当前源码): run-checkpoint.ts 的 context-cost-change reason 设了
requiresConfirm:true + confirm-context-cost 动作;两个聊天入口(page.tsx:288 /
ChatView.tsx:368)都用 `checkpointReasons.filter(r => r.requiresConfirm)` 派生
blockingReasonIds,MessageInput:511 据此 throw 'run-checkpoint-blocked' 阻断发送。
即估算型上下文大小被做成了二次确认阻断——违反"非破坏性、用户主动发起的发送不得因
估算风险被阻断"。注:context-cost 是当前唯一的 requiresConfirm reason。
Fix:
- run-checkpoint.ts: context-cost-change 去掉 requiresConfirm + confirm 动作 →
纯 info-tone 非阻断 heads-up,永不进入 blockingReasonIds,图片/文件首个 Enter 即发。
- i18n en/zh: 文案去掉"Confirm before sending / 发送前请确认"的确认框架,改为纯提示。
- 阻断/bypass 基建(blockingReasonIds + MessageInput 'run-checkpoint-blocked' throw +
PromptInput 截图保留契约 + confirm→bypass 桥)**保留**:它保护任何被拒提交、且按计划
留给未来真实危险动作(写/删/执行/提权——那些走权限系统)。两入口的 confirm-context-cost
处理器改注释为 dormant,逻辑不动。
语义验收: 普通上下文过大只出非阻断提示;阻断只留给真实危险动作;图片发送不再二次确认。
Verify: typecheck 通过;run-checkpoint.test.ts 把"requiresConfirm=true + confirm action"
断言翻为"info-tone 非阻断、无 requiresConfirm、无 action",scope-guard 的"每个 reason 必有
action"放宽为"context-cost info-only 无 action、其余有";run-checkpoint-blocking.test.ts
更新前提(无 reason 当前 requiresConfirm)+ bypass-machine 样例 id 改假想值,保留通用机器与
截图保留契约;全量单测 3368/3368。
Guardrail: run-checkpoint.test.ts 钉死 context-cost 非阻断(notEqual requiresConfirm true
+ action undefined),防回退到把估算上下文做成阻断确认。
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 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>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 op7418#2 补充连续水位推进机制
- 新增决策 op7418#9(图片接收)和 op7418#10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <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
… 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
[P1] /api/providers/models route: DEFAULT_MODELS.sonnet + ENV_ALIAS_TO_UPSTREAM.sonnet
claude-sonnet-4-20250514 → claude-sonnet-4-6(API 层 op7418#23 之前未闭环)
[P1] /api/media/jobs/plan fallback + /api/skills/search MODEL_MAP: 旧 Sonnet → claude-sonnet-4-6;
skills/search 的 opus(4.6) / 旧 haiku 一并修正 → claude-opus-4-7 / claude-haiku-4-5-20251001
[P2] isOpusAdaptiveThinkingModel regex /opus-?4-?[78]/ → /opus-?4[-.]?[78]/,同时匹配 dotted
OpenRouter slug anthropic/claude-opus-4.8(不再依赖"dotted 不走此 sanitizer"的假设)
[P2] post-refactor-cleanup.md Open Question op7418#2:OpenRouter Opus 4.8 不再写 deferred(已接入)
测试: opus-4-8-sonnet-4-6.test.ts 扩到 18 断言(+dotted slug +路由层 op7418#23 source-pin 含 skills opus/haiku)。
验证: tsc exit 0、targeted 18/18、业务代码无 claude-sonnet-4-20250514 残留。
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
用户 2026-05-29 跑通三条真实凭据 smoke(Smoke Ledger 已记):
- OpenRouter Opus 4.8 (opus-4-8 → anthropic/claude-opus-4.8): OPENROUTER_OPUS48_OK
- Anthropic direct Opus 4.8 (Claude Code 账户): OPUS48_CLAUDE_ACCOUNT_A/B_OK
- Sonnet 4.6 op7418#23 反例路径: SONNET46_SMOKE_A/B_OK
状态表 Phase A → 完成;Open Question op7418#2 smoke 标已通过。
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
在用户本机做隔离 POC + 端到端 POC(findCodexBinary 解析到的 .app codex
0.133.0 + 真实 ~/.codex),证伪了原日志推断「xhigh 配置让 app-server 挂掉」:
- .app codex 0.133.0 原生接受 model_reasoning_effort=xhigh(initialize +
model/list 全 OK,不退出);对 max/垃圾值只警告不致命。
- 端到端:当前二进制 + 真实含 xhigh 的 ~/.codex → initialize OK + model/list
返回 6 个真实模型 → 用户 Codex 现在就是通的。
- 日志里失败的是 /opt/homebrew/bin/codex(现已卸载),更旧/更严、只认 4 档且
把配置反序列化失败当致命退出。login shell PATH 已无任何 codex,打包 app 只会
解析到 .app 0.133.0。
修正:
- 顶部新增「POC 实测修正」权威段(外部事实 pin 0.133.0 / 仓库 file:line / 推断三层)。
- 标注下方「日志确认」claim op7418#2 与修复表 row1 为已更正,指向新段,保留推断留痕。
- 修复方向改判:立即动作=重启 CodePilot(不用改 config);P0=app-server init 期
退出时立即 reject pending init(不等 30s,这才是三症状变慢的真因);P1=clamp
CodePilot 发给 Codex 的 effort;否决 spawn -c 覆盖(no-op+覆盖用户配置+不可验证)。
- 同步 research/README.md 索引。
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
b853188 把侧栏"需要批准"徽章的清理放在 useStreamSubscription,但它依赖当前会话的
ChatView 挂载:用户切到别的会话后该 hook 退订(useStreamSubscription cleanup),
后续 timeout 的 snapshot-updated 不再触发清理。AppShell 的全局 handler 会从所有
active stream 重算 pendingApprovalSessionIds(Set 源,已正确排除超时),但没有清全局
单值 pendingApprovalSessionId;侧栏 needsApproval 仍 OR 这两个来源(ChatListPanel)
→ 切走后单值残留,徽章不灭直到 stream 结束。
改动:
- src/components/layout/AppShell.tsx:全局 stream-session-event handler 改为接收
event,重算 approvals 后,若 pendingApprovalSessionId === detail.sessionId 且该
session 不在 approvals,就清单值(函数式更新 + 守卫)。这不依赖 ChatView 挂载
(覆盖"切走后超时"),且精确——不会误清仍 pending 的 peer 或 /chat inline 新会话。
- src/hooks/useStreamSubscription.ts:移除 b853188 那条无条件清理(已被 AppShell
完整且更安全地取代;无条件版在分屏下会误清 peer 的全局单值,虽被 Set 源掩盖)。
- 入口1(/chat inline)不走 stream-session-manager 的 window event,保留 page.tsx
自身 permission_resolved case 的清理。
验证:tsc --noEmit exit 0;全量单测 3360/3360。React 状态接线无 hook-test harness,
靠 typecheck + AppShell Set 源独立保护 + 代码审查。
guardrail:徽章单值清理收敛到 AppShell 全局 handler 这一处(不依赖任何 ChatView
挂载),与 Set 源对超时 / resolved 态一致。
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: 用户反馈 + 计划 Phase 2——图片/文件等普通上下文过大时弹"上下文太多,发送前
请确认"的阻断式横幅,必须再点一次才能发;图片发送被二次确认卡住。
Triage(当前源码): run-checkpoint.ts 的 context-cost-change reason 设了
requiresConfirm:true + confirm-context-cost 动作;两个聊天入口(page.tsx:288 /
ChatView.tsx:368)都用 `checkpointReasons.filter(r => r.requiresConfirm)` 派生
blockingReasonIds,MessageInput:511 据此 throw 'run-checkpoint-blocked' 阻断发送。
即估算型上下文大小被做成了二次确认阻断——违反"非破坏性、用户主动发起的发送不得因
估算风险被阻断"。注:context-cost 是当前唯一的 requiresConfirm reason。
Fix:
- run-checkpoint.ts: context-cost-change 去掉 requiresConfirm + confirm 动作 →
纯 info-tone 非阻断 heads-up,永不进入 blockingReasonIds,图片/文件首个 Enter 即发。
- i18n en/zh: 文案去掉"Confirm before sending / 发送前请确认"的确认框架,改为纯提示。
- 阻断/bypass 基建(blockingReasonIds + MessageInput 'run-checkpoint-blocked' throw +
PromptInput 截图保留契约 + confirm→bypass 桥)**保留**:它保护任何被拒提交、且按计划
留给未来真实危险动作(写/删/执行/提权——那些走权限系统)。两入口的 confirm-context-cost
处理器改注释为 dormant,逻辑不动。
语义验收: 普通上下文过大只出非阻断提示;阻断只留给真实危险动作;图片发送不再二次确认。
Verify: typecheck 通过;run-checkpoint.test.ts 把"requiresConfirm=true + confirm action"
断言翻为"info-tone 非阻断、无 requiresConfirm、无 action",scope-guard 的"每个 reason 必有
action"放宽为"context-cost info-only 无 action、其余有";run-checkpoint-blocking.test.ts
更新前提(无 reason 当前 requiresConfirm)+ bypass-machine 样例 id 改假想值,保留通用机器与
截图保留契约;全量单测 3368/3368。
Guardrail: run-checkpoint.test.ts 钉死 context-cost 非阻断(notEqual requiresConfirm true
+ action undefined),防回退到把估算上下文做成阻断确认。
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
- 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>
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.

3 participants

@arthurlee116@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('^' + ".*" + ' fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题 by arthurlee116 · Pull Request #2 · op7418/CodePilot · GitHub
Skip to content

fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题 - #2

Closed
arthurlee116 wants to merge 1 commit into
op7418:mainfrom
arthurlee116:fix/build-rmsync-recursive
Closed

fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题#2
arthurlee116 wants to merge 1 commit into
op7418:mainfrom
arthurlee116:fix/build-rmsync-recursive

Conversation

@arthurlee116

Copy link
Copy Markdown

问题

执行 npm run electron:build 时,scripts/build-electron.mjs 在解析 .next/standalone/.next/node_modules/ 中的符号链接时报错:

Error: Path is a directory: .next/standalone/.next/node_modules/better-sqlite3-90e2652d1716b047
at Object.rmSync (node:fs:1236:18)
at resolveStandaloneSymlinks (file:///...CodePilot/scripts/build-electron.mjs:18:12)

部分条目(如 better-sqlite3-90e2652d1716b047)是指向目录的符号链接,fs.rmSync() 在未传入 { recursive: true } 时会抛出 ERR_FS_EISDIR 错误。

修复

fs.rmSync() 添加 { recursive: true, force: true } 参数。

CopilotAI review requested due to automatic review settings February 7, 2026 07:00

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

该 PR 修复 Electron 构建脚本在处理 Next.js standalone 输出中的“指向目录的符号链接”时,因 fs.rmSync() 未开启递归删除而报错的问题,保证 npm run electron:build 可正常执行并为后续 electron-builder 打包准备好可复制的目录结构。

Changes:

  • 为删除 standalone 目录下的符号链接时的 fs.rmSync() 增加 { recursive: true, force: true } 参数,避免遇到目录型符号链接时报 ERR_FS_EISDIR

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@op7418

Copy link
Copy Markdown
Owner

Thanks for the fix! This change was already included in PR #7 which has been merged. Closing as duplicate.

@op7418op7418 closed this Feb 7, 2026
op7418 pushed a commit that referenced this pull request Mar 2, 2026
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 #2 补充连续水位推进机制
- 新增决策 #9(图片接收)和 #10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 1, 2026
在用户本机做隔离 POC + 端到端 POC(findCodexBinary 解析到的 .app codex
0.133.0 + 真实 ~/.codex),证伪了原日志推断「xhigh 配置让 app-server 挂掉」:
- .app codex 0.133.0 原生接受 model_reasoning_effort=xhigh(initialize +
model/list 全 OK,不退出);对 max/垃圾值只警告不致命。
- 端到端:当前二进制 + 真实含 xhigh 的 ~/.codex → initialize OK + model/list
返回 6 个真实模型 → 用户 Codex 现在就是通的。
- 日志里失败的是 /opt/homebrew/bin/codex(现已卸载),更旧/更严、只认 4 档且
把配置反序列化失败当致命退出。login shell PATH 已无任何 codex,打包 app 只会
解析到 .app 0.133.0。
修正:
- 顶部新增「POC 实测修正」权威段(外部事实 pin 0.133.0 / 仓库 file:line / 推断三层)。
- 标注下方「日志确认」claim #2 与修复表 row1 为已更正,指向新段,保留推断留痕。
- 修复方向改判:立即动作=重启 CodePilot(不用改 config);P0=app-server init 期
退出时立即 reject pending init(不等 30s,这才是三症状变慢的真因);P1=clamp
CodePilot 发给 Codex 的 effort;否决 spawn -c 覆盖(no-op+覆盖用户配置+不可验证)。
- 同步 research/README.md 索引。
op7418 added a commit that referenced this pull request Jun 28, 2026
f99edbb 把侧栏"需要批准"徽章的清理放在 useStreamSubscription,但它依赖当前会话的
ChatView 挂载:用户切到别的会话后该 hook 退订(useStreamSubscription cleanup),
后续 timeout 的 snapshot-updated 不再触发清理。AppShell 的全局 handler 会从所有
active stream 重算 pendingApprovalSessionIds(Set 源,已正确排除超时),但没有清全局
单值 pendingApprovalSessionId;侧栏 needsApproval 仍 OR 这两个来源(ChatListPanel)
→ 切走后单值残留,徽章不灭直到 stream 结束。
改动:
- src/components/layout/AppShell.tsx:全局 stream-session-event handler 改为接收
event,重算 approvals 后,若 pendingApprovalSessionId === detail.sessionId 且该
session 不在 approvals,就清单值(函数式更新 + 守卫)。这不依赖 ChatView 挂载
(覆盖"切走后超时"),且精确——不会误清仍 pending 的 peer 或 /chat inline 新会话。
- src/hooks/useStreamSubscription.ts:移除 f99edbb 那条无条件清理(已被 AppShell
完整且更安全地取代;无条件版在分屏下会误清 peer 的全局单值,虽被 Set 源掩盖)。
- 入口1(/chat inline)不走 stream-session-manager 的 window event,保留 page.tsx
自身 permission_resolved case 的清理。
验证:tsc --noEmit exit 0;全量单测 3360/3360。React 状态接线无 hook-test harness,
靠 typecheck + AppShell Set 源独立保护 + 代码审查。
guardrail:徽章单值清理收敛到 AppShell 全局 handler 这一处(不依赖任何 ChatView
挂载),与 Set 源对超时 / resolved 态一致。
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: 用户反馈 + 计划 Phase 2——图片/文件等普通上下文过大时弹"上下文太多,发送前
请确认"的阻断式横幅,必须再点一次才能发;图片发送被二次确认卡住。
Triage(当前源码): run-checkpoint.ts 的 context-cost-change reason 设了
requiresConfirm:true + confirm-context-cost 动作;两个聊天入口(page.tsx:288 /
ChatView.tsx:368)都用 `checkpointReasons.filter(r => r.requiresConfirm)` 派生
blockingReasonIds,MessageInput:511 据此 throw 'run-checkpoint-blocked' 阻断发送。
即估算型上下文大小被做成了二次确认阻断——违反"非破坏性、用户主动发起的发送不得因
估算风险被阻断"。注:context-cost 是当前唯一的 requiresConfirm reason。
Fix:
- run-checkpoint.ts: context-cost-change 去掉 requiresConfirm + confirm 动作 →
纯 info-tone 非阻断 heads-up,永不进入 blockingReasonIds,图片/文件首个 Enter 即发。
- i18n en/zh: 文案去掉"Confirm before sending / 发送前请确认"的确认框架,改为纯提示。
- 阻断/bypass 基建(blockingReasonIds + MessageInput 'run-checkpoint-blocked' throw +
PromptInput 截图保留契约 + confirm→bypass 桥)**保留**:它保护任何被拒提交、且按计划
留给未来真实危险动作(写/删/执行/提权——那些走权限系统)。两入口的 confirm-context-cost
处理器改注释为 dormant,逻辑不动。
语义验收: 普通上下文过大只出非阻断提示;阻断只留给真实危险动作;图片发送不再二次确认。
Verify: typecheck 通过;run-checkpoint.test.ts 把"requiresConfirm=true + confirm action"
断言翻为"info-tone 非阻断、无 requiresConfirm、无 action",scope-guard 的"每个 reason 必有
action"放宽为"context-cost info-only 无 action、其余有";run-checkpoint-blocking.test.ts
更新前提(无 reason 当前 requiresConfirm)+ bypass-machine 样例 id 改假想值,保留通用机器与
截图保留契约;全量单测 3368/3368。
Guardrail: run-checkpoint.test.ts 钉死 context-cost 非阻断(notEqual requiresConfirm true
+ action undefined),防回退到把估算上下文做成阻断确认。
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 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>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 op7418#2 补充连续水位推进机制
- 新增决策 op7418#9(图片接收)和 op7418#10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <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
… 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
[P1] /api/providers/models route: DEFAULT_MODELS.sonnet + ENV_ALIAS_TO_UPSTREAM.sonnet
claude-sonnet-4-20250514 → claude-sonnet-4-6(API 层 op7418#23 之前未闭环)
[P1] /api/media/jobs/plan fallback + /api/skills/search MODEL_MAP: 旧 Sonnet → claude-sonnet-4-6;
skills/search 的 opus(4.6) / 旧 haiku 一并修正 → claude-opus-4-7 / claude-haiku-4-5-20251001
[P2] isOpusAdaptiveThinkingModel regex /opus-?4-?[78]/ → /opus-?4[-.]?[78]/,同时匹配 dotted
OpenRouter slug anthropic/claude-opus-4.8(不再依赖"dotted 不走此 sanitizer"的假设)
[P2] post-refactor-cleanup.md Open Question op7418#2:OpenRouter Opus 4.8 不再写 deferred(已接入)
测试: opus-4-8-sonnet-4-6.test.ts 扩到 18 断言(+dotted slug +路由层 op7418#23 source-pin 含 skills opus/haiku)。
验证: tsc exit 0、targeted 18/18、业务代码无 claude-sonnet-4-20250514 残留。
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
用户 2026-05-29 跑通三条真实凭据 smoke(Smoke Ledger 已记):
- OpenRouter Opus 4.8 (opus-4-8 → anthropic/claude-opus-4.8): OPENROUTER_OPUS48_OK
- Anthropic direct Opus 4.8 (Claude Code 账户): OPUS48_CLAUDE_ACCOUNT_A/B_OK
- Sonnet 4.6 op7418#23 反例路径: SONNET46_SMOKE_A/B_OK
状态表 Phase A → 完成;Open Question op7418#2 smoke 标已通过。
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
在用户本机做隔离 POC + 端到端 POC(findCodexBinary 解析到的 .app codex
0.133.0 + 真实 ~/.codex),证伪了原日志推断「xhigh 配置让 app-server 挂掉」:
- .app codex 0.133.0 原生接受 model_reasoning_effort=xhigh(initialize +
model/list 全 OK,不退出);对 max/垃圾值只警告不致命。
- 端到端:当前二进制 + 真实含 xhigh 的 ~/.codex → initialize OK + model/list
返回 6 个真实模型 → 用户 Codex 现在就是通的。
- 日志里失败的是 /opt/homebrew/bin/codex(现已卸载),更旧/更严、只认 4 档且
把配置反序列化失败当致命退出。login shell PATH 已无任何 codex,打包 app 只会
解析到 .app 0.133.0。
修正:
- 顶部新增「POC 实测修正」权威段(外部事实 pin 0.133.0 / 仓库 file:line / 推断三层)。
- 标注下方「日志确认」claim op7418#2 与修复表 row1 为已更正,指向新段,保留推断留痕。
- 修复方向改判:立即动作=重启 CodePilot(不用改 config);P0=app-server init 期
退出时立即 reject pending init(不等 30s,这才是三症状变慢的真因);P1=clamp
CodePilot 发给 Codex 的 effort;否决 spawn -c 覆盖(no-op+覆盖用户配置+不可验证)。
- 同步 research/README.md 索引。
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
b853188 把侧栏"需要批准"徽章的清理放在 useStreamSubscription,但它依赖当前会话的
ChatView 挂载:用户切到别的会话后该 hook 退订(useStreamSubscription cleanup),
后续 timeout 的 snapshot-updated 不再触发清理。AppShell 的全局 handler 会从所有
active stream 重算 pendingApprovalSessionIds(Set 源,已正确排除超时),但没有清全局
单值 pendingApprovalSessionId;侧栏 needsApproval 仍 OR 这两个来源(ChatListPanel)
→ 切走后单值残留,徽章不灭直到 stream 结束。
改动:
- src/components/layout/AppShell.tsx:全局 stream-session-event handler 改为接收
event,重算 approvals 后,若 pendingApprovalSessionId === detail.sessionId 且该
session 不在 approvals,就清单值(函数式更新 + 守卫)。这不依赖 ChatView 挂载
(覆盖"切走后超时"),且精确——不会误清仍 pending 的 peer 或 /chat inline 新会话。
- src/hooks/useStreamSubscription.ts:移除 b853188 那条无条件清理(已被 AppShell
完整且更安全地取代;无条件版在分屏下会误清 peer 的全局单值,虽被 Set 源掩盖)。
- 入口1(/chat inline)不走 stream-session-manager 的 window event,保留 page.tsx
自身 permission_resolved case 的清理。
验证:tsc --noEmit exit 0;全量单测 3360/3360。React 状态接线无 hook-test harness,
靠 typecheck + AppShell Set 源独立保护 + 代码审查。
guardrail:徽章单值清理收敛到 AppShell 全局 handler 这一处(不依赖任何 ChatView
挂载),与 Set 源对超时 / resolved 态一致。
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: 用户反馈 + 计划 Phase 2——图片/文件等普通上下文过大时弹"上下文太多,发送前
请确认"的阻断式横幅,必须再点一次才能发;图片发送被二次确认卡住。
Triage(当前源码): run-checkpoint.ts 的 context-cost-change reason 设了
requiresConfirm:true + confirm-context-cost 动作;两个聊天入口(page.tsx:288 /
ChatView.tsx:368)都用 `checkpointReasons.filter(r => r.requiresConfirm)` 派生
blockingReasonIds,MessageInput:511 据此 throw 'run-checkpoint-blocked' 阻断发送。
即估算型上下文大小被做成了二次确认阻断——违反"非破坏性、用户主动发起的发送不得因
估算风险被阻断"。注:context-cost 是当前唯一的 requiresConfirm reason。
Fix:
- run-checkpoint.ts: context-cost-change 去掉 requiresConfirm + confirm 动作 →
纯 info-tone 非阻断 heads-up,永不进入 blockingReasonIds,图片/文件首个 Enter 即发。
- i18n en/zh: 文案去掉"Confirm before sending / 发送前请确认"的确认框架,改为纯提示。
- 阻断/bypass 基建(blockingReasonIds + MessageInput 'run-checkpoint-blocked' throw +
PromptInput 截图保留契约 + confirm→bypass 桥)**保留**:它保护任何被拒提交、且按计划
留给未来真实危险动作(写/删/执行/提权——那些走权限系统)。两入口的 confirm-context-cost
处理器改注释为 dormant,逻辑不动。
语义验收: 普通上下文过大只出非阻断提示;阻断只留给真实危险动作;图片发送不再二次确认。
Verify: typecheck 通过;run-checkpoint.test.ts 把"requiresConfirm=true + confirm action"
断言翻为"info-tone 非阻断、无 requiresConfirm、无 action",scope-guard 的"每个 reason 必有
action"放宽为"context-cost info-only 无 action、其余有";run-checkpoint-blocking.test.ts
更新前提(无 reason 当前 requiresConfirm)+ bypass-machine 样例 id 改假想值,保留通用机器与
截图保留契约;全量单测 3368/3368。
Guardrail: run-checkpoint.test.ts 钉死 context-cost 非阻断(notEqual requiresConfirm true
+ action undefined),防回退到把估算上下文做成阻断确认。
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
- 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>
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.

3 participants

@arthurlee116@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('^' + ".*" + ' fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题 by arthurlee116 · Pull Request #2 · op7418/CodePilot · GitHub
Skip to content

fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题 - #2

Closed
arthurlee116 wants to merge 1 commit into
op7418:mainfrom
arthurlee116:fix/build-rmsync-recursive
Closed

fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题#2
arthurlee116 wants to merge 1 commit into
op7418:mainfrom
arthurlee116:fix/build-rmsync-recursive

Conversation

@arthurlee116

Copy link
Copy Markdown

问题

执行 npm run electron:build 时,scripts/build-electron.mjs 在解析 .next/standalone/.next/node_modules/ 中的符号链接时报错:

Error: Path is a directory: .next/standalone/.next/node_modules/better-sqlite3-90e2652d1716b047
at Object.rmSync (node:fs:1236:18)
at resolveStandaloneSymlinks (file:///...CodePilot/scripts/build-electron.mjs:18:12)

部分条目(如 better-sqlite3-90e2652d1716b047)是指向目录的符号链接,fs.rmSync() 在未传入 { recursive: true } 时会抛出 ERR_FS_EISDIR 错误。

修复

fs.rmSync() 添加 { recursive: true, force: true } 参数。

CopilotAI review requested due to automatic review settings February 7, 2026 07:00

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

该 PR 修复 Electron 构建脚本在处理 Next.js standalone 输出中的“指向目录的符号链接”时,因 fs.rmSync() 未开启递归删除而报错的问题,保证 npm run electron:build 可正常执行并为后续 electron-builder 打包准备好可复制的目录结构。

Changes:

  • 为删除 standalone 目录下的符号链接时的 fs.rmSync() 增加 { recursive: true, force: true } 参数,避免遇到目录型符号链接时报 ERR_FS_EISDIR

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@op7418

Copy link
Copy Markdown
Owner

Thanks for the fix! This change was already included in PR #7 which has been merged. Closing as duplicate.

@op7418op7418 closed this Feb 7, 2026
op7418 pushed a commit that referenced this pull request Mar 2, 2026
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 #2 补充连续水位推进机制
- 新增决策 #9(图片接收)和 #10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 1, 2026
在用户本机做隔离 POC + 端到端 POC(findCodexBinary 解析到的 .app codex
0.133.0 + 真实 ~/.codex),证伪了原日志推断「xhigh 配置让 app-server 挂掉」:
- .app codex 0.133.0 原生接受 model_reasoning_effort=xhigh(initialize +
model/list 全 OK,不退出);对 max/垃圾值只警告不致命。
- 端到端:当前二进制 + 真实含 xhigh 的 ~/.codex → initialize OK + model/list
返回 6 个真实模型 → 用户 Codex 现在就是通的。
- 日志里失败的是 /opt/homebrew/bin/codex(现已卸载),更旧/更严、只认 4 档且
把配置反序列化失败当致命退出。login shell PATH 已无任何 codex,打包 app 只会
解析到 .app 0.133.0。
修正:
- 顶部新增「POC 实测修正」权威段(外部事实 pin 0.133.0 / 仓库 file:line / 推断三层)。
- 标注下方「日志确认」claim #2 与修复表 row1 为已更正,指向新段,保留推断留痕。
- 修复方向改判:立即动作=重启 CodePilot(不用改 config);P0=app-server init 期
退出时立即 reject pending init(不等 30s,这才是三症状变慢的真因);P1=clamp
CodePilot 发给 Codex 的 effort;否决 spawn -c 覆盖(no-op+覆盖用户配置+不可验证)。
- 同步 research/README.md 索引。
op7418 added a commit that referenced this pull request Jun 28, 2026
f99edbb 把侧栏"需要批准"徽章的清理放在 useStreamSubscription,但它依赖当前会话的
ChatView 挂载:用户切到别的会话后该 hook 退订(useStreamSubscription cleanup),
后续 timeout 的 snapshot-updated 不再触发清理。AppShell 的全局 handler 会从所有
active stream 重算 pendingApprovalSessionIds(Set 源,已正确排除超时),但没有清全局
单值 pendingApprovalSessionId;侧栏 needsApproval 仍 OR 这两个来源(ChatListPanel)
→ 切走后单值残留,徽章不灭直到 stream 结束。
改动:
- src/components/layout/AppShell.tsx:全局 stream-session-event handler 改为接收
event,重算 approvals 后,若 pendingApprovalSessionId === detail.sessionId 且该
session 不在 approvals,就清单值(函数式更新 + 守卫)。这不依赖 ChatView 挂载
(覆盖"切走后超时"),且精确——不会误清仍 pending 的 peer 或 /chat inline 新会话。
- src/hooks/useStreamSubscription.ts:移除 f99edbb 那条无条件清理(已被 AppShell
完整且更安全地取代;无条件版在分屏下会误清 peer 的全局单值,虽被 Set 源掩盖)。
- 入口1(/chat inline)不走 stream-session-manager 的 window event,保留 page.tsx
自身 permission_resolved case 的清理。
验证:tsc --noEmit exit 0;全量单测 3360/3360。React 状态接线无 hook-test harness,
靠 typecheck + AppShell Set 源独立保护 + 代码审查。
guardrail:徽章单值清理收敛到 AppShell 全局 handler 这一处(不依赖任何 ChatView
挂载),与 Set 源对超时 / resolved 态一致。
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: 用户反馈 + 计划 Phase 2——图片/文件等普通上下文过大时弹"上下文太多,发送前
请确认"的阻断式横幅,必须再点一次才能发;图片发送被二次确认卡住。
Triage(当前源码): run-checkpoint.ts 的 context-cost-change reason 设了
requiresConfirm:true + confirm-context-cost 动作;两个聊天入口(page.tsx:288 /
ChatView.tsx:368)都用 `checkpointReasons.filter(r => r.requiresConfirm)` 派生
blockingReasonIds,MessageInput:511 据此 throw 'run-checkpoint-blocked' 阻断发送。
即估算型上下文大小被做成了二次确认阻断——违反"非破坏性、用户主动发起的发送不得因
估算风险被阻断"。注:context-cost 是当前唯一的 requiresConfirm reason。
Fix:
- run-checkpoint.ts: context-cost-change 去掉 requiresConfirm + confirm 动作 →
纯 info-tone 非阻断 heads-up,永不进入 blockingReasonIds,图片/文件首个 Enter 即发。
- i18n en/zh: 文案去掉"Confirm before sending / 发送前请确认"的确认框架,改为纯提示。
- 阻断/bypass 基建(blockingReasonIds + MessageInput 'run-checkpoint-blocked' throw +
PromptInput 截图保留契约 + confirm→bypass 桥)**保留**:它保护任何被拒提交、且按计划
留给未来真实危险动作(写/删/执行/提权——那些走权限系统)。两入口的 confirm-context-cost
处理器改注释为 dormant,逻辑不动。
语义验收: 普通上下文过大只出非阻断提示;阻断只留给真实危险动作;图片发送不再二次确认。
Verify: typecheck 通过;run-checkpoint.test.ts 把"requiresConfirm=true + confirm action"
断言翻为"info-tone 非阻断、无 requiresConfirm、无 action",scope-guard 的"每个 reason 必有
action"放宽为"context-cost info-only 无 action、其余有";run-checkpoint-blocking.test.ts
更新前提(无 reason 当前 requiresConfirm)+ bypass-machine 样例 id 改假想值,保留通用机器与
截图保留契约;全量单测 3368/3368。
Guardrail: run-checkpoint.test.ts 钉死 context-cost 非阻断(notEqual requiresConfirm true
+ action undefined),防回退到把估算上下文做成阻断确认。
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 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>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 op7418#2 补充连续水位推进机制
- 新增决策 op7418#9(图片接收)和 op7418#10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <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
… 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
[P1] /api/providers/models route: DEFAULT_MODELS.sonnet + ENV_ALIAS_TO_UPSTREAM.sonnet
claude-sonnet-4-20250514 → claude-sonnet-4-6(API 层 op7418#23 之前未闭环)
[P1] /api/media/jobs/plan fallback + /api/skills/search MODEL_MAP: 旧 Sonnet → claude-sonnet-4-6;
skills/search 的 opus(4.6) / 旧 haiku 一并修正 → claude-opus-4-7 / claude-haiku-4-5-20251001
[P2] isOpusAdaptiveThinkingModel regex /opus-?4-?[78]/ → /opus-?4[-.]?[78]/,同时匹配 dotted
OpenRouter slug anthropic/claude-opus-4.8(不再依赖"dotted 不走此 sanitizer"的假设)
[P2] post-refactor-cleanup.md Open Question op7418#2:OpenRouter Opus 4.8 不再写 deferred(已接入)
测试: opus-4-8-sonnet-4-6.test.ts 扩到 18 断言(+dotted slug +路由层 op7418#23 source-pin 含 skills opus/haiku)。
验证: tsc exit 0、targeted 18/18、业务代码无 claude-sonnet-4-20250514 残留。
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
用户 2026-05-29 跑通三条真实凭据 smoke(Smoke Ledger 已记):
- OpenRouter Opus 4.8 (opus-4-8 → anthropic/claude-opus-4.8): OPENROUTER_OPUS48_OK
- Anthropic direct Opus 4.8 (Claude Code 账户): OPUS48_CLAUDE_ACCOUNT_A/B_OK
- Sonnet 4.6 op7418#23 反例路径: SONNET46_SMOKE_A/B_OK
状态表 Phase A → 完成;Open Question op7418#2 smoke 标已通过。
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
在用户本机做隔离 POC + 端到端 POC(findCodexBinary 解析到的 .app codex
0.133.0 + 真实 ~/.codex),证伪了原日志推断「xhigh 配置让 app-server 挂掉」:
- .app codex 0.133.0 原生接受 model_reasoning_effort=xhigh(initialize +
model/list 全 OK,不退出);对 max/垃圾值只警告不致命。
- 端到端:当前二进制 + 真实含 xhigh 的 ~/.codex → initialize OK + model/list
返回 6 个真实模型 → 用户 Codex 现在就是通的。
- 日志里失败的是 /opt/homebrew/bin/codex(现已卸载),更旧/更严、只认 4 档且
把配置反序列化失败当致命退出。login shell PATH 已无任何 codex,打包 app 只会
解析到 .app 0.133.0。
修正:
- 顶部新增「POC 实测修正」权威段(外部事实 pin 0.133.0 / 仓库 file:line / 推断三层)。
- 标注下方「日志确认」claim op7418#2 与修复表 row1 为已更正,指向新段,保留推断留痕。
- 修复方向改判:立即动作=重启 CodePilot(不用改 config);P0=app-server init 期
退出时立即 reject pending init(不等 30s,这才是三症状变慢的真因);P1=clamp
CodePilot 发给 Codex 的 effort;否决 spawn -c 覆盖(no-op+覆盖用户配置+不可验证)。
- 同步 research/README.md 索引。
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
b853188 把侧栏"需要批准"徽章的清理放在 useStreamSubscription,但它依赖当前会话的
ChatView 挂载:用户切到别的会话后该 hook 退订(useStreamSubscription cleanup),
后续 timeout 的 snapshot-updated 不再触发清理。AppShell 的全局 handler 会从所有
active stream 重算 pendingApprovalSessionIds(Set 源,已正确排除超时),但没有清全局
单值 pendingApprovalSessionId;侧栏 needsApproval 仍 OR 这两个来源(ChatListPanel)
→ 切走后单值残留,徽章不灭直到 stream 结束。
改动:
- src/components/layout/AppShell.tsx:全局 stream-session-event handler 改为接收
event,重算 approvals 后,若 pendingApprovalSessionId === detail.sessionId 且该
session 不在 approvals,就清单值(函数式更新 + 守卫)。这不依赖 ChatView 挂载
(覆盖"切走后超时"),且精确——不会误清仍 pending 的 peer 或 /chat inline 新会话。
- src/hooks/useStreamSubscription.ts:移除 b853188 那条无条件清理(已被 AppShell
完整且更安全地取代;无条件版在分屏下会误清 peer 的全局单值,虽被 Set 源掩盖)。
- 入口1(/chat inline)不走 stream-session-manager 的 window event,保留 page.tsx
自身 permission_resolved case 的清理。
验证:tsc --noEmit exit 0;全量单测 3360/3360。React 状态接线无 hook-test harness,
靠 typecheck + AppShell Set 源独立保护 + 代码审查。
guardrail:徽章单值清理收敛到 AppShell 全局 handler 这一处(不依赖任何 ChatView
挂载),与 Set 源对超时 / resolved 态一致。
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: 用户反馈 + 计划 Phase 2——图片/文件等普通上下文过大时弹"上下文太多,发送前
请确认"的阻断式横幅,必须再点一次才能发;图片发送被二次确认卡住。
Triage(当前源码): run-checkpoint.ts 的 context-cost-change reason 设了
requiresConfirm:true + confirm-context-cost 动作;两个聊天入口(page.tsx:288 /
ChatView.tsx:368)都用 `checkpointReasons.filter(r => r.requiresConfirm)` 派生
blockingReasonIds,MessageInput:511 据此 throw 'run-checkpoint-blocked' 阻断发送。
即估算型上下文大小被做成了二次确认阻断——违反"非破坏性、用户主动发起的发送不得因
估算风险被阻断"。注:context-cost 是当前唯一的 requiresConfirm reason。
Fix:
- run-checkpoint.ts: context-cost-change 去掉 requiresConfirm + confirm 动作 →
纯 info-tone 非阻断 heads-up,永不进入 blockingReasonIds,图片/文件首个 Enter 即发。
- i18n en/zh: 文案去掉"Confirm before sending / 发送前请确认"的确认框架,改为纯提示。
- 阻断/bypass 基建(blockingReasonIds + MessageInput 'run-checkpoint-blocked' throw +
PromptInput 截图保留契约 + confirm→bypass 桥)**保留**:它保护任何被拒提交、且按计划
留给未来真实危险动作(写/删/执行/提权——那些走权限系统)。两入口的 confirm-context-cost
处理器改注释为 dormant,逻辑不动。
语义验收: 普通上下文过大只出非阻断提示;阻断只留给真实危险动作;图片发送不再二次确认。
Verify: typecheck 通过;run-checkpoint.test.ts 把"requiresConfirm=true + confirm action"
断言翻为"info-tone 非阻断、无 requiresConfirm、无 action",scope-guard 的"每个 reason 必有
action"放宽为"context-cost info-only 无 action、其余有";run-checkpoint-blocking.test.ts
更新前提(无 reason 当前 requiresConfirm)+ bypass-machine 样例 id 改假想值,保留通用机器与
截图保留契约;全量单测 3368/3368。
Guardrail: run-checkpoint.test.ts 钉死 context-cost 非阻断(notEqual requiresConfirm true
+ action undefined),防回退到把估算上下文做成阻断确认。
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
- 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>
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.

3 participants

@arthurlee116@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); } })(); })(); fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题 by arthurlee116 · Pull Request #2 · op7418/CodePilot · GitHub
Skip to content

fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题 - #2

Closed
arthurlee116 wants to merge 1 commit into
op7418:mainfrom
arthurlee116:fix/build-rmsync-recursive
Closed

fix: 修复构建脚本中 rmSync 无法删除目录符号链接的问题#2
arthurlee116 wants to merge 1 commit into
op7418:mainfrom
arthurlee116:fix/build-rmsync-recursive

Conversation

@arthurlee116

Copy link
Copy Markdown

问题

执行 npm run electron:build 时,scripts/build-electron.mjs 在解析 .next/standalone/.next/node_modules/ 中的符号链接时报错:

Error: Path is a directory: .next/standalone/.next/node_modules/better-sqlite3-90e2652d1716b047
at Object.rmSync (node:fs:1236:18)
at resolveStandaloneSymlinks (file:///...CodePilot/scripts/build-electron.mjs:18:12)

部分条目(如 better-sqlite3-90e2652d1716b047)是指向目录的符号链接,fs.rmSync() 在未传入 { recursive: true } 时会抛出 ERR_FS_EISDIR 错误。

修复

fs.rmSync() 添加 { recursive: true, force: true } 参数。

CopilotAI review requested due to automatic review settings February 7, 2026 07:00

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

该 PR 修复 Electron 构建脚本在处理 Next.js standalone 输出中的“指向目录的符号链接”时,因 fs.rmSync() 未开启递归删除而报错的问题,保证 npm run electron:build 可正常执行并为后续 electron-builder 打包准备好可复制的目录结构。

Changes:

  • 为删除 standalone 目录下的符号链接时的 fs.rmSync() 增加 { recursive: true, force: true } 参数,避免遇到目录型符号链接时报 ERR_FS_EISDIR

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@op7418

Copy link
Copy Markdown
Owner

Thanks for the fix! This change was already included in PR #7 which has been merged. Closing as duplicate.

@op7418op7418 closed this Feb 7, 2026
op7418 pushed a commit that referenced this pull request Mar 2, 2026
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 #2 补充连续水位推进机制
- 新增决策 #9(图片接收)和 #10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
op7418 added a commit that referenced this pull request Jun 1, 2026
在用户本机做隔离 POC + 端到端 POC(findCodexBinary 解析到的 .app codex
0.133.0 + 真实 ~/.codex),证伪了原日志推断「xhigh 配置让 app-server 挂掉」:
- .app codex 0.133.0 原生接受 model_reasoning_effort=xhigh(initialize +
model/list 全 OK,不退出);对 max/垃圾值只警告不致命。
- 端到端:当前二进制 + 真实含 xhigh 的 ~/.codex → initialize OK + model/list
返回 6 个真实模型 → 用户 Codex 现在就是通的。
- 日志里失败的是 /opt/homebrew/bin/codex(现已卸载),更旧/更严、只认 4 档且
把配置反序列化失败当致命退出。login shell PATH 已无任何 codex,打包 app 只会
解析到 .app 0.133.0。
修正:
- 顶部新增「POC 实测修正」权威段(外部事实 pin 0.133.0 / 仓库 file:line / 推断三层)。
- 标注下方「日志确认」claim #2 与修复表 row1 为已更正,指向新段,保留推断留痕。
- 修复方向改判:立即动作=重启 CodePilot(不用改 config);P0=app-server init 期
退出时立即 reject pending init(不等 30s,这才是三症状变慢的真因);P1=clamp
CodePilot 发给 Codex 的 effort;否决 spawn -c 覆盖(no-op+覆盖用户配置+不可验证)。
- 同步 research/README.md 索引。
op7418 added a commit that referenced this pull request Jun 28, 2026
f99edbb 把侧栏"需要批准"徽章的清理放在 useStreamSubscription,但它依赖当前会话的
ChatView 挂载:用户切到别的会话后该 hook 退订(useStreamSubscription cleanup),
后续 timeout 的 snapshot-updated 不再触发清理。AppShell 的全局 handler 会从所有
active stream 重算 pendingApprovalSessionIds(Set 源,已正确排除超时),但没有清全局
单值 pendingApprovalSessionId;侧栏 needsApproval 仍 OR 这两个来源(ChatListPanel)
→ 切走后单值残留,徽章不灭直到 stream 结束。
改动:
- src/components/layout/AppShell.tsx:全局 stream-session-event handler 改为接收
event,重算 approvals 后,若 pendingApprovalSessionId === detail.sessionId 且该
session 不在 approvals,就清单值(函数式更新 + 守卫)。这不依赖 ChatView 挂载
(覆盖"切走后超时"),且精确——不会误清仍 pending 的 peer 或 /chat inline 新会话。
- src/hooks/useStreamSubscription.ts:移除 f99edbb 那条无条件清理(已被 AppShell
完整且更安全地取代;无条件版在分屏下会误清 peer 的全局单值,虽被 Set 源掩盖)。
- 入口1(/chat inline)不走 stream-session-manager 的 window event,保留 page.tsx
自身 permission_resolved case 的清理。
验证:tsc --noEmit exit 0;全量单测 3360/3360。React 状态接线无 hook-test harness,
靠 typecheck + AppShell Set 源独立保护 + 代码审查。
guardrail:徽章单值清理收敛到 AppShell 全局 handler 这一处(不依赖任何 ChatView
挂载),与 Set 源对超时 / resolved 态一致。
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: 用户反馈 + 计划 Phase 2——图片/文件等普通上下文过大时弹"上下文太多,发送前
请确认"的阻断式横幅,必须再点一次才能发;图片发送被二次确认卡住。
Triage(当前源码): run-checkpoint.ts 的 context-cost-change reason 设了
requiresConfirm:true + confirm-context-cost 动作;两个聊天入口(page.tsx:288 /
ChatView.tsx:368)都用 `checkpointReasons.filter(r => r.requiresConfirm)` 派生
blockingReasonIds,MessageInput:511 据此 throw 'run-checkpoint-blocked' 阻断发送。
即估算型上下文大小被做成了二次确认阻断——违反"非破坏性、用户主动发起的发送不得因
估算风险被阻断"。注:context-cost 是当前唯一的 requiresConfirm reason。
Fix:
- run-checkpoint.ts: context-cost-change 去掉 requiresConfirm + confirm 动作 →
纯 info-tone 非阻断 heads-up,永不进入 blockingReasonIds,图片/文件首个 Enter 即发。
- i18n en/zh: 文案去掉"Confirm before sending / 发送前请确认"的确认框架,改为纯提示。
- 阻断/bypass 基建(blockingReasonIds + MessageInput 'run-checkpoint-blocked' throw +
PromptInput 截图保留契约 + confirm→bypass 桥)**保留**:它保护任何被拒提交、且按计划
留给未来真实危险动作(写/删/执行/提权——那些走权限系统)。两入口的 confirm-context-cost
处理器改注释为 dormant,逻辑不动。
语义验收: 普通上下文过大只出非阻断提示;阻断只留给真实危险动作;图片发送不再二次确认。
Verify: typecheck 通过;run-checkpoint.test.ts 把"requiresConfirm=true + confirm action"
断言翻为"info-tone 非阻断、无 requiresConfirm、无 action",scope-guard 的"每个 reason 必有
action"放宽为"context-cost info-only 无 action、其余有";run-checkpoint-blocking.test.ts
更新前提(无 reason 当前 requiresConfirm)+ bypass-machine 样例 id 改假想值,保留通用机器与
截图保留契约;全量单测 3368/3368。
Guardrail: run-checkpoint.test.ts 钉死 context-cost 非阻断(notEqual requiresConfirm true
+ action undefined),防回退到把估算上下文做成阻断确认。
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 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>
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
- 目录结构增加 telegram-media.ts
- 数据流图补充图片/相册处理路径
- 设计决策 op7418#2 补充连续水位推进机制
- 新增决策 op7418#9(图片接收)和 op7418#10(DB 格式统一)
- 设置项表增加 image_enabled 和 max_image_size
Co-Authored-By: Claude Opus 4.6 <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
… 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
[P1] /api/providers/models route: DEFAULT_MODELS.sonnet + ENV_ALIAS_TO_UPSTREAM.sonnet
claude-sonnet-4-20250514 → claude-sonnet-4-6(API 层 op7418#23 之前未闭环)
[P1] /api/media/jobs/plan fallback + /api/skills/search MODEL_MAP: 旧 Sonnet → claude-sonnet-4-6;
skills/search 的 opus(4.6) / 旧 haiku 一并修正 → claude-opus-4-7 / claude-haiku-4-5-20251001
[P2] isOpusAdaptiveThinkingModel regex /opus-?4-?[78]/ → /opus-?4[-.]?[78]/,同时匹配 dotted
OpenRouter slug anthropic/claude-opus-4.8(不再依赖"dotted 不走此 sanitizer"的假设)
[P2] post-refactor-cleanup.md Open Question op7418#2:OpenRouter Opus 4.8 不再写 deferred(已接入)
测试: opus-4-8-sonnet-4-6.test.ts 扩到 18 断言(+dotted slug +路由层 op7418#23 source-pin 含 skills opus/haiku)。
验证: tsc exit 0、targeted 18/18、业务代码无 claude-sonnet-4-20250514 残留。
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
用户 2026-05-29 跑通三条真实凭据 smoke(Smoke Ledger 已记):
- OpenRouter Opus 4.8 (opus-4-8 → anthropic/claude-opus-4.8): OPENROUTER_OPUS48_OK
- Anthropic direct Opus 4.8 (Claude Code 账户): OPUS48_CLAUDE_ACCOUNT_A/B_OK
- Sonnet 4.6 op7418#23 反例路径: SONNET46_SMOKE_A/B_OK
状态表 Phase A → 完成;Open Question op7418#2 smoke 标已通过。
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
在用户本机做隔离 POC + 端到端 POC(findCodexBinary 解析到的 .app codex
0.133.0 + 真实 ~/.codex),证伪了原日志推断「xhigh 配置让 app-server 挂掉」:
- .app codex 0.133.0 原生接受 model_reasoning_effort=xhigh(initialize +
model/list 全 OK,不退出);对 max/垃圾值只警告不致命。
- 端到端:当前二进制 + 真实含 xhigh 的 ~/.codex → initialize OK + model/list
返回 6 个真实模型 → 用户 Codex 现在就是通的。
- 日志里失败的是 /opt/homebrew/bin/codex(现已卸载),更旧/更严、只认 4 档且
把配置反序列化失败当致命退出。login shell PATH 已无任何 codex,打包 app 只会
解析到 .app 0.133.0。
修正:
- 顶部新增「POC 实测修正」权威段(外部事实 pin 0.133.0 / 仓库 file:line / 推断三层)。
- 标注下方「日志确认」claim op7418#2 与修复表 row1 为已更正,指向新段,保留推断留痕。
- 修复方向改判:立即动作=重启 CodePilot(不用改 config);P0=app-server init 期
退出时立即 reject pending init(不等 30s,这才是三症状变慢的真因);P1=clamp
CodePilot 发给 Codex 的 effort;否决 spawn -c 覆盖(no-op+覆盖用户配置+不可验证)。
- 同步 research/README.md 索引。
youcho2 pushed a commit to youcho2/CodePilot that referenced this pull request Aug 11, 2026
b853188 把侧栏"需要批准"徽章的清理放在 useStreamSubscription,但它依赖当前会话的
ChatView 挂载:用户切到别的会话后该 hook 退订(useStreamSubscription cleanup),
后续 timeout 的 snapshot-updated 不再触发清理。AppShell 的全局 handler 会从所有
active stream 重算 pendingApprovalSessionIds(Set 源,已正确排除超时),但没有清全局
单值 pendingApprovalSessionId;侧栏 needsApproval 仍 OR 这两个来源(ChatListPanel)
→ 切走后单值残留,徽章不灭直到 stream 结束。
改动:
- src/components/layout/AppShell.tsx:全局 stream-session-event handler 改为接收
event,重算 approvals 后,若 pendingApprovalSessionId === detail.sessionId 且该
session 不在 approvals,就清单值(函数式更新 + 守卫)。这不依赖 ChatView 挂载
(覆盖"切走后超时"),且精确——不会误清仍 pending 的 peer 或 /chat inline 新会话。
- src/hooks/useStreamSubscription.ts:移除 b853188 那条无条件清理(已被 AppShell
完整且更安全地取代;无条件版在分屏下会误清 peer 的全局单值,虽被 Set 源掩盖)。
- 入口1(/chat inline)不走 stream-session-manager 的 window event,保留 page.tsx
自身 permission_resolved case 的清理。
验证:tsc --noEmit exit 0;全量单测 3360/3360。React 状态接线无 hook-test harness,
靠 typecheck + AppShell Set 源独立保护 + 代码审查。
guardrail:徽章单值清理收敛到 AppShell 全局 handler 这一处(不依赖任何 ChatView
挂载),与 Set 源对超时 / resolved 态一致。
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: 用户反馈 + 计划 Phase 2——图片/文件等普通上下文过大时弹"上下文太多,发送前
请确认"的阻断式横幅,必须再点一次才能发;图片发送被二次确认卡住。
Triage(当前源码): run-checkpoint.ts 的 context-cost-change reason 设了
requiresConfirm:true + confirm-context-cost 动作;两个聊天入口(page.tsx:288 /
ChatView.tsx:368)都用 `checkpointReasons.filter(r => r.requiresConfirm)` 派生
blockingReasonIds,MessageInput:511 据此 throw 'run-checkpoint-blocked' 阻断发送。
即估算型上下文大小被做成了二次确认阻断——违反"非破坏性、用户主动发起的发送不得因
估算风险被阻断"。注:context-cost 是当前唯一的 requiresConfirm reason。
Fix:
- run-checkpoint.ts: context-cost-change 去掉 requiresConfirm + confirm 动作 →
纯 info-tone 非阻断 heads-up,永不进入 blockingReasonIds,图片/文件首个 Enter 即发。
- i18n en/zh: 文案去掉"Confirm before sending / 发送前请确认"的确认框架,改为纯提示。
- 阻断/bypass 基建(blockingReasonIds + MessageInput 'run-checkpoint-blocked' throw +
PromptInput 截图保留契约 + confirm→bypass 桥)**保留**:它保护任何被拒提交、且按计划
留给未来真实危险动作(写/删/执行/提权——那些走权限系统)。两入口的 confirm-context-cost
处理器改注释为 dormant,逻辑不动。
语义验收: 普通上下文过大只出非阻断提示;阻断只留给真实危险动作;图片发送不再二次确认。
Verify: typecheck 通过;run-checkpoint.test.ts 把"requiresConfirm=true + confirm action"
断言翻为"info-tone 非阻断、无 requiresConfirm、无 action",scope-guard 的"每个 reason 必有
action"放宽为"context-cost info-only 无 action、其余有";run-checkpoint-blocking.test.ts
更新前提(无 reason 当前 requiresConfirm)+ bypass-machine 样例 id 改假想值,保留通用机器与
截图保留契约;全量单测 3368/3368。
Guardrail: run-checkpoint.test.ts 钉死 context-cost 非阻断(notEqual requiresConfirm true
+ action undefined),防回退到把估算上下文做成阻断确认。
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
- 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>
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.

3 participants

@arthurlee116@op7418