# pi-frontend-kpc-agent

一个基于 Pi 的终端前端 coding agent 扩展包，面向 Vue、`@ksyun-internal/versatile` 和 `@king-design/vue`。从目标项目实际安装的包版本、入口声明、类型关系和 lockfile 中生成组件契约，再用编译器做确定性校验。

## 核心链路

```mermaid
flowchart LR
  A[目标项目 package.json / lockfile] --> B[精确定位已安装版本]
  B --> C[TypeScript 组件契约清单]
  B --> T[frontend_scene_template 场景骨架]
  T -->|命中| F[Vue SFC 静态校验]
  T -->|未命中 / 新增组件| D[component_query 精简发现]
  D --> U[component_usage 安装包示例 / 组合结构]
  U -->|示例未覆盖| E[component_contract 精确成员]
  C --> E
  C --> F[Vue SFC 静态校验]
  H[frontend_preview 截图 / 路由<br/>仅显式视觉验收时] -.-> I[frontend_finish]
  F --> I
  G[typecheck / lint / test / build] --> I
```

组件库升级后会按“项目根目录 + 包名 + 精确版本”重新抽取契约，不需要维护一份手写 API 文档副本。

## 环境与安装

- Node.js `>=22.19.0`
- 已按 Pi `0.81.1`、TypeBox `1.1.38` 完成构建和测试

### 推荐：使用安装脚本

`0.1.11` 发布到 npm 后，其他人可以先下载并检查脚本，再执行：

```bash
curl -fsSL https://unpkg.com/pi-frontend-kpc-agent@latest/install.sh | sh

curl -fsSLo /tmp/pi-frontend-kpc-agent-install.sh \
  https://unpkg.com/pi-frontend-kpc-agent@0.1.11/install.sh
less /tmp/pi-frontend-kpc-agent-install.sh
sh /tmp/pi-frontend-kpc-agent-install.sh
```

仓库使用者也可以直接运行：

```bash
./install.sh
```

脚本会依次：

1. 检查 Node.js、npm 和 `pi`；若缺少 `pi`，全局安装已验证的 `@earendil-works/pi-coding-agent@0.81.1`。
2. 通过 `pi install npm:pi-frontend-kpc-agent@0.1.11` 安装与脚本相同版本的 Agent Package。
3. 将 `company-openai` 的无密钥模型模板合并到 `${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}/models.json`。

脚本不会复制开发者本机的密钥、认证信息或其他 Pi 配置。模型配置只保存环境变量引用 `$COMPANY_LLM_API_KEY`，使用前请在当前 shell 提供真实密钥：

```bash
export COMPANY_LLM_API_KEY='your-key'
pi --model company-openai/qwen3.6-plus
```

默认模型服务地址为公司内网的 `http://kspmas.ksyun.com/v1`。仅应在可信内网使用；如有 HTTPS 地址，可在安装时覆盖：

```bash
PI_COMPANY_OPENAI_BASE_URL='https://llm.example.com/v1' \
  sh /tmp/pi-frontend-kpc-agent-install.sh
```

已有 `company-openai` 配置时，脚本默认保持原样，适合重复执行。确认要用包内模板替换时，显式开启覆盖；原文件会以 `models.json.bak-*` 备份：

```bash
PI_MODELS_OVERWRITE=1 sh /tmp/pi-frontend-kpc-agent-install.sh
```

高级参数：

- `PI_CODING_AGENT_DIR=/absolute/path`：修改 Pi agent 配置目录，必须是绝对路径。
- `PI_FRONTEND_AGENT_SOURCE=npm:pi-frontend-kpc-agent@0.1.11`：固定版本或切换为本地包路径。
- `PI_NPM_PACKAGE=@earendil-works/pi-coding-agent@version`：显式选择要安装的 Pi 版本；必须满足 `>=0.81.1`。

若上次执行被 `kill -9` 强制终止，可能留下 `.pi-frontend-kpc-agent-install.lock`。确认没有其他安装进程后再手动删除该空目录。全局 npm 目录无写权限时，脚本会直接失败且不会尝试 `sudo`；建议使用 nvm 管理 Node.js 后重试。

卸载 Agent Package 可执行 `pi remove npm:pi-frontend-kpc-agent`。为避免误删用户配置，卸载不会自动移除 `models.json` 中的 provider。

### 手动安装

安装 Pi：

```bash
npm install -g --ignore-scripts @earendil-works/pi-coding-agent@0.81.1
```

安装已发布的 Agent Package：

```bash
pi install npm:pi-frontend-kpc-agent@0.1.11
```

本地开发及验收：

```bash
npm install
npm run verify
pi -e /absolute/path/to/pi-frontend-kpc-agent
```

开发阶段安装当前本地包：

```bash
pi install /absolute/path/to/pi-frontend-kpc-agent
```

进入目标 Vue 项目后运行 `pi`，可直接描述需求，也可使用包内提示模板：

```text
/frontend 实现带筛选、分页和错误重试的实例列表
/frontend-review 当前改动
```

## 九个确定性工具

| 工具 | 作用 |
| --- | --- |
| `frontend_project_inspect` | 识别包管理器、精确组件库版本、脚本、构建配置、Node 兼容性、数据层路径，以及 Vue 的 TS/JS、script setup/Options API 等现有约定 |
| `frontend_scene_template` | 第一级检索：按自然语言或模板 ID 返回一个匹配的列表、详情或购买场景骨架；根据 `targetFile` 自动匹配 TS/JS，优先选择 Versatile，未安装时回退原生 KPC；命中后模板组件自动登记为已验证证据 |
| `component_query` | 模板未命中或需要新增组件时，批量发现最多 12 个精确安装导出；模板尚未解析或请求的组件已被模板覆盖时自动跳过 |
| `component_usage` | 第二级检索：从当前安装版本的 tests/examples/source 提取最小用法，并识别 `Table > TableColumn`、`Dropdown > DropdownMenu > DropdownItem` 等组合结构 |
| `component_contract` | 第三级检索：示例未覆盖所需细节时，按需读取 props、events、models、slots、methods 或 exposed 精确成员 |
| `component_validate` | 用 Vue/TypeScript AST 校验 SFC 的导入、静态 prop、event、`v-model`、slot、枚举和必填 prop |
| `frontend_verify` | 可选的中途诊断工具：只从固定脚本候选生成 `fast` 或 `full` 检查计划，区分变更范围内与存量错误，并为变更范围诊断附上失败源码和所属组件；不要紧接着再调用本身已执行 full gate 的 `frontend_finish` |
| `frontend_preview` | 高成本、显式启用的视觉工具。只有用户明确要求截图验证、视觉对比/验收或渲染预览时，才启动目标项目并截图真实路由；无路由的独立组件走单 SFC 沙箱。返回截图、渲染状态、console error、路由和可选参考图比较 |
| `frontend_finish` | 默认按 code 模式校验组件证据、mock/图标/列表结构、新页面静态路由引用，并运行项目可用的 typecheck、lint、test、build；只有显式 visual 模式才启动页面并增加截图、参考图和真实路由验收 |

包内还提供三个可组合 Skill：`ksyun-frontend-workflow`、`ksyun-frontend-review`、`ksyun-frontend-testing`。

## P0 / P1 / P2 执行策略

### P0：先产出，再校验

- 常见列表、详情和购买流程先调用一次 `frontend_scene_template`，传入准备修改或创建的 `targetFile`，并等待模板结果后再查询组件。并行发起的提前组件检索会被工具跳过，避免提示规则被绕过。工具按“目标文件 → 同目录 Vue 文件 → 项目采样 → TypeScript 依赖”的顺序选择 TS/JS；若局部代码仍使用 Options API，只返回可迁移的 template/style 组合，不要求整页改写为 Composition API。
- 兼容模板是实现基线，不只是参考代码。列表模板会记录当前变体要求的 `ProTable` 或 `Table` 根组件；首次 `write/edit` 若把它替换成另一套表格组合，会在落盘前被拒绝，后续静态检查也会按 error 阻断。
- `list-basic` 会同时返回 `supportingFiles`，提供与主 SFC 一致的 `types`、确定性 `mock` 和纯函数 `utils` 源码及建议路径。应在同一实现批次写入并统一改字段，不能一边复制主模板、一边重新猜测配套模块。
- 命中兼容模板后直接按本地数据、字段、路由和状态做最小适配。模板列出的组件自动计为渲染验证证据，后续 `component_query`、`component_usage` 或 `component_contract` 会跳过这些 API；只有实质改变模板 API 时才显式 `force: true`。
- 兼容模板命中后、目标页首次写入前最多允许 4 次聚焦的额外组件研究调用；模板覆盖组件此时不能用 `force` 绕过。先写出最小页面，再由自动校验或最终门禁给出精确缺口，避免长时间“查而不写”。
- 模板的 TS SFC 是实际渲染基线；JS 版本仅替换独立脚本适配器，template/style 共用同一份，避免双份页面结构逐渐漂移。确有迁移或测试需要时才显式传 `language: "ts"` 或 `language: "js"` 覆盖自动判断。
- 没有兼容模板时，先看邻近业务代码，再用一次 `component_query` 批量确认精确组件名，并优先读取 `component_usage` 的安装包示例。只有示例未覆盖的 API 成员才读取 `component_contract` 或安装源码。
- 在线组件文档放在最后，只作为搜索线索；任何文档写法都必须回到当前安装版本的声明、测试或源码验证，不能覆盖本地包事实。
- `frontend_project_inspect` 只读取项目结构，不在后台启动 typecheck/build，也不会因生成 `tsconfig.tsbuildinfo` 等产物污染工作区。项目脚本仅在显式调用 `frontend_verify` 或最终 `frontend_finish` 时运行；最终检查按诊断文件路径隔离变更范围与存量错误。
- 源码变更后最多允许两次无关只读调查；当前报错文件、变更文件、组件 usage、验证命令和生成截图不受该预算限制。一次验证尝试后预算会重置，不再因项目缺脚本形成死锁。
- 同一组件错误，或同一文件/错误码/行号的 TypeScript 错误连续出现两次后暂停继续盲改。`frontend_verify` 会附上准确源码行、上下文和最近的所属组件，应先修这一表达式，不能顺手删除模板里的选择、分页、搜索或总数行为。
- provider 请求按估算 token 使用滚动 TPM 窗口节流；遇到 429 时优先遵循 `Retry-After`，否则至少退避 60 秒。
- 页面 SFC 保持展示和交互职责；本轮新建或明显膨胀到 500 行以上的页面会阻止完成，要求把类型、纯逻辑和可选 mock 拆出。

页面功能较复杂时，推荐按 feature 共置：

```text
src/views/Instances.vue
src/views/instances/types.ts
src/views/instances/utils.ts
src/views/instances/mock.ts   # 仅在 mock 判定成立时创建
```

TypeScript 页面用 `types.ts` 放接口、表单和行数据类型；JavaScript 页面不为模板强行引入 TypeScript。`utils.ts`/`utils.js` 放搜索、过滤、排序、分页等纯函数。不要为了凑目录创建空模块。

Mock 数据不是附图或页面任务的默认选择。`frontend_project_inspect` 会报告已有 API/service/store/mock 路径和请求库：

- 已有 API、service、store 或邻近页面数据流时，优先复用真实 adapter；测试在边界层 mock。
- 明确是隔离原型或图片生成、没有可用数据源且需要稳定展示 loading、empty、error、success 状态时，才按项目语言创建 `mock.ts`/`mock.js`。
- Mock 必须有明确数据结构、确定性、无随机数和当前时间依赖，不得把大段数组直接写进 `.vue`；不要让 mock 静默成为生产默认数据源。
- 明确要求 mock 或任务显式启用视觉门禁时，`frontend_verify`/`frontend_finish` 会扫描本轮所有变更源码中的 `Math.random()`、`Date.now()`、`randomUUID()`，不能通过把随机生成器放进 `utils.ts` 绕过；同时检查生成的 Table/ProTable 搜索分页页是否导入共置 `utils.ts`/`utils.js`、搜索输入是否真正进入过滤链路。TS 列表模板要求类型从 `types.ts` 导入；明确要求 mock 时要求从共置 `mock.ts`/`mock.js` 导入。

### P1：控制上下文和环境噪音

- 上下文超过约 32k token 后压缩旧的成功工具结果；超过约 48k 时进一步压缩其他旧结果。最近消息和错误输出保留。
- `frontend_project_inspect` 缓存到 `package.json` 发生变化为止，组件查询和单组件契约按参数缓存。
- 验证前检查当前 Node 版本是否满足项目和构建工具的 `engines.node`，不兼容时直接报告环境阻塞，不消耗一次无效构建。
- 存量项目使用同口径的 full 可用-gate 基线；若仍无基线，则按报错路径判断是否落在本轮 dirty scope。任务外旧错误不会触发自动修复，无法归属文件的失败仍阻塞。
- formatter、patch、codegen 等不透明写入通过前后工作区快照定位实际文件；不要求目标目录必须是 Git 仓库。`2>/dev/null` 等诊断重定向不会再被标成写入。
- `npx`/`bunx` 调用项目 `node_modules/.bin` 中已安装的命令不再误标为依赖变更；显式 `--package` 或需要下载的执行仍要求授权。
- KPC 图标类会对照当前安装包的 iconfont registry，错误的 `k-icon-plus`、`k-icon-arrow-down` 等会在完成前给出精确文件和行号。
- KPC `Table` 运行时默认启用 checkbox 选择列。生成页若又手写包含 `Checkbox` 的 selection 列会被阻断；使用内置选择时绑定 `v-model:checkedKeys`，确需自定义列时显式设置 `check-type="none"`。
- 从列表模板生成的 ProTable 会保留选择状态和受控分页不变量。批量按钮依赖 `checkedKeys` 却没有 `v-model:checked-keys`，或把模板分页对象退化成 `:pagination="true"`，都会在执行项目脚本前被阻断。
- ProTable 列表模板还会保留 request、row-key、sort、group、搜索模型、`LayoutContent` 头部和 `TableColumnId` 主列；这些绑定缺失会被视为模板结构退化。新生成的模板页必须保留显式组件 import，不能依赖无法静态确认的全局同名组件。
- 生成页中的 `any`、`any[]`、`as any`、`@ts-ignore`/`@ts-expect-error` 会被视为组件事件/数据类型尚未查明，而不是可接受的修复。

### P2：默认代码验收，视觉验收显式启用

- 默认 `validationMode` 为 `code`。附件、`.png/.jpg/.webp` 路径、“根据图片生成”或“原型”只作为需求输入，不会启动目标项目、浏览器或 SSIM。
- code 模式依赖场景模板不变量、组件契约与安装示例、页面架构、纯函数/行为门禁，以及项目已有的 typecheck、lint、test、build。`frontend_finish` 会静态确认新页面已被现有 Vue Router 引用，并明确返回“未验证运行时外观”；它不会启动页面或要求截图。
- 只有用户明确要求“截图验证/对比/验收”“视觉验证/对比/验收”“像素级还原”或“查看渲染预览”等操作时才切换到 `visual`。用户也可以明确要求只做代码/编译检查切回 code。
- visual 模式下，每个变更的 Vue 文件必须有成功预览；`views/` 页面和 `App.vue` 还必须证明请求路由已声明且目标页面被路由引用。
- 有已验证路由时，预览工具启动目标项目并截图真实页面；没有路由时才使用独立 SFC 沙箱。只有 wrapper 明确报告渲染成功且没有 `console.error` 时才计入视觉证据；错误页只作为诊断附件。相同基础设施失败重复两次后会熔断本轮重试。
- visual 模式会自动选择提示中唯一的项目内参考图；多张图时必须明确选择。工具记录尺寸并在 ffmpeg 可用时计算 SSIM；低于 0.75 或未产生比较证据时阻断完成。

## 版本与发布

版本脚本会修改 `package.json`、`package-lock.json`，并同步 `install.sh` 中固定的 Agent 版本；不会创建 Git tag、commit 或执行发布：

```bash
npm run release:version:patch
npm run release:version:minor
npm run release:version:major
```

发布前检查会运行完整验证，并检查最终 npm tarball 的入口、Skills 和 Prompts：

```bash
nvm use 22.19.0
npm run release:check
```

确认版本和检查结果后，由发布者手动执行。当前开发机的默认 npm cache 存在权限问题，因此使用一个可写的临时 cache：

```bash
npm publish --cache "${TMPDIR:-/tmp}/pi-frontend-kpc-agent-npm-cache"
```

## 契约判定规则

- KPC 支持直接或间接 `Component<Props, Events, Blocks>` 继承，并提取继承的公开方法。
- KPC 的 Vue adapter 语义按已安装运行时代码处理：默认 `v-model` 映射到 `value`，`v-model:x`、`@change:x`、`@change-x` 与 `@update:x` 仅在契约中存在对应 prop 时通过。
- Vue `DefineComponent` 支持标准多泛型声明，读取 props、emits 和 RawBindings/`defineExpose` 表面。
- 字面量枚举保留真实的 string/number/boolean/null 值；开放类型不会被错误收窄成封闭枚举。
- `coverage: false` 表示声明只提供了部分证据。已知成员仍会校验，未知成员降为 `UNVERIFIABLE` warning，不臆断为非法。Versatile 组件可能通过 `$attrs` 透传 props/listeners/slots，因此默认采用这一保守策略。
- 已知 prop 的普通动态值（如 `:data="rows"`）不产生噪音 warning，由 vue-tsc 负责表达式类型；无法确定成员名的 `v-bind` spread、动态 event/slot、全局注册或 auto-import 组件仍会给出 warning。
- KPC/Intact 声明经常不表达 Vue adapter 接受的隐式 default children；这类内容不再误报为非法 slot，复合结构由 `component_usage` 的安装包示例证明。
- 组件深路径导入若无法由根声明证明，会给出 warning，并交给 `vue-tsc`/build 判断是否真实可解析；生成代码优先使用清单给出的根导入路径。

## 最终门禁

`fast` 优先运行 typecheck 与 lint；如果两者都不存在但有 build，则用 build 作为可用回退。`full` 会运行项目实际存在的 typecheck、lint、test、build；缺失项作为明确的 residual risk 返回，但不会让原型任务永久无法完成。typecheck/lint 单步最长 5 分钟，test/build 单步最长 15 分钟；取消后不再继续。已有失败只有在同口径基线中存在，或能明确归属到 dirty scope 之外时才可接受。

`frontend_finish` 会先运行不需要项目脚本的确定性预检；组件、结构、证据或新页面静态路由引用未通过时直接返回，不重复消耗 typecheck/build。只有 visual 模式才启动页面并把真实路由和截图加入预检。预检通过后才运行项目 gate。只有以下条件同时成立时才返回终止信号：

1. 本轮已知变更的 Vue 文件没有契约 error。
2. formatter、patch、codegen 等不透明写入已通过工作区前后快照解析为具体文件；遗留未知范围才回退到 Git 状态。
3. 没有无法解析的写入范围或项目根外改动。
4. 所有可用 full gate 成功，或失败已被基线/文件路径证明只属于本轮范围外的存量问题；缺失 gate 已显式报告。
5. 模板语言可被契约校验器处理。
6. 用户显式要求视觉验收时，变更 SFC 已成功预览，页面级文件的目标路由已验证；code 模式不运行也不宣称视觉验收。
7. 本轮没有生成或大幅扩张出超过 500 行的单体页面 SFC。
8. 新生成页中每个组件 import 都有 contract 或 installed-usage 证据；Table、Dropdown、Select、Form 等复合组件必须有 installed usage，并符合其观测到的子组件结构。表格搜索分页逻辑已按项目语言拆到 `utils.ts`/`utils.js`。
9. mock 数据确定、图标名存在于安装包 registry，搜索控件不是未连接的装饰。
10. KPC Table 没有同时启用内置选择列和手写 Checkbox selection 列；列表模板的 checkedKeys 与受控分页仍连接；生成页没有用 `any` 或 TypeScript suppression 掩盖组件类型问题。
11. visual 模式且提供参考图时，已记录对应页面的参考比较；预览日志没有 `console.error`。

当前契约 AST 只支持 HTML template。Pug 会明确标记 `TEMPLATE_LANGUAGE_UNSUPPORTED` 并阻止最终门禁，而不是伪装成已校验。

## 测试与实包验证

```bash
npm run check   # TypeScript strict check
npm test        # manifest / validator / safety / installer / tools / verification tests
npm run build   # ESM + declarations
npm run smoke   # 动态加载 dist 入口并核对九个 Pi 工具
```

离线实包冒烟结果：KPC 3.8.0 抽取 413 个根导出、95 个组件；Versatile 1.1.2 抽取 1047 个根导出、59 个组件。覆盖了 KPC 间接继承以及 Versatile ProTable 的公开 ref 方法。

这些门禁能证明“声明契约、静态 SFC、项目既有检查均通过”，但不能数学上保证所有运行时行为。新业务仍应为 loading、empty、error、retry、重复交互、可访问性和关键视觉状态补充有针对性的组件/E2E 测试。

## 安全边界与已知限制

- write/edit 的路径、符号链接逃逸、敏感文件、常见 shell 写入和依赖变更都有保护；交互模式的依赖变更需要确认，headless 默认阻断。
- 真实路由截图会启动目标项目的 `dev` 脚本，typecheck/test/build 也会执行项目自己的代码。只有项目已受信，或终端用户显式确认后才运行，并设置超时。
- shell 和项目脚本是图灵完备的；命令解析保护是 guardrail，不是 OS sandbox。需要强隔离时应在容器或操作系统沙箱内运行 Pi。
- 当前要求依赖存在于所选项目根的 `node_modules`；Yarn PnP 与依赖仅 hoist 到工作区父目录的 monorepo 尚未支持。此时请从实际 workspace 根运行，或后续增加受限的 workspace package resolver。
- 当前包名为无 scope 的 `pi-frontend-kpc-agent`，`publishConfig.access` 为 `public`；若改发公司私有 registry，应在发布前调整 registry 与访问策略。
