Skip to content

feat(plugins): unified plugin lifecycle readiness across discovery, enable, UI, scheduler, and credentials - #668

Closed
xxxxxccc wants to merge 51 commits into
makecindy:mainfrom
xxxxxccc:feat/plugin-lifecycle-readiness
Closed

feat(plugins): unified plugin lifecycle readiness across discovery, enable, UI, scheduler, and credentials#668
xxxxxccc wants to merge 51 commits into
makecindy:mainfrom
xxxxxccc:feat/plugin-lifecycle-readiness

Conversation

@xxxxxccc

@xxxxxccc xxxxxccc commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

这次改了什么

摘要

把插件生命周期统一成一等公民的 readiness 状态(ready / needs_setup / needs_reauth / degraded / blocked / unknown),贯穿 agent 发现层、启用门槛、UI 徽章、调度器与凭证失效闭环。动机:此前插件"已安装但不可用"(缺 Key、凭证被吊销、熔断)时对 agent 和用户都不透明——工具照样列出、调用才静默失败、启用开关回弹让人困惑。现在未就绪插件对 agent 降级暴露(可发现但零工具派发)、UI 有明确徽章、凭证失效能自动翻转状态。

设计来源:plugin-lifecycle-issue-2026-07-27.md,采纳推荐案 B(降级暴露)与 D2=B(enable-then-guide)。全程只动客户端,服务端 installPolicy / catalog v3 / device-link / 发布链路均不在范围内。

变更类型

  • feat 新功能
  • fix 缺陷修复
  • refactor / perf
  • docs / test / chore

范围

  • 关联 Issue / 需求:plugin-lifecycle-issue-2026-07-27
  • 本 PR 包含:
    • 统一生命周期投影 ghostLifecycle.ts(纯函数推导 readiness)+ ghosts:lifecycle invoke / ghosts:lifecycle-changed 推送
    • 发现层降级:roster 携带 readiness、ghost_list 对非 ready 插件返回 tools: [] + readiness + message
    • enable-then-guide:ghosts:set-enabled 启用后做 setup 评估并触发配置流程,不回弹
    • 插件卡片与详情页 readiness 徽章、全局启用开关语义说明
    • 调度器能力警告改走投影
    • 凭证拒绝台账:networkSlot 对 401 直接记账、403 需 body 凭证失效信号才记账(限流/业务 403 不误伤),且只记命中最终响应 host 的 key;折算 needs_reauth,重新保存 Key 清账
    • Claude / Codex 双 harness roster 过滤对齐(空 workdir 召回代价的显式取舍:用户只要在任一项目停用过某插件,所有空 workdir 会话的花名册都不再显示它——issue 1.4 两方案之外的第三方案,选它因「描述层一致不可见」比「可见但运行期被拦」更易向 agent 解释;代价已在 ghost.ts 注释披露,可回退为「建线期不过滤、运行期精确拦」)
    • 市场卡片未安装项按钮由「详情」改为「安装」直达
    • 文档与 defaultInstall 实际行为对齐
  • 明确不包含:服务端任何改动(installPolicy、catalog v3、device-link、发布)
  • 远程 / Mobile 适配结论:
    • SSH 远程工作区:不读写远程 workdir 文件、不启动远程 agent;目录级插件偏好继续走既有 session context / ALS,插件生命周期与 setup 仍由本机 Desktop Host 判定,因此无需新增 remote-file-service / cc-manager 适配。
    • device-link / 远程控制:新增 lifecycle invoke/push 只服务 Desktop 插件页本地 renderer,不是远程控制能力,不加入 device-link allowlist;远端调用插件仍走既有 Host 侧 ghost_list / ghost_call
    • Mobile UI:Mobile 当前没有插件市场或插件详情入口,本 PR 不新增手机版入口;Desktop Host 的 readiness gate 会继续约束由远程会话发起的插件调用,因此无独立 Mobile UI 适配项。
  • 用户可见变化:插件卡片/详情出现「待配置 / 需重新授权」徽章;未安装市场插件卡片按钮变「安装」;启用未配置插件时弹出配置引导
  • 是否存在 breaking change:无(CindyGhostInfo 新增可选字段 readiness? / message?,向后兼容)

UI 变化

  • 插件卡片(已安装 + 市场)与详情页头部新增 readiness 徽章

  • 详情页"作者 · 版本"行内嵌徽章,与文本同基线

  • 未安装市场卡片按钮「详情」→「安装」

  • 引用的设计规范:docs/design-rules/DESIGN.md。徽章用语义 token(--warning-accent / --error-fg on --surface-chip),不做硬编码颜色;卡片交互遵循既有 hover/active 过渡规范。

界面效果证据

改动后界面效果(结构 1:1 转录 GhostReadinessBadge / GhostPluginPage 卡片 DOM,颜色取 themes/colors.ts 同名 token 的 light/dark 双值;prefers-color-scheme 自动适配系统明暗)。浏览器打开即渲染:

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<title>PR #668 生命周期徽章 — 界面效果证据</title>
<style>
  /* CSS 变量取值转录自 apps/desktop/src/renderer/themes/colors.ts 的 registerColor
     定义(与线上渲染一致);prefers-color-scheme 自动切换明暗两套 token。 */
  :root {
    --surface-chip: #e5e5e5;  --warning-accent: #EA6B17;  --error-fg: #dc2626;
    --text-primary: #262626;  --text-secondary: #737373;  --text-tertiary: #a3a3a3;
    --border-default: #d7d7d4;  --background: hsl(0 0% 100%);
    color-scheme: light;
  }
  @media (prefers-color-scheme: dark) {
    :root {
      --surface-chip: #3c3c3a;  --warning-accent: #EA6B17;  --error-fg: #f87171;
      --text-primary: #d4d4d4;  --text-secondary: #a3a3a3;  --text-tertiary: #737373;
      --border-default: #3c3c3a;  --background: hsl(60 3% 14%);
      color-scheme: dark;
    }
  }
  body { margin: 0; padding: 24px; background: var(--background);
    font-family: -apple-system, "PingFang SC", "Segoe UI", sans-serif; color: var(--text-primary); }
  h2 { font-size: 14px; margin: 24px 0 8px; }
  .panel { display: flex; flex-direction: column; gap: 8px; max-width: 560px; }
  /* GhostPluginCard 行结构转录(features/plugin/GhostPluginPage.tsx) */
  .card { display: flex; align-items: center; gap: 12px;
    border: 1px solid var(--border-default); border-radius: 12px; padding: 12px; }
  .icon { width: 36px; height: 36px; border-radius: 8px; background: var(--surface-chip);
    display: flex; align-items: center; justify-content: center; font-size: 18px; flex-shrink: 0; }
  .meta { min-width: 0; flex: 1; }
  .title-row { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 500; }
  .sub-row { margin-top: 4px; font-size: 11px; color: var(--text-tertiary); }
  .desc { margin-top: 6px; font-size: 13px; line-height: 20px; color: var(--text-secondary); }
  /* GhostReadinessBadge 1:1 转录(features/plugin/GhostReadinessBadge.tsx):
     rounded-full px-2 py-0.5 text-10 font-medium leading-4
     warning: bg --surface-chip / text --warning-accent;  error: bg --surface-chip / text --error-fg */
  .badge { flex-shrink: 0; user-select: none; border-radius: 9999px; padding: 2px 8px;
    font-size: 10px; font-weight: 500; line-height: 16px; background: var(--surface-chip); }
  .badge.warning { color: var(--warning-accent); }
  .badge.error { color: var(--error-fg); }
  /* 市场卡片按钮(installable 时文案「安装」,否则「详情」+ ChevronRight) */
  .btn { display: inline-flex; align-items: center; gap: 6px; height: 32px;
    border: 1px solid var(--border-default); border-radius: 8px; padding: 0 12px;
    font-size: 12px; font-weight: 500; color: var(--text-primary); background: transparent; flex-shrink: 0; }
  /* 详情页头部「作者 · 版本」行内嵌徽章(GhostPluginDetailView.tsx:223 trailing) */
  .detail-author { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-secondary); }
</style>
</head>
<body>

<h2>插件列表卡 — readiness 徽章(ready 不渲染)</h2>
<div class="panel">
  <div class="card">
    <div class="icon">&#128269;</div>
    <div class="meta">
      <div class="title-row">Web Search <span class="badge warning">待配置</span></div>
      <div class="sub-row">官方 · v1.2.0</div>
      <div class="desc">联网搜索,Brave / Tavily 双引擎</div>
    </div>
    <button class="btn">详情 &rsaquo;</button>
  </div>
  <div class="card">
    <div class="icon">&#128269;</div>
    <div class="meta">
      <div class="title-row">Web Search <span class="badge error">需重新授权</span></div>
      <div class="sub-row">官方 · v1.2.0</div>
      <div class="desc">凭证被拒自动翻转(401 记账 &rarr; needs_reauth)</div>
    </div>
    <button class="btn">详情 &rsaquo;</button>
  </div>
  <div class="card">
    <div class="icon">&#127918;</div>
    <div class="meta">
      <div class="title-row">TapTap Maker</div>
      <div class="sub-row">官方 · v0.9.1</div>
      <div class="desc">ready 常态,不渲染徽章(与旧 UI 口径一致)</div>
    </div>
    <button class="btn">详情 &rsaquo;</button>
  </div>
</div>

<h2>市场卡片 — 未安装项按钮「详情」&rarr;「安装」</h2>
<div class="panel">
  <div class="card">
    <div class="icon">&#128230;</div>
    <div class="meta">
      <div class="title-row">Linear Sync</div>
      <div class="sub-row">社区 · v2.0.3</div>
      <div class="desc">未安装的市场插件,按钮直达安装(改动前为「详情 &rsaquo;」)</div>
    </div>
    <button class="btn">安装</button>
  </div>
</div>

<h2>详情页头部 — 「作者 · 版本」行内嵌徽章(与文本同基线)</h2>
<div class="panel">
  <div class="card">
    <div class="meta">
      <div class="title-row" style="font-size:16px">Web Search</div>
      <div class="detail-author" style="margin-top:6px">Cindy 官方 · v1.2.0 <span class="badge warning">待配置</span></div>
    </div>
  </div>
</div>

<h2>徽章全色板(四种非 ready 态)</h2>
<div class="panel" style="flex-direction:row;gap:12px;align-items:center">
  <span class="badge warning">待配置</span>
  <span class="badge error">需重新授权</span>
  <span class="badge error">运行异常</span>
  <span class="badge warning">状态未知</span>
</div>

</body>
</html>

怎么验证的

自动验证

pnpm test:unit                                      # 全仓通过;Desktop 13,405 tests,Mobile 与全部 packages/protocol workspaces 通过
pnpm --filter desktop run --if-present typecheck   # 通过
pnpm --filter cindy-tools run --if-present typecheck # package 无 typecheck script,按门禁规则跳过
pnpm exec vitest run networkSlot.test.ts ghostMcp.test.ts # 定向回归通过(Desktop 88;cindy-tools 38)
pnpm check:i18n                                    # 5540 key 全一致(434 警告为既有)
pnpm check:i18n-glossary                           # 通过
pnpm check:dco                                      # 21 commits 全部通过

全量测试使用临时 Python 3 wrapper,避免本机 python 命令解析到 Python 2.7;未修改仓库环境配置。

Prompt / tool-definition 影响实测

  • 影响指标:MCP tool-definition 前缀体积、跨会话 prompt cache 复用、未就绪插件的典型 Agent turn;未触及 translator、event loop、model route 与 usage 计量。
  • 测量方法:用 formatGhostRoster 对空花名册、2 插件代表样本、16 条上限样本测 UTF-8 体积;并用定向单测与本地 Agent turn 抽查 ghost_list → setup_plan → 重新发现 事件流。
  • 结果:空花名册新增 0 bytes;2 插件样本每个 tool description 新增 512 bytes(两个固定工具合计 1,024 bytes);16 条边界每个新增 6,965 bytes(合计 13,930 bytes)。花名册只在会话装配时取一次,单会话内 tool-definition 前缀稳定,不在 token/event 热路径重算;跨新会话会随安装/就绪快照变化,这是为了让描述层与当时可用能力一致的显式取舍。
  • 行为结论:未就绪插件仍可被 ghost_list 发现,但 tools: []setup_plan 可用占位 tool 到达配置卡且不会派发占位调用;配置完成后重新 ghost_list 才恢复真实工具。对应回归测试已覆盖。

手工验证

pnpm restart:desktop:remote --region=cn --isolated=plugin-lifecycle(独立 userData Cindy-dev-plugin-lifecycle)逐项验证通过:

  1. 降级派发:Web Search 待配置时,不带 $ 提问不派发其工具(日志确认无 ghost_call
  2. enable-then-guide:关再开 Web Search,开关停在开、徽章「待配置」、弹配置引导
  3. ghost_list 降级:Web Search tools: [] + needs_setup,TapTap Maker ready 全量工具
  4. 配置回填:填 Key 后徽章热更新消失,ghost_list 恢复 ready
  5. needs_reauth:模拟凭证拒绝后自动记账 → 徽章翻「需重新授权」→ $ 调用弹重新配置表单;422 按 owner 决策明确不纳入启发式判定

未执行的验证

  • Dark / Light 双模式未在真机逐项视觉核对;「UI 变化 → 界面效果证据」中的 HTML 用 prefers-color-scheme 自动双模式渲染(token 取值与 themes/colors.ts 一致),未做设备级截图对比
  • 调度器警告、双 harness 一致性靠单测与共享投影保证,未做端到端真机触发

风险

风险分类

  • 无已知风险
  • SQLite / migration
  • system prompt
  • 协议兼容
  • 权限 / 安全 / 用户数据
  • 存量插件兼容(批准状态 / 指纹 / manifest 校验 / 安装布局 / 包格式)
  • 原生层 / fingerprint / OTA
  • 跨平台差异
  • 其他:

影响与回滚

  • 影响范围:
    • system prompt:roster 头部两行与 readiness 标记、ghost_list / ghost_call 工具描述进入 system 段。仓库维护者已在 2026-07-28 的实施会话中明确确认按推荐案 B / D2=B 落地并保留该 MCP tool-description 调整。会话常量快照机制保证单会话前缀稳定(不逐 token 变);FORGE_GUIDE 无需同步(未改作者契约)。Prompt 体积与典型 turn 实测见「怎么验证的」。
    • 用户数据:新增 ghost-credential-rejections.json 台账(仅 secret key 名,不存凭证值),损坏时 fail-open 按空账处理,不会把可用插件判死。
    • 存量插件影响:无(对照 docs/dev-rules/plugin-security-and-authoring.md 第 5 节红线逐条自查):
      • 本链路唯一新增的落盘物就是上面那份台账(owner 作用域 userData 下的独立文件)。老版本的 userData 里没有这个文件,读到 ENOENT 即按空账处理;读取不会顺手把文件创建出来,所以旧版本回退后看到的目录形态不变。含未知字段的台账按忽略处理、不判损坏(留回滚余地)。
      • 生命周期投影全部是现有存储的现查读取GhostManager 启用态、oauth 账号面、连接清单、kv、manifest),没有新增 schema、没有新增必填字段、没有改指纹编码 / manifest 校验规则 / slot 形态 / 安装根与状态根 / .cindy 包格式 / 管子协议 / 内置 id —— 因此不存在需要 backfill 的旧数据。
      • 未就绪插件是降级暴露(花名册与 ghost_list 保留条目、不派发工具 + 引导配置),不是停用:开关照旧可点,已保存的凭证 / KV / per-plugin 偏好 / errand 配置一律不动。升级前已配置好的插件升级后仍判 ready,用户什么都不做即照旧可用。
      • 「从旧状态升级」用例:apps/desktop/src/main/cindy-brain/__tests__/ghostCredentialRejections.test.ts存量安装升级:台账缺失即空账,不降级已配置的插件 —— 断言台账文件不存在时为空账且不被创建、无台账时折算为恒等变换(ready 不会降 required)、含未知字段的台账仍可读。
      • 本 PR 命中第 5 节的「插件基座白名单确认门」(main/cindy-brain/mcp-integrations/ghost.tsshared/ghost.tspackages/cindy-tools 的 ghost 部分、renderer 侧 installErrorKey.ts / ghostPluginViewModel.ts / pluginMarketPresentation.ts),需放行人在 PR 上明确 Approve 后才能合并。
  • 回滚 / 降级方式:纯客户端改动,revert 本 PR 即恢复;台账文件为增量新增,删除不影响既有数据。无 migration、无协议变更、无 fingerprint 变化。

提交前检查

  • 已 review 完整 diff
  • 每个 commit 都带 DCO 签名(git commit -s
  • UI 改动已在「UI 变化」注明引用的设计规范章节
  • 未提交凭证、令牌或授权文件
  • 已补充必要文档
  • 已确认测试结果或说明未执行原因

Copilot AI review requested due to automatic review settings July 27, 2026 10:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR makes plugin lifecycle “readiness” a first-class state (ready / needs_setup / needs_reauth / degraded / blocked / unknown) and threads it consistently through the desktop client: agent discovery (roster + ghost_list), plugin UI badges and enable flow, scheduler capability warnings, and a runtime credential-rejection ledger that can flip plugins into reauth-required.

Changes:

  • Adds a unified lifecycle projection (main “pure” projection + shared wire types + renderer mirror) and pushes lifecycle updates via IPC.
  • Degrades exposure for non-ready plugins (discoverable but tools: [] + readiness/message), and implements “enable-then-guide” behavior (enable stays on, returns setup payload to guide the user).
  • Tracks runtime secret-key credential rejections (401/403 and certain 422s) into a local ledger and folds it into readiness as needs_reauth.

Reviewed changes

Copilot reviewed 33 out of 34 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/cindy-tools/src/types.ts Extends ghost_list/roster types with readiness + message and updated setup semantics.
packages/cindy-tools/src/ghost/mcpServer.ts Roster formatting includes readiness markers and stronger “data not instruction” guidance.
packages/cindy-tools/src/tests/ghostMcp.test.ts Updates/extends roster formatting tests for readiness markers and 2-line header.
docs/dev-rules/protocol-and-submodules.md Updates client rules doc on plugin distribution channels (builtin seeding + defaultInstall).
docs/dev-rules/plugin-security-and-authoring.md Documents readiness as the unified exposure gate and credential rejection behavior.
apps/desktop/src/shared/ipc-errors.ts Adds IPC error code for setup-status evaluation failures.
apps/desktop/src/shared/ghostLifecycle.ts New shared wire types for lifecycle projection across processes.
apps/desktop/src/renderer/vite-env.d.ts Extends renderer ElectronAPI typings for lifecycle IPC + richer scheduler capability states + setEnabled return shape.
apps/desktop/src/renderer/i18n/locales/zh-CN/common.json Adds readiness badge strings, setup-status-unavailable error, scheduler warn strings, and new aria label text.
apps/desktop/src/renderer/i18n/locales/ko/common.json Same i18n additions for Korean.
apps/desktop/src/renderer/i18n/locales/ja/common.json Same i18n additions for Japanese.
apps/desktop/src/renderer/i18n/locales/en/common.json Same i18n additions for English.
apps/desktop/src/renderer/features/scheduler/components/ScriptCapabilityMultiSelect.tsx Shows new warning variants for capability availability (needs setup/reauth/degraded).
apps/desktop/src/renderer/features/plugin/GhostReadinessBadge.tsx New readiness badge component (non-ready only) using semantic tokens.
apps/desktop/src/renderer/features/plugin/GhostPluginPage.tsx Implements enable-then-guide and market “install” CTA routing; integrates readiness badges.
apps/desktop/src/renderer/features/plugin/GhostPluginDetailView.tsx Adds readiness badge in metadata row; refines toggle tooltip/aria semantics.
apps/desktop/src/renderer/features/plugin/tests/GhostPluginCard.test.tsx Adds tests for market card action routing (install vs details).
apps/desktop/src/renderer/cindy-brain/lifecycleProjection.ts New renderer-side external-store mirror for lifecycle projection updates.
apps/desktop/src/renderer/cindy-brain/installErrorKey.ts Maps new IPC error code to i18n key.
apps/desktop/src/preload/preload.ts Exposes lifecycle IPC and updated setEnabled return payload to renderer.
apps/desktop/src/main/scheduler-host/script-capability-status.ts Extends capability availability resolution to incorporate readiness (setup/reauth/degraded/etc.).
apps/desktop/src/main/scheduler-host/tests/scriptCapabilityStatus.test.ts Adds tests for readiness-to-warning mapping.
apps/desktop/src/main/mcp-integrations/ghost.ts Aligns roster + ghost_list exposure with lifecycle projection; adds readiness/message and conservative workdir filtering.
apps/desktop/src/main/mcp-integrations/tests/ghostWorkdirGate.test.ts Updates tests for new lifecycle-driven exposure and Codex empty-workdir filtering behavior.
apps/desktop/src/main/maker-ipc/schedule.ts Sources scheduler capability warnings from lifecycle projection (single source of truth).
apps/desktop/src/main/cindy-brain/networkSlot.ts Adds runtime credential-rejection detection and reporting hooks (401/403 + certain 422).
apps/desktop/src/main/cindy-brain/index.ts Implements lifecycle projection, IPC handlers, lifecycle broadcasting, and integrates credential rejection ledger into setup assessment.
apps/desktop/src/main/cindy-brain/ghostWorkdirPrefs.ts Adds helper to list disabled-ghost union across all workdirs for conservative filtering.
apps/desktop/src/main/cindy-brain/ghostSetupChangeBus.ts Adds runtime_probe source and wildcard subscription for lifecycle projection broadcasting.
apps/desktop/src/main/cindy-brain/ghostLifecycle.ts New pure projection logic for readiness + derived views + agent-facing summary strings.
apps/desktop/src/main/cindy-brain/ghostCredentialRejections.ts New local ledger for runtime secret-key rejection tracking.
apps/desktop/src/main/cindy-brain/tests/networkSlot.test.ts Adds/updates tests for credential rejection reporting behavior including 422 probing.
apps/desktop/src/main/cindy-brain/tests/ghostLifecycle.test.ts New unit tests for lifecycle projection priority chain and derived view helpers.
apps/desktop/src/main/cindy-brain/tests/ghostCredentialRejections.test.ts New tests for ledger idempotency, persistence, and fail-open behavior.
Comments suppressed due to low confidence (1)

packages/cindy-tools/src/types.ts:288

  • getRosterItems().readiness is also typed as string even though the allowed values are fixed and already described in the comment. For consistency with CindyGhostInfo.readiness, this should use the same CindyGhostReadiness type.

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

Comment thread packages/cindy-tools/src/types.ts Outdated
Comment thread apps/desktop/src/main/cindy-brain/ghostCredentialRejections.ts
Comment thread apps/desktop/src/main/scheduler-host/script-capability-status.ts
Copilot AI review requested due to automatic review settings July 27, 2026 10:46
xxxxxccc added 12 commits July 27, 2026 18:47
Aggregate install/enable/setup/runtime facts into a single readiness
projection (ready | needs_setup | needs_reauth | degraded | blocked |
unknown) with a pure-function core (ghostLifecycle.ts), ghosts:lifecycle
invoke, and ghosts:lifecycle-changed push driven by the setup change
bus, ghosts:changed, and runtime crash/fuse transitions.

Roster assessment failure now degrades explicitly: the entry stays
discoverable but ships zero tools plus a guidance message, instead of
silently omitting the setup field while exposing the full tool list.

Signed-off-by: xxxcc <xxxcc123@126.com>
Roster snapshot (getRosterItems) and ghost_list now carry readiness
from the lifecycle projection. Non-ready plugins stay discoverable but
ship zero tools: needs_setup/needs_reauth entries include the sanitized
assessment so the agent can drive setup cards; degraded/unknown entries
carry only a guidance message. The strict ghost_call setup gate remains
as the dispatch-time backstop.

Contract: CindyGhostInfo.setup semantics tightened (required state
implies empty tools; field absence never means ready), readiness field
added to ghost_list entries and roster items.

Signed-off-by: xxxcc <xxxcc123@126.com>
Enabling a plugin now evaluates setup readiness immediately after the
enable takes effect (same probes as the plugin-page setup-status gate).
When not ready, the response carries the setup payload and the plugin
page opens the configuration flow right away — the plugin rests in an
explicit enabled-but-unconfigured state instead of silently appearing
usable to the agent. Evaluation failure rejects with the new
SETUP_STATUS_UNAVAILABLE error code (enable still applied; the renderer
shows a system error rather than a misleading setup prompt).

Signed-off-by: xxxcc <xxxcc123@126.com>
…projection

Script capability statuses now consume the same lifecycle projection as
the agent discovery layer: needs_setup/needs_reauth/degraded/blocked/
unknown map to distinct run-time failure warnings in the schedule
editor, instead of only checking the enabled flag.

Signed-off-by: xxxcc <xxxcc123@126.com>
Renderer mirrors the lifecycle projection (lifecycleProjection.ts store
fed by ghosts:lifecycle + ghosts:lifecycle-changed push) and renders a
status badge on installed plugin cards and the detail header: needs
setup / needs reauth / malfunctioning / unknown state, in all four
locales, colors via semantic tokens only. Ready and blocked entries
render no badge.

Signed-off-by: xxxcc <xxxcc123@126.com>
The detail header switch is explicitly the global enable control
(tooltip + aria), distinct from project-scoped disables which follow
the scope picker; readiness badge i18n keys for the detail/card
badges.

Signed-off-by: xxxcc <xxxcc123@126.com>
Secret keys revoked server-side previously left the plugin forever in a
configured-looking state. networkSlot now reports 401/403 responses
(retry budget exhausted) per user-source secret key into a persistent
ledger; getGhostSetupAssessment folds rejected keys into expired items,
so the lifecycle projection degrades to needs_reauth and the discovery
layer / plugin page learn on the next projection. Re-storing a secret
clears the ledger via the setup change bus (all write paths emit).
OAuth and connection credentials keep their own expiry chain and are
not double-recorded.

Signed-off-by: xxxcc <xxxcc123@126.com>
Codex sessions build the roster with an empty workingDir, which
previously meant no workdir filtering at all — a plugin disabled in the
session's project stayed visible in the Codex roster while Claude's
roster hid it. Empty workingDir now falls back to the union of all
workdir-scoped disables: conservative at the description snapshot layer,
with runtime ghost_list/ghost_call still enforcing the precise workdir.

Signed-off-by: xxxcc <xxxcc123@126.com>
protocol-and-submodules.md previously claimed provisioning was fully
removed while the builtin seed provisioner and market defaultInstall
both install silently — the rule was dead. Restate the three existing
channels as intended behavior (first-party seeding, curated
defaultInstall, manual confirmed install), and record the
enabled-but-unconfigured lifecycle state as the product answer instead
of a confirm dialog. plugin-security-and-authoring.md gains the
readiness-as-first-class-state rule (degraded exposure, unknown never
folds into ready, credential rejection ledger).

Signed-off-by: xxxcc <xxxcc123@126.com>
ownerScopedUserDataPath() requires the Electron app; module-scope
construction broke tests that import cindy-brain without Electron.

Signed-off-by: xxxcc <xxxcc123@126.com>
Move the readiness badge into GhostPluginMetadata as a trailing inline
element so it shares the text baseline of the author/version row
instead of floating in a separate flex row.

Signed-off-by: xxxcc <xxxcc123@126.com>
Brave returns HTTP 422 (not 401/403) for an invalid subscription token,
so the runtime credential-rejection ledger never observed it and the
plugin stayed 'ready' while every call failed. For plain user-source
key secrets (no exchange, non-oauth), treat a 422 whose body mentions
token/key/invalid keywords as a credential rejection too, so the
lifecycle projection flips to needs_reauth. Business-logic 422s without
those keywords are left untouched.

Signed-off-by: xxxcc <xxxcc123@126.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 33 out of 34 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (2)

packages/cindy-tools/src/types.ts:115

  • CindyGhostInfo.readiness is typed as string, which allows arbitrary/invalid values (including ones that could later be embedded into prompt text). Since the allowed readiness states are already documented here, it’s safer to model this as a string-literal union so hosts/agents can’t accidentally emit typos or unexpected values.
    packages/cindy-tools/src/types.ts:288
  • getRosterItems().readiness is also typed as string, which weakens the contract and makes it easy to emit values outside the documented set. Consider narrowing it to the same readiness union as CindyGhostInfo.readiness.

Comment thread packages/cindy-tools/src/ghost/mcpServer.ts Outdated
Comment thread apps/desktop/src/main/cindy-brain/networkSlot.ts Outdated
Signed-off-by: xxxcc <xxxcc123@126.com>
Copilot AI review requested due to automatic review settings July 27, 2026 10:56
@xxxxxccc
xxxxxccc force-pushed the feat/plugin-lifecycle-readiness branch from 8fd822d to fad8ee7 Compare July 27, 2026 10:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 32 out of 33 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (2)

packages/cindy-tools/src/types.ts:114

  • CindyGhostInfo.readiness is documented as a small, well-known enum, but it is typed as string, which weakens the public contract and makes typos easy to miss at compile time. Prefer a string-literal union type that matches the documented values.
    packages/cindy-tools/src/types.ts:287
  • getRosterItems().readiness is also typed as string even though the allowed values are enumerated in the docstring. Reuse the same readiness type as CindyGhostInfo to keep the API consistent.

Comment thread packages/cindy-tools/src/ghost/mcpServer.ts Outdated
Comment thread packages/cindy-tools/src/ghost/mcpServer.ts Outdated
Comment thread apps/desktop/src/main/scheduler-host/script-capability-status.ts Outdated

@zqchris zqchris left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

先把决策面定下来,以下作为 owner 的正式决策记录:

  • D1=B 同意:未就绪插件对 agent 降级暴露(可发现、不派发工具),方向按此推进。
  • D2=B 同意:enable-then-guide,启用不回弹、立即引导配置。
  • system prompt 文案确认:roster 头部两行说明 + [needs_setup] 标记的文案我认可;会话内快照机制核实属实,缓存声明成立。此前的程序性阻断就此解除。

代码这次先不合(PR 也还在 draft、CI verify 未跑完),有两个实打实的 [阻断] 要修,连同几条 [必改] 都在行级意见里。整体架子是对的——生命周期投影的分层干净,D2 的语义(不回弹 + 意图保留)还原得准,评估失败显式降级 unknown 的契约收紧也到位,这些不用动。

锚不到代码行的两条也要处理:

  1. [必改] description 更正:「市场卡片『详情』改『安装』」在本 diff 里不存在,删掉或补实现;同时把 ghost_list 对未就绪插件从「给工具」变「tools:[]」的行为性变更写进「用户可见变化」。
  2. Copilot 的 9 条行级意见目前一条都没处理(标 outdated 的只是行号漂移)。逐条要么修掉、要么回复不修的理由后 resolve;其中三条已并入我下面的行级意见。

[建议] 级不阻断,顺手收:台账写盘改 temp+rename 原子写(对照 plugin-market/ledger.ts);blocked 态别复用「未完成配置」文案(账号面插件在本地模式会被误导);ScriptCapabilityMultiSelect 嵌套三元改 state→key map;ghostLifecycle.ts 的 isDiscoverable/isCallable 目前无消费方;「待配置/需重新授权」按规则加 glossary.json 的 proposed 条目;无云端会话时投影对账号面插件的 warn 会刷屏,建议先短路。

改完 push 我再看一轮。投影分层和 D2 还原是这个 PR 里最扎实的部分,辛苦。

Comment thread apps/desktop/src/main/mcp-integrations/ghost.ts
Comment thread apps/desktop/src/main/cindy-brain/networkSlot.ts Outdated
Comment thread apps/desktop/src/main/cindy-brain/networkSlot.ts
Comment thread apps/desktop/src/main/mcp-integrations/ghost.ts
Comment thread packages/cindy-tools/src/types.ts Outdated
Comment thread docs/dev-rules/protocol-and-submodules.md Outdated
- cindy-tools: narrow readiness to a CindyGhostReadiness literal union
  (forward-compatible via (string & {})) on CindyGhostInfo and roster items
- mcpServer: whitelist readiness tokens before rendering into roster text
  so arbitrary/injected strings cannot leak into tool descriptions
- networkSlot: only ledger credentials whose (inject.hosts ?? net.hosts)
  matches the final response host, so a rejection on one host no longer
  flips unrelated secrets into needs_reauth
- ghostCredentialRejections: write the ledger atomically (temp+rename,
  Windows replace handling) to avoid corrupting it on crash
- scheduler: split 'blocked' into its own ghost-blocked capability state
  with dedicated i18n copy (cloud-session/account-services remediation,
  not 'go configure')
- scheduler UI: replace nested ternary warn-key selection with a
  state->key map

Signed-off-by: xxxcc <xxxcc123@126.com>
Copilot AI review requested due to automatic review settings July 27, 2026 13:33
Reintroduce the market card 'install' CTA for not-installed items on top
of the upstream unified install flow. The card button now pulls the full
plugin detail (manifest included) and routes through the same
runMarketInstall path as the detail page, so the confirm dialog still
shows the full permission list / diff before install-or-enable — the
card body remains the detail entry.

Signed-off-by: xxxcc <xxxcc123@126.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 33 out of 34 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

packages/cindy-tools/src/ghost/mcpServer.ts:190

  • 花名册标题字符串里多了一个多余的右括号,且标题文案仍声称“以下是插件作者提供的描述”,但现在同一段里也包含 Host 注入的 readiness 状态标记;这会让提示词注入防护文案语义不准确。建议去掉多余括号,并把标题改成同时涵盖“作者描述 + 宿主状态标记”。

Copilot AI review requested due to automatic review settings July 27, 2026 13:38

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d656cb0ac6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/desktop/src/main/cindy-brain/index.ts Outdated
Comment thread apps/desktop/src/main/cindy-brain/networkSlot.ts

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

在「待确认 PR」面板完成维护者确认。

@MagicLizi

Copy link
Copy Markdown
Contributor

@xxxxxccc 👋 这个 PR 还有 2 条 review conversation 没 resolve(apps/desktop/src/main/cindy-brain/index.ts / apps/desktop/src/main/cindy-brain/networkSlot.ts),auto-review 因此暂时跳过、没法继续审查 / 合并。

如果你已经按评论改完或回应了,请到对应 thread 上点 Resolve conversation;全部 resolve 后,下一轮 auto-review 会自动重新审查这个 PR。

Signed-off-by: xxxcc <xxxcc123@126.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 46 out of 47 changed files in this pull request and generated no new comments.

Suppressed comments (4)

apps/desktop/src/renderer/features/plugin/GhostPluginPage.tsx:1538

  • 这里对所有市场条目都传入了 onInstall,而 MarketPluginCard 会据此渲染“安装”操作;这会让已安装/可更新等条目也出现“安装”并触发 install 流程(可能造成重复安装或不符合状态的确认文案)。建议仅在 installState === 'not-installed' 时传入 onInstall。
    apps/desktop/src/renderer/features/plugin/GhostPluginPage.tsx:1918
  • GhostPluginCard 的标题行使用了 truncate 包裹插件名并直接内联渲染徽章;当插件名较长时,徽章会一起被 ellipsis/overflow 裁掉,导致非 ready 状态在列表上不可见。建议把行容器改成 flex,并只让“名字”那段 truncate,徽章保持 shrink-0 独立显示。
    apps/desktop/src/main/cindy-brain/ghostSetupChangeBus.ts:119
  • JSDoc 注释里 events(e.g. 缺少空格,影响可读性。
  /**
   * Subscribe to every plugin's change events(e.g. the lifecycle projection
   * broadcaster, which re-reads all stores on any signal). Distinct from
   * emitAll: this receives events for ghostIds that have no keyed subscriber.
   */

apps/desktop/src/renderer/features/plugin/GhostPluginPage.tsx:1522

  • 这里对所有市场条目都传入了 onInstall,而 MarketPluginCard 会据此渲染“安装”操作;这会让已安装/可更新等条目也出现“安装”并触发 install 流程(可能造成重复安装或不符合状态的确认文案)。建议仅在 installState === 'not-installed' 时传入 onInstall。

This issue also appears on line 1534 of the same file.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 297cc15898

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/desktop/src/main/cindy-brain/networkSlot.ts
Comment thread apps/desktop/src/main/cindy-brain/networkSlot.ts
@MagicLizi

Copy link
Copy Markdown
Contributor

@xxxxxccc 👋 这个 PR 现在在等维护者确认,确认之前流程不会合并它 —— 不是卡住了,也不是在等你再改一版(你推的改动流程都读到了,判的就是最新一版代码)。

这条是流程自动发的状态提醒(同一版代码只发一次),不用回复。

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 46 out of 47 changed files in this pull request and generated no new comments.

Suppressed comments (2)

apps/desktop/src/renderer/features/plugin/GhostPluginPage.tsx:1637

  • installable 常量已声明但在组件内未使用,会留下死代码并让后续读者误以为存在基于 installState 的分支逻辑。建议直接移除,或在需要时再引入明确的条件渲染。
    apps/desktop/src/renderer/features/plugin/GhostPluginPage.tsx:1918
  • 插件名使用 truncate 的同一个 <span> 内直接拼接了 readiness 徽章,徽章本身是 shrink-0,但父元素 truncate 会设置 overflow-hidden,在标题较长时徽章可能被裁切/省略,导致“待配置/需重新授权”等关键信息不可见。建议把标题和徽章拆成 flex 布局:标题单独 truncate,徽章独立放在旁边。

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

在「待确认 PR」面板完成维护者确认。

@MagicLizi

Copy link
Copy Markdown
Contributor

@xxxxxccc 👋 这个 PR 目前与 main 有合并冲突,auto-review 因此暂时跳过、没法继续审查 / 合并。

请在本地 merge 最新的 origin/main 解决冲突后推送;冲突解除后,下一轮 auto-review 会自动重新处理这个 PR。

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Heavy-tier security review passed: unified plugin lifecycle readiness correctly projects existing states without modifying schemas, approval records, or installation layouts. Credential rejection ledger is additive (ENOENT=fail-open), backwards compatibility fully preserved per Section 5 requirements.

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

代码审查发现 1 个 P1 问题:

P1: 403 分支遗漏 OAuth 撤销检测

文件: apps/desktop/src/main/cindy-brain/networkSlot.ts (line 1424)

401 分支正确调用了 noteOauthRejectionsIfCurrent,但 403 分支没有。同时 403 的门控条件(trackableKeys.length > 0 || responseConnectionRefs.size > 0)也不检查 OAuth 归属,导致仅凭 OAuth token 认证的插件如果上游 API 通过 403(而非 401)报告 token 撤销,永远不会被标记 needs_reauth——静默持续失败,无就绪信号。

这不是回归(PR 前完全没有 403 检测),但与本 PR 的核心目标(lifecycle readiness 准确性)直接冲突。

修复建议: 在 403 分支镜像 401 分支的 noteOauthRejectionsIfCurrent 调用,并扩展门控条件以包含 OAuth 归属检查。补充一个 OAuth + 403 revocation 场景的测试用例。

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Heavy-tier 审查 + 安全专项通过:lifecycle readiness 投影架构完整,向下兼容存量插件(additive schema 不破坏已装/已批准状态),无凭证泄露、无沙箱逃逸风险。前几轮 reviewer 指出的六项问题(tool-name 绕过 setup_plan、per-host 归属、422 清理、workdir 取舍披露、readiness 类型联合、false decision 撤回)均已在当前修订中解决。

⚠️ bot settle 超时:copilot-pull-request-reviewer / chatgpt-codex-connector 在 683 分钟内未对当前 head 表态,按超时放行——合并后可能有迟到意见。

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review passed (heavy tier)

审查通过,零 P0/P1。

4 条 P2 观察(均为性能优化建议,不阻断):

  1. apps/desktop/src/main/cindy-brain/index.ts:575 — lifecycle projection 每次广播重算全部插件评估(当前事件频率低,不构成瓶颈)
  2. apps/desktop/src/main/mcp-integrations/ghost.ts:464 — isGhostFused 为单插件查询调用全量 projection(N 小时无碍)
  3. packages/cindy-tools/src/ghost/mcpServer.ts:193 — roster 格式精简(安全改进,ghost_list 仍提供全量)
  4. apps/desktop/src/main/cindy-brain/networkSlot.ts:756 — credential rejection 正则仅覆盖英文(保守启发式,安全方向正确)

安全评估:本 PR 改善了安全态势——roster 防注入、凭证拒绝帐本仅存 key name 不存 value、owner 边界保护、IPC origin assert 均正确。无新增网络调用、无凭证泄露路径。

当前无法合并:存在代码冲突(mergeable=CONFLICTING),需作者 rebase。

@MagicLizi

Copy link
Copy Markdown
Contributor

代码审查已完成,结论:通过(零 P0/P1)。

但当前 PR 与 main 存在合并冲突,无法直接合并。请 rebase 到最新 main 解决冲突后,下一轮自动审查将直接尝试合并。

审查摘要:

  • 安全扫描:通过(无恶意代码、无数据外发、无可疑网络调用)
  • 向后兼容:OK(新增字段可选,持久化 schema 未变,测试验证了 rollback 安全性)
  • 仅 2 条 P2 建议(roster 信息精简的产品意识提醒、broadcastGhostLifecycleChanged 序列化性能)

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

代码审查通过(heavy 档:含 semgrep 安全扫描 + 恶意插件利用面检查)。

核心结论:

  • 向下兼容:所有新增 wire-protocol/IPC 字段均为 optional/additive,已装插件升级后无需用户操作
  • 竞态保护:凭证拒绝归因计数、指纹式 in-flight 变更检测(4 种凭证类型对称覆盖)、grant_only TOCTOU 二次校验、owner 边界丢弃逻辑均已验证
  • 错误处理:ledger 写失败 fail-open(日志 + 保持运行态),损坏/缺失 ledger 有兜底,批量投影中单插件 assessment 错误隔离
  • 恶意插件面:degraded/non-ready 插件始终 tools: [],roster 文本经过清洗和 enum 白名单校验,fused 插件同时阻断 normal call 和 grant_only 预授权
  • 安全扫描:semgrep (p/javascript + p/nodejs) 0 findings

225/225 PR 相关测试通过,typecheck 两个 package 均 clean。无 P0/P1 问题。

@MagicLizi

Copy link
Copy Markdown
Contributor

✅ 代码审查通过(heavy 档),已 Approve。

⚠️ 当前有合并冲突(mergeStateStatus=DIRTY),需要作者 rebase 或 merge main 解决冲突后即可合并。

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

代码审查通过(heavy tier + security scan)。

审查确认:

  • 安全扫描无问题(无新依赖,凭证拒绝台账只存 key 名不存值,原子写入 mode 0o600)
  • 插件向后兼容(REDLINE):空台账 = 无降级,可选字段不影响旧消费者,未知字段被忽略
  • 凭证指纹用 SHA-256 前 16 位防 stale-401 竞态
  • 正则无 ReDoS 风险(锚定 + 有界回溯 {0,96})
  • IPC handler 已加 assertTrustedAppRendererEvent 守卫
  • UI 组件使用语义 token,双模式兼容

阻断: 当前有合并冲突(mergeable=CONFLICTING),需要作者 rebase/merge main 解决后才能合并。

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

重审查通过:全部 7 处安全软命中逐条验证安全(密钥台账只记名不记值、IPC 都有 trusted-renderer 守卫、无能力扩散),存量插件兼容性完整,semgrep 扫描 0 条。

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Automated review (heavy tier) complete — no P0/P1 found.

  • All 7 dangerous pattern soft hits confirmed as false positives (bounded regex, owner-scoped file ops, trusted-renderer IPC, microtask coalescing)
  • Plugin backward compatibility: new ledger is additive, ENOENT = empty, no mandatory fields added to existing stores
  • Author contract (FORGE_GUIDE) unchanged — readiness is host-side only
  • Security scan (semgrep): 0 findings against origin/main
  • Credential handling: ledger stores only key names, never values
  • IPC handlers correctly use assertTrustedAppRendererEvent

Note: awaiting maintainer re-approval before merge.

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Heavy-tier code review passed. Security posture is improved: roster no longer includes plugin descriptions in system prompts (eliminates prompt injection vector), non-ready plugins no longer expose tool schemas, and credential fingerprint comparison prevents false-positive rejections. All 13 security soft hits are test fixtures. No actionable P0/P1 issues found.

Note: zqchris's earlier review comments may still need addressing.

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

自动审查通过:0 P0/P1。

逐项核实了 zqchris 此前指出的两个阻断点均已修复:

  1. setup_plan 路径下 tool name 校验跳过(ghost.ts:727, 780)
  2. 401/403 凭证驳回归因改为 host-scoped + 403 body signal 门控(networkSlot.ts)

向下兼容验证:ledger 文件缺失 = 空(fail-open)、optional 字段、无 schema/布局/包格式变化。安全扫描 0 新发现,无新依赖。

当前唯一合并阻断:zqchris 的 CHANGES_REQUESTED 尚未 dismiss 或重新 approve。

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Auto review (heavy tier): PASS — 0 P0, 0 P1, 1 P2 (minor indentation nit).

Security soft hit: SAFE — SHA-256 fingerprint used only for in-flight credential race detection; only key names persisted, never values; file mode 0o600.

Well-structured PR: credential rejection ledger, unified lifecycle projection, owner boundary guards, prompt injection hardening — all look sound.

Note: PR currently has merge conflicts that need resolution before merge.

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Heavy-tier auto-review complete: 0 P0, 0 P1. All 7 security soft hits assessed as false positives. Code quality and test coverage are strong. However, this PR now has merge conflicts that need to be resolved before it can be merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status:awaiting-author 等作者修改(review-pr 自动维护,仅展示) touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示) touches:large-diff 改动量较大(review-pr 自动维护,仅展示) touches:plugin-base 改动碰到插件基座(review-pr 自动维护,仅展示) touches:product-ui 改动碰到产品 / UI 面(review-pr 自动维护,仅展示) touches:rules 改动碰到规则 / 规范文档(review-pr 自动维护,仅展示)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants