# mode=apply：在模板基础上实现功能代码

> CLI `update` 已在各 entry 路径生成了模板代码。apply 阶段在模板基础上**填充用户真实需求的功能代码**。

## A1：为每个点位实现功能代码

用 `lpm ai peek` 取 resources（不要 Read 整份 `plugin.config.json`）：

```bash
lpm --cwd "<projectRoot>" ai peek plugin.config.json resources --format json
```

对每个 entry 路径：

1. Read `entry` 文件（单文件，体量小）获取 CLI 已生成的模板代码
2. 根据 plan 阶段的实现方案，在模板基础上填充功能逻辑
3. 将修改后的代码写回 `entry` 路径

> ⚠️ `index.tsx` 入口包含"等 SDK 注入再挂载"的启动逻辑，**改动这段会导致插件不可用**。功能代码写在模板预留区域，不要替换整个入口文件。

（`plugin.config.json` 的维护规则见 [`shared.md`](shared.md#安全规则)。）

## A1.2：调试日志（必做）

**对有信息量的 `window.JSSDK.*` 调用紧邻一行 `console.log`**：

```ts
const x = await window.JSSDK.<ns>.<method>(args);
console.log('[<method>]', x);
```

打 / 不打的判断：

| 情形 | 处理 |
|---|---|
| 有返回值的调用（`getProps` / `getContext` / `handleSubmit` 返回 res 等）| **打 log 出返回值** |
| 有 payload 的写调用（`saveFieldValue(payload)` / `notify(key, payload)` / `handleSubmit(payload)`）| **调用前打 payload**（出错时方便定位输入） |
| watch / on*Changed 的回调函数 | **回调内打入参**（`changed` / `next`） |
| catch 块捕获的异常 | **打 error**（仅在 catch 里打，不在 try 后空打） |
| 副作用类无返回值（`containerModal.close()` / `script.end()`）| **不打** —— `done` 标记是噪音 |

格式：前缀 `[<methodName>]` 方便 console 过滤；大数组打 `{ dataLen, sample: data[0] }` 即可。

## A1.5：代码溯源审计（原生命令，跨平台）

A1 写完后、A2 输出前，**MUST 执行下述审计命令**对所有改动文件做方法名存在性校验，避免 AI 在写代码时悄悄从 schema 字段名脑补 SDK 调用。

> 本步骤用 `lpm ai audit-jssdk` 原生命令实现（纯 Node、跨 OS），任何 agent 在任何系统上都能直接调。

### 审计命令

```bash
# 默认 types 路径：node_modules/@lark-project/js-sdk/dist/types/index.d.ts
# 默认扫描范围：git diff 改动的 src/features/**/*.{ts,tsx} → 否则 src/features 全量
lpm --cwd "<projectRoot>" ai audit-jssdk
```

退出码：
- `0` = 审计通过（无违规；或 types 未安装的 SKIP 情形）
- `1` = 有违规，stdout 列出 `FILE:LINE | method "<name>" not in types | <原文行>`

需要限定文件范围或机器可读时：

```bash
lpm --cwd "<projectRoot>" ai audit-jssdk --files src/features/foo/index.tsx,src/features/bar/index.tsx
lpm --cwd "<projectRoot>" ai audit-jssdk --format json
```

### 处理命令输出

- **exit 0 + stdout 为 `ok ...`** → 审计通过 → 进入 A2 输出摘要
- **exit 1 + stdout 有违规行** → **暂停**，把每一条原文呈现给用户：

```
⚠️ 代码溯源审计发现以下可疑调用（方法名在 @lark-project/js-sdk types 中不存在）：

1. src/features/xxx/index.tsx:42
   代码: window.JSSDK.control.getValue()
   原因: 'getValue' 在 @lark-project/js-sdk 类型定义中不存在
         可能的真实 API：getCreateWorkItemFormItemValues

2. src/features/yyy/index.tsx:88
   代码: window.JSSDK.customField.saveData(...)
   原因: 'saveData' 在 types 中未找到
         可能的真实 API：saveFieldValue

请告诉我每条怎么处理：
- A. 按提示修改
- B. 我提供真实 API（贴文档/示例）
- C. 跳过这处功能（输出 TODO 占位）
```

> ⚠️ **禁止 orchestrator 自己"过滤"审计输出**。所有条目必须**原文呈现**，不允许"我帮你筛选了下，问题不大"这种 sycophancy。
>
> ⚠️ **禁止用主 agent 自审代替此命令**——AI 对自己写的代码有偏见，容易放行。`lpm ai audit-jssdk` 是闸口，即使觉得"我这次写得挺稳"也要跑。

### 何时可以跳过 A1.5？

仅在以下条件全满足时可跳过（plan 阶段已显式记录）：

- 本次 apply 没有产生任何新的 `window.JSSDK.*` / SDK 调用
- 仅修改 UI、样式、纯前端逻辑（无 SDK 接触）

### 局限与补强

审计命令只查"方法名存不存在于 types"，查不了：
- 方法签名参数是否正确
- 调用顺序 / 跨 API 约束

这些语义层问题靠 [`code-plan.md`](feature-code-plan.md) 的"代码溯源协议 + 无源即停"在前置阶段堵住。脚本是**事后兜底闸**，不是全部防线。

## A2：输出摘要

```
✅ 代码生成完成
   修改文件：
   • ./src/features/board_web_rj4v_m/index.tsx

   下一步：执行语法检查（mode=verify）
```
