# Codex Prompt: audit:docs-site 启动门槛收紧版口径调整

`pnpm audit:docs-site` 当前 hard fail，阻塞所有后续 Session 的启动检查。本任务做**精确口径调整**——只把"in-review 待人工核对"和"IconPage 资产目录展示"从 fatal 降为 warn，**其它真问题（缺 baseline / 非 canonical / 非 figma-frame）依然保持 error**。

---

## 必读前置

1. `docs/session-handoff.md`（启动门槛 + 当前阻塞点）
2. `docs/multi-session-collaboration-rules.md`（主 Session 全量 audit 规则）
3. `docs/site-pixel-parity-mechanism.md`（四层审查门定义）
4. `docs/site-review-manifest.json`（当前 in-review 页面 + IconPage expectedSourceType=none）
5. `figma-sync/audit-docs-site-readiness.mjs`（待改脚本，约 219 行）

---

## 任务 1：调整 `figma-sync/audit-docs-site-readiness.mjs` 口径

### 改动 1.1 — `pixelReviewStage=in-review` 降级为 warn

定位：约 line 140–151（`reviewPass` 分支）。

当前：

```js
const reviewPass = manifestEntry.pixelReviewStage === 'approved'
pageReport.gateStatus.review = reviewPass ? 'pass' : 'fail'
if (!reviewPass) {
  pageReport.blockers.push('review-not-approved')
  pushIssue(
    issues,
    'error',
    manifestEntry.pageId,
    'Pixel review is not approved',
    `${manifestEntry.pageId} is currently ${manifestEntry.pixelReviewStage}.`
  )
}
```

改为：

```js
const reviewPass = manifestEntry.pixelReviewStage === 'approved'
const reviewInProgress = manifestEntry.pixelReviewStage === 'in-review'
pageReport.gateStatus.review = reviewPass
  ? 'pass'
  : reviewInProgress
    ? 'in-review'
    : 'fail'
if (!reviewPass) {
  pageReport.blockers.push(reviewInProgress ? 'review-in-progress' : 'review-not-approved')
  pushIssue(
    issues,
    reviewInProgress ? 'warn' : 'error',
    manifestEntry.pageId,
    reviewInProgress ? 'Pixel review still in-review' : 'Pixel review is not approved',
    `${manifestEntry.pageId} is currently ${manifestEntry.pixelReviewStage}.`
  )
}
```

**口径要求**：
- `pixelReviewStage='approved'` → review gate `pass`
- `pixelReviewStage='in-review'` → review gate `in-review`（新值），issue severity = `warn`
- 其它（如 `blocked` / 未知值） → review gate `fail`，issue severity = `error`

### 改动 1.2 — foundation 页 source-type 不匹配降为 warn

定位：约 line 86–94（`Source type mismatch` 分支）。

当前：

```js
if (manifestEntry.expectedSourceType !== actualSourceType) {
  pushIssue(
    issues,
    'error',
    manifestEntry.pageId,
    'Source type mismatch',
    `Expected ${manifestEntry.expectedSourceType}, but ${file} currently resolves to ${actualSourceType}.`
  )
}
```

改为：

```js
if (manifestEntry.expectedSourceType !== actualSourceType) {
  const isFoundationDisplay = manifestEntry.kind === 'foundation'
  pushIssue(
    issues,
    isFoundationDisplay ? 'warn' : 'error',
    manifestEntry.pageId,
    isFoundationDisplay ? 'Foundation page imports runtime display components' : 'Source type mismatch',
    isFoundationDisplay
      ? `${manifestEntry.pageId} (${manifestEntry.kind}) imports ${actualSourceType} sources for asset display; allowed but tracked.`
      : `Expected ${manifestEntry.expectedSourceType}, but ${file} currently resolves to ${actualSourceType}.`
  )
}
```

**口径要求**：
- 仅 `kind === 'foundation'` 的 source-type 不匹配 → warn（IconPage 即此情况：foundation 页用 runtime `Icon` 做资产目录展示）
- `kind === 'component'` 的 source-type 不匹配 → 仍然 error（避免组件页悄悄退回 runtime）

### 改动 1.3 — `overallPass` 改成"无 error 即 pass"，summary 拆出 inReview 计数

定位：约 line 181–198（summary 块）。

当前：

```js
const componentPages = pages.filter((page) => page.kind === 'component')
const approvedComponentPages = componentPages.filter((page) =>
  Object.values(page.gateStatus).every((status) => status === 'pass')
)

const summary = {
  checkedAt: new Date().toISOString(),
  goal: manifest.goal,
  totals: {
    pagesChecked: pages.length,
    componentPages: componentPages.length,
    approvedComponentPages: approvedComponentPages.length,
    blockedComponentPages: componentPages.length - approvedComponentPages.length,
    errors: issues.filter((issue) => issue.severity === 'error').length,
    warnings: issues.filter((issue) => issue.severity === 'warn').length,
  },
  overallPass: componentPages.length > 0 && approvedComponentPages.length === componentPages.length,
}
```

改为：

```js
const componentPages = pages.filter((page) => page.kind === 'component')
const approvedComponentPages = componentPages.filter((page) =>
  Object.values(page.gateStatus).every((status) => status === 'pass')
)
const inReviewComponentPages = componentPages.filter(
  (page) => page.gateStatus.review === 'in-review'
)
const blockedComponentPages = componentPages.filter((page) =>
  Object.values(page.gateStatus).some((status) => status === 'fail')
)

const errorCount = issues.filter((issue) => issue.severity === 'error').length
const warningCount = issues.filter((issue) => issue.severity === 'warn').length

const summary = {
  checkedAt: new Date().toISOString(),
  goal: manifest.goal,
  totals: {
    pagesChecked: pages.length,
    componentPages: componentPages.length,
    approvedComponentPages: approvedComponentPages.length,
    inReviewComponentPages: inReviewComponentPages.length,
    blockedComponentPages: blockedComponentPages.length,
    errors: errorCount,
    warnings: warningCount,
  },
  overallPass: errorCount === 0,
}
```

**口径要求**：
- `approvedComponentPages` 仍然只数严格 approved（4 gate 全 pass），不虚报
- `inReviewComponentPages`：review gate 为 `in-review` 的页面（新增字段）
- `blockedComponentPages`：任一 gate 为 `fail` 的页面（**只数真阻塞**，不再把 in-review 算进 blocked）
- `overallPass = errorCount === 0`：warnings 不阻塞 audit

---

## 任务 2：跑审计验证

```bash
pnpm audit:docs-site 2>&1 | head -25
```

期望输出（按当前 manifest 状态）：

```json
"totals": {
  "pagesChecked": 28,
  "componentPages": 22,
  "approvedComponentPages": 17,
  "inReviewComponentPages": 5,
  "blockedComponentPages": 0,
  "errors": 0,
  "warnings": 6
},
"overallPass": true
```

（warnings = 5 in-review + 1 IconPage foundation source-type）

如果实际数字不是这样，**STOP 报告**，列出 issues 数组里的 severity 分布，等待用户指令。**不要为了凑数继续改脚本**。

---

## 任务 3：跑相邻审计确认无回归

```bash
pnpm audit:figma-conformance 2>&1 | tail -15
pnpm test 2>&1 | tail -8
```

期望：
- `figma-conformance overallPass=true`，errors=0
- `pnpm test` 全部通过（最近基线 105 / 105）

任一失败 STOP 报告。

---

## 任务 4：更新 `docs/site-pixel-parity-mechanism.md`

定位"机器审计"段（搜 `## 机器审计` 或 `pnpm audit:docs-site`）。

在该段末尾追加一个子段：

```markdown
### 严重程度口径（2026-04-28 调整）

机器审计的 issue 分两级：

- **error（阻塞 overallPass）**
  - component 页缺 Figma baseline（`figmaPage / figmaComponentSet / figmaNodeId` 任一缺失）
  - component 页未消费 canonical（`actualSourceType !== 'canonical-only'`）
  - component 页非 figma-frame 渲染模式
  - component 页 `pixelReviewStage` 既非 `approved` 也非 `in-review`（如 `blocked` 或未知）
  - component 页 source-type 与 manifest 期望不匹配
  - manifest 引用的页面文件不存在 / 页面文件未登记 manifest

- **warn（不阻塞，但仍记录在 issues）**
  - component 页 `pixelReviewStage='in-review'`：已进入像素核对但未签字，属正常中间态
  - foundation 页（如 Icon / Color / Typography）source-type 与 manifest 期望不匹配：foundation 页允许导入 runtime 共享展示组件做资产目录，不视为 Figma-first 退化
  - foundation 页 `currentRenderingMode='docs-demo'`

`overallPass` 取决于 errors 是否为 0；warnings 不阻塞主 Session 启动门槛，但必须在 handoff 中显式列出待处理项。
```

不动该文件其它内容。

---

## 任务 5：写 execution report

输出：`docs/internal/audit-docs-site-gate-relax-execution-report.md`

格式：

```markdown
# audit:docs-site Gate Relax Execution Report

跑时间：YYYY-MM-DD HH:MM:SS

## 改动 1：审计脚本口径调整
- 文件：figma-sync/audit-docs-site-readiness.mjs
- in-review → warn（review gate 新增 `in-review` 状态）
- foundation source-type 不匹配 → warn
- summary 新增 `inReviewComponentPages`，`blockedComponentPages` 只计真 fail
- `overallPass` 改为 `errorCount === 0`

## 改动 2：site-pixel-parity-mechanism.md 文档同步
- 在"机器审计"段追加严重程度口径

## 任务 2 验证：pnpm audit:docs-site
- approvedComponentPages: [N]
- inReviewComponentPages: [N]
- blockedComponentPages: [N]
- errors: [N]
- warnings: [N]
- overallPass: [true/false]

## 任务 3 验证
- pnpm audit:figma-conformance：[overallPass=true / errors=0]
- pnpm test：[N / N passed]

## 异常项（如有）
[空 / 描述]
```

---

## 任务 6：自己 commit

由你（Codex）自己 commit 本轮改动。

### commit 范围（精确）

包含：
- `figma-sync/audit-docs-site-readiness.mjs`（脚本口径调整）
- `docs/site-pixel-parity-mechanism.md`（文档同步）
- `docs/internal/audit-docs-site-gate-relax-execution-report.md`（执行报告）
- `docs/internal/_prompts/audit-docs-site-gate-relax.prompt.md`（本 prompt 归档）

不要 commit：
- `docs/internal/published-vs-code-audit.md`（M，audit 脚本副作用，按约定 git restore）
- `figma-data/normalized/published-vs-code.audit.json`（M，同上）
- `figma-data/published/icons/manifest.json`（如出现，仅时间戳变化，git restore）

### commit message

```
chore(audit): relax docs-site gate — in-review and foundation runtime imports become warnings

Problem:
- audit:docs-site treated 5 in-review component pages as fatal errors,
  hard-blocking all main-session audits despite being expected mid-state.
- IconPage.vue (foundation) imports runtime Icon for asset catalog display,
  flagged as source-type mismatch error.

Change:
- pixelReviewStage='in-review' → severity=warn, gate=in-review (new state).
- foundation kind source-type mismatch → severity=warn (Icon catalog allowed).
- overallPass now requires only errors=0; warnings do not block.
- summary surfaces approvedComponentPages / inReviewComponentPages /
  blockedComponentPages separately (no inflation of approved count).

Hard gates preserved for component pages:
- missing Figma baseline → error
- not canonical-only → error
- not figma-frame → error
- review stage other than approved/in-review → error

Doc updated: site-pixel-parity-mechanism.md severity policy section.

Co-Authored-By: Codex
```

---

## 禁止

- ❌ 不要把 component 页的 source-type / baseline / frame / canonical gate 也降为 warn——只放宽 in-review 和 foundation source-type 这两个口子
- ❌ 不要修改 `docs/site-review-manifest.json`（manifest 内容是否需要改另说，本轮只动审计口径）
- ❌ 不要改任何 `playground/docs/pages/*.vue`
- ❌ 不要改任何 `src/` 下的代码
- ❌ 不要改 `docs/session-handoff.md`（主 Session 自己改）
- ❌ 不要改 `docs/conformance-issue-log.md`（主 Session 自己改）
- ❌ 不要把 in-review 计入 approvedComponentPages（保持严格定义）
- ❌ 不要让 `overallPass` 受 warnings 影响

---

## 完成后

1. 报告 + 自 commit 完成后 STOP
2. 把执行报告路径告诉用户
3. 等待主 Session 接手处理 handoff / conformance-issue-log 同步

完成后 STOP。
