Files
OneOS1.2/docs/superpowers/plans/2026-07-25-autorodo-web.md

717 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AutoRDO Web 工作台 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 落地 Axhub 原型 `autorodo-web`:粘贴素材 → 复制 AutoRDO 清洗提示词 → 粘回初稿 → 按需求分页确认待确认并回填描述 → 填写优先级/标签/提交部门/提交人 → 一键复制 YunxiaoPMapp 多条记录需求提示词。
**Architecture:** 纯函数放在原型内 `lib/`(解析初稿、出题回填、拼提示词、识别部门/提交人UI 为三步工作台React + OneOS V2 Token。MVP 不连云效、不嵌 OCR/ASRCursor 往返靠剪贴板。预留 `agentAdapter` 接口形状供组织 Agent。
**Tech Stack:** React + TypeScriptAxhub Make 原型、Vitest、OneOS V2`oneos-ds-tokens.css` + `UIComponents` 按需)、`PrototypeAnnotationHost`
**Spec:** [docs/superpowers/specs/2026-07-25-autorodo-web-design.md](../specs/2026-07-25-autorodo-web-design.md)
---
## 文件结构(锁定)
| 路径 | 职责 |
|------|------|
| `src/prototypes/autorodo-web/lib/types.ts` | 需求稿、待确认点、元数据、步骤状态类型 |
| `src/prototypes/autorodo-web/lib/parseDraft.ts` | 解析粘回的 AutoRDO Markdown → `RequirementDraft[]` |
| `src/prototypes/autorodo-web/lib/parseDraft.test.ts` | 解析单测 |
| `src/prototypes/autorodo-web/lib/applyAnswer.ts` | 选择题/补充 → 回填描述、消待确认 |
| `src/prototypes/autorodo-web/lib/applyAnswer.test.ts` | 回填单测 |
| `src/prototypes/autorodo-web/lib/buildCleanPrompt.ts` | 步骤 1 清洗提示词 |
| `src/prototypes/autorodo-web/lib/buildRecordPrompt.ts` | 步骤 3 YunxiaoPMapp 多条口令 |
| `src/prototypes/autorodo-web/lib/buildRecordPrompt.test.ts` | 上报词单测 |
| `src/prototypes/autorodo-web/lib/inferMeta.ts` | 从原文推断提交部门/提交人 |
| `src/prototypes/autorodo-web/lib/inferMeta.test.ts` | 推断单测 |
| `src/prototypes/autorodo-web/lib/agentAdapter.ts` | 预留 `clean` / `record` 接口类型MVP 空实现) |
| `src/prototypes/autorodo-web/lib/clipboard.ts` | `navigator.clipboard.writeText` 封装 |
| `src/prototypes/autorodo-web/lib/pendingQuestions.ts` | 从「待确认」文案生成选择题选项(词典摘要常量) |
| `src/prototypes/autorodo-web/components/StepPaste.tsx` | 步骤 1 UI |
| `src/prototypes/autorodo-web/components/StepConfirm.tsx` | 步骤 2 UI |
| `src/prototypes/autorodo-web/components/StepExport.tsx` | 步骤 3 UI |
| `src/prototypes/autorodo-web/AutorodoWebApp.tsx` | 三步状态机主壳 |
| `src/prototypes/autorodo-web/index.tsx` | 入口 `@name` + AnnotationHost |
| `src/prototypes/autorodo-web/style.css` | 布局与触控样式 |
| `src/prototypes/autorodo-web/annotation-source.json` | 标注目录 |
| `src/prototypes/autorodo-web/.spec/requirements-prd.md` | AutoPRD |
| `src/prototypes/autorodo-web/.spec/confirm-flow.md` | 确认与回填规则全文 |
| `src/resources/prd/autorodo-web-autoprd.md` | PRD 副本(若项目惯例需要) |
| 修改 `.axhub/make/project.json` | 注册原型(若 Make 未自动发现) |
| 修改 `~/.cursor/skills/YunxiaoPMapp` + 项目内副本 | 记录需求解析四字段Task 8可同迭代或紧随 |
**不放入 `src/common/`**:逻辑仅本原型使用,避免污染公共层。
---
### Task 1: 类型 + parseDraft + 单测
**Files:**
- Create: `src/prototypes/autorodo-web/lib/types.ts`
- Create: `src/prototypes/autorodo-web/lib/parseDraft.ts`
- Create: `src/prototypes/autorodo-web/lib/parseDraft.test.ts`
- [ ] **Step 1: 写入类型**
```ts
// src/prototypes/autorodo-web/lib/types.ts
export type Priority = '紧急' | '高' | '中' | '低';
export type RequirementMeta = {
priority: Priority | '';
tags: string[];
submitDept: string;
submitter: string;
titleKind: '新增' | '优化' | '';
};
export type PendingItem = {
id: string;
raw: string;
question: string;
options: string[];
resolved: boolean;
answer?: string;
};
export type RequirementDraft = {
index: number;
title: string;
description: string;
pendings: PendingItem[];
meta: RequirementMeta;
confirmed: boolean;
};
export type WizardStep = 1 | 2 | 3;
```
- [ ] **Step 2: 写失败单测(多条 + 待确认)**
```ts
// src/prototypes/autorodo-web/lib/parseDraft.test.ts
import { describe, it, expect } from 'vitest';
import { parseAutorodoDraft } from './parseDraft';
const SAMPLE = `共 2 条
### 1
## 原始诉求AutoRDO
**标题**:合同台账批量导出
**描述**
在租赁合同台账支持批量导出
待确认:
- 导出范围未说明
### 2
## 原始诉求AutoRDO
**标题**:证照到期提醒
**描述**
调整证照到期提醒口径
待确认:
`;
describe('parseAutorodoDraft', () => {
it('splits multiple requirements and pending items', () => {
const list = parseAutorodoDraft(SAMPLE);
expect(list).toHaveLength(2);
expect(list[0].title).toContain('合同台账');
expect(list[0].pendings).toHaveLength(1);
expect(list[0].pendings[0].raw).toContain('导出范围');
expect(list[1].pendings).toHaveLength(0);
expect(list[1].confirmed).toBe(true);
});
});
```
- [ ] **Step 3: 跑测确认失败**
Run: `npx vitest run src/prototypes/autorodo-web/lib/parseDraft.test.ts`
Expected: FAIL模块不存在或 `parseAutorodoDraft` 未定义)
- [ ] **Step 4: 实现解析**
```ts
// src/prototypes/autorodo-web/lib/parseDraft.ts
import type { RequirementDraft, PendingItem, RequirementMeta } from './types';
const emptyMeta = (): RequirementMeta => ({
priority: '',
tags: [],
submitDept: '',
submitter: '',
titleKind: '',
});
function parsePendings(block: string, reqIndex: number): PendingItem[] {
const m = block.match(/待确认[:]\s*([\s\S]*?)(?=\n###|\n##\s*原始诉求|$)/);
if (!m) return [];
const body = m[1].trim();
if (!body || body === '无') return [];
const lines = body
.split('\n')
.map((l) => l.replace(/^[-*•\d.、)\s]+/, '').trim())
.filter(Boolean);
return lines.map((raw, i) => ({
id: `r${reqIndex}-p${i}`,
raw,
question: raw,
options: [],
resolved: false,
}));
}
export function parseAutorodoDraft(md: string): RequirementDraft[] {
const parts = md.split(/(?=^###\s*\d+)/m).filter((p) => /原始诉求AutoRDO/.test(p) || /\*\*标题\*\*/.test(p));
const chunks =
parts.length > 0
? parts
: md.includes('**标题**')
? [md]
: [];
return chunks.map((chunk, index) => {
const title = (chunk.match(/\*\*标题\*\*[:]\s*(.+)/)?.[1] ?? '').trim();
const descMatch = chunk.match(/\*\*描述\*\*[:]\s*\n?([\s\S]*?)(?=\n待确认|$)/);
const description = (descMatch?.[1] ?? '').trim();
const pendings = parsePendings(chunk, index);
return {
index,
title,
description,
pendings,
meta: emptyMeta(),
confirmed: pendings.length === 0,
};
});
}
```
- [ ] **Step 5: 跑测确认通过**
Run: `npx vitest run src/prototypes/autorodo-web/lib/parseDraft.test.ts`
Expected: PASS
- [ ] **Step 6: Commit**(仅当用户要求提交时执行;否则跳过所有 Commit 步骤)
```bash
git add src/prototypes/autorodo-web/lib/types.ts src/prototypes/autorodo-web/lib/parseDraft.ts src/prototypes/autorodo-web/lib/parseDraft.test.ts
git commit -m "$(cat <<'EOF'
feat(autorodo-web): add AutoRDO draft parser and types
EOF
)"
```
---
### Task 2: applyAnswer + pendingQuestions
**Files:**
- Create: `src/prototypes/autorodo-web/lib/applyAnswer.ts`
- Create: `src/prototypes/autorodo-web/lib/applyAnswer.test.ts`
- Create: `src/prototypes/autorodo-web/lib/pendingQuestions.ts`
- [ ] **Step 1: 写回填单测**
```ts
import { describe, it, expect } from 'vitest';
import { applyPendingAnswer } from './applyAnswer';
import type { RequirementDraft } from './types';
const base: RequirementDraft = {
index: 0,
title: '合同台账批量导出',
description: '在租赁合同台账支持批量导出\n导出范围待确认',
pendings: [
{
id: 'r0-p0',
raw: '导出范围未说明',
question: '导出范围指什么?',
options: ['当前筛选结果', '全部合同', '仅勾选行'],
resolved: false,
},
],
meta: { priority: '', tags: [], submitDept: '', submitter: '', titleKind: '' },
confirmed: false,
};
describe('applyPendingAnswer', () => {
it('merges answer into description and marks pending resolved', () => {
const next = applyPendingAnswer(base, 'r0-p0', '当前筛选结果');
expect(next.pendings[0].resolved).toBe(true);
expect(next.pendings[0].answer).toBe('当前筛选结果');
expect(next.description).toContain('当前筛选结果');
expect(next.description).not.toMatch(/导出范围:待确认/);
expect(next.confirmed).toBe(true);
});
});
```
- [ ] **Step 2: 跑测确认失败**
Run: `npx vitest run src/prototypes/autorodo-web/lib/applyAnswer.test.ts`
Expected: FAIL
- [ ] **Step 3: 实现 applyAnswer + 简易出题**
```ts
// applyAnswer.ts
import type { RequirementDraft } from './types';
export function applyPendingAnswer(
draft: RequirementDraft,
pendingId: string,
answer: string,
): RequirementDraft {
const pendings = draft.pendings.map((p) =>
p.id === pendingId ? { ...p, resolved: true, answer: answer.trim() } : p,
);
const hit = draft.pendings.find((p) => p.id === pendingId);
let description = draft.description;
if (hit) {
const label = hit.raw.replace(/未说明|待确认|不清楚/g, '').trim() || hit.raw;
if (/待确认/.test(description)) {
description = description.replace(/待确认/g, answer.trim());
} else {
description = `${description.replace(/\s+$/, '')}\n${label}${answer.trim()}`;
}
}
const confirmed = pendings.every((p) => p.resolved);
return { ...draft, description, pendings, confirmed };
}
// pendingQuestions.ts — MVP关键词启发式无匹配则「是 / 否 / 需补充」
export function buildOptionsForPending(raw: string): { question: string; options: string[] } {
if (/导出范围|范围/.test(raw)) {
return {
question: '「导出范围」指什么?',
options: ['当前筛选结果', '全部数据', '仅勾选行'],
};
}
if (/模块|归属/.test(raw)) {
return {
question: '归属哪个业务模块?',
options: ['租赁合同管理', '车辆管理', '证照管理', '还车应结款'],
};
}
return {
question: raw.endsWith('') || raw.endsWith('?') ? raw : `${raw}`,
options: ['确认按原文理解', '暂不纳入本需求', '需文字补充'],
};
}
export function enrichPendingsWithQuestions(draft: RequirementDraft): RequirementDraft {
return {
...draft,
pendings: draft.pendings.map((p) => {
const q = buildOptionsForPending(p.raw);
return { ...p, question: q.question, options: q.options };
}),
};
}
```
`parseAutorodoDraft` 返回前对每条调用 `enrichPendingsWithQuestions`,或在 UI 粘回后统一 enrich二选一推荐 UI 粘回后调用,保持 parse 纯净)。
- [ ] **Step 4: 跑测确认通过**
Run: `npx vitest run src/prototypes/autorodo-web/lib/applyAnswer.test.ts`
Expected: PASS
- [ ] **Step 5: Commit**(用户要求时)
---
### Task 3: inferMeta + buildCleanPrompt + buildRecordPrompt
**Files:**
- Create: `src/prototypes/autorodo-web/lib/inferMeta.ts`
- Create: `src/prototypes/autorodo-web/lib/inferMeta.test.ts`
- Create: `src/prototypes/autorodo-web/lib/buildCleanPrompt.ts`
- Create: `src/prototypes/autorodo-web/lib/buildRecordPrompt.ts`
- Create: `src/prototypes/autorodo-web/lib/buildRecordPrompt.test.ts`
- Create: `src/prototypes/autorodo-web/lib/clipboard.ts`
- Create: `src/prototypes/autorodo-web/lib/agentAdapter.ts`
- [ ] **Step 1: inferMeta 单测**
```ts
import { describe, it, expect } from 'vitest';
import { inferSubmitMeta } from './inferMeta';
describe('inferSubmitMeta', () => {
it('detects dept and person from free text', () => {
const r = inferSubmitMeta('业务管理组张三反馈:合同导出不好用');
expect(r.submitDept).toMatch(/业务/);
expect(r.submitter).toContain('张三');
});
});
```
- [ ] **Step 2: 实现 inferMeta**
```ts
const DEPT_PATTERNS = [
/(?:提交部门|部门)[:]\s*([^\s,;]+)/,
/(业务管理组|产品部|安全部|运营部|财务部|技术部)/,
];
const PERSON_PATTERNS = [
/(?:提交人|反馈人|提出人)[:]\s*([^\s,;]+)/,
/@([\u4e00-\u9fa5]{2,4})/,
/([\u4e00-\u9fa5]{2,4})反馈/,
];
export function inferSubmitMeta(text: string): { submitDept: string; submitter: string } {
let submitDept = '';
let submitter = '';
for (const re of DEPT_PATTERNS) {
const m = text.match(re);
if (m?.[1]) {
submitDept = m[1];
break;
}
}
for (const re of PERSON_PATTERNS) {
const m = text.match(re);
if (m?.[1]) {
submitter = m[1];
break;
}
}
return { submitDept, submitter };
}
```
- [ ] **Step 3: buildRecordPrompt 单测 + 实现**
```ts
// buildRecordPrompt.test.ts
import { describe, it, expect } from 'vitest';
import { buildYunxiaoRecordPrompt } from './buildRecordPrompt';
import type { RequirementDraft } from './types';
const one: RequirementDraft = {
index: 0,
title: '合同台账批量导出',
description: '在租赁合同台账支持按筛选结果批量导出 Excel',
pendings: [],
meta: {
priority: '中',
tags: ['租赁合同'],
submitDept: '产品部',
submitter: '王冕',
titleKind: '新增',
},
confirmed: true,
};
describe('buildYunxiaoRecordPrompt', () => {
it('includes priority tags dept submitter', () => {
const text = buildYunxiaoRecordPrompt([one]);
expect(text).toContain('YunxiaoPMapp');
expect(text).toContain('记录需求:【新增】合同台账批量导出');
expect(text).toContain('优先级=中');
expect(text).toContain('标签=租赁合同');
expect(text).toContain('提交部门=产品部');
expect(text).toContain('提交人=王冕');
expect(text).toContain('推进至=暂不推进');
});
it('throws when meta incomplete', () => {
expect(() =>
buildYunxiaoRecordPrompt([{ ...one, meta: { ...one.meta, submitter: '' } }]),
).toThrow(/提交人/);
});
});
```
```ts
// buildRecordPrompt.ts
import type { RequirementDraft } from './types';
export function metaComplete(d: RequirementDraft): boolean {
const m = d.meta;
return Boolean(
m.priority && m.tags.length > 0 && m.submitDept.trim() && m.submitter.trim() && m.titleKind,
);
}
export function buildYunxiaoRecordPrompt(drafts: RequirementDraft[]): string {
for (const d of drafts) {
if (!d.confirmed) throw new Error(`需求 ${d.index + 1} 仍有未确认项`);
if (!metaComplete(d)) throw new Error(`需求 ${d.index + 1} 缺少优先级/标签/提交部门/提交人/类型`);
}
const lines = drafts.map((d) => {
const title = `${d.meta.titleKind}${d.title.replace(/^【(?:新增|优化)】/, '')}`;
const tags = d.meta.tags.join('、');
return `记录需求:${title};描述=${d.description.replace(/\n/g, ' ')};优先级=${d.meta.priority};标签=${tags};提交部门=${d.meta.submitDept};提交人=${d.meta.submitter};推进至=暂不推进`;
});
return [
'YunxiaoPMapp',
'请按下列条目依次记录需求;每条保持独立,不要合并。',
'',
...lines,
].join('\n');
}
```
```ts
// buildCleanPrompt.ts
export function buildCleanPrompt(payload: {
text: string;
attachmentNames: string[];
}): string {
const files =
payload.attachmentNames.length > 0
? `附件:${payload.attachmentNames.join('、')}(请用多模态识读图/语音内容)`
: '附件:无';
return [
'AutoRDO',
'请按 AutoRDO 规则清洗下列素材:多条独立诉求拆成多份;提炼标题与书面描述;不确定处标「待确认」;描述无结尾句号。',
files,
'',
'—— 素材开始 ——',
payload.text.trim() || '(仅附件,无正文)',
'—— 素材结束 ——',
].join('\n');
}
```
```ts
// clipboard.ts
export async function copyText(text: string): Promise<void> {
await navigator.clipboard.writeText(text);
}
// agentAdapter.ts
export type CleanRequest = { text: string; attachmentNames: string[] };
export type RecordRequest = { drafts: import('./types').RequirementDraft[] };
/** MVP未接组织 Agent后续替换实现即可 */
export const agentAdapter = {
async clean(_req: CleanRequest): Promise<null> {
return null;
},
async record(_req: RecordRequest): Promise<null> {
return null;
},
};
```
- [ ] **Step 4: 跑全部 lib 单测**
Run: `npx vitest run src/prototypes/autorodo-web/lib`
Expected: 全部 PASS
- [ ] **Step 5: Commit**(用户要求时)
---
### Task 4: 原型壳 + 步骤 1 UI
**Files:**
- Create: `src/prototypes/autorodo-web/index.tsx`
- Create: `src/prototypes/autorodo-web/AutorodoWebApp.tsx`
- Create: `src/prototypes/autorodo-web/style.css`
- Create: `src/prototypes/autorodo-web/components/StepPaste.tsx`
- Create: `src/prototypes/autorodo-web/annotation-source.json`(先最小目录)
- Modify: `.axhub/make/project.json`(若启动后未出现在列表则补注册)
前置Read `src/resources/design-system/DESIGN.md`Token、触控 ≥44px、禁止原生 select
- [ ] **Step 1: 入口与主壳骨架**
```tsx
// index.tsx
/**
* @name AutoRDO 需求清洗工作台
*/
import './style.css';
import '../../../resources/design-system/oneos-ds-tokens.css';
import React from 'react';
import { PrototypeAnnotationHost } from '../../common/prototype-annotation-host';
import type { AnnotationSourceDocument } from '@axhub/annotation';
import annotationSourceDocument from './annotation-source.json';
import { AutorodoWebApp } from './AutorodoWebApp';
export default function AutorodoWebEntry() {
return (
<>
<AutorodoWebApp />
<PrototypeAnnotationHost
source={annotationSourceDocument as AnnotationSourceDocument}
options={{}}
/>
</>
);
}
```
`AutorodoWebApp`:左侧步骤 1/2/3`step` state步骤 1 渲染 `StepPaste`
- [ ] **Step 2: StepPaste**
- contentEditable 或 textarea 接收粘贴;`onPaste` 收集 `clipboardData.files`image/*、audio/*)为附件名列表(原型阶段可用 File.name不上传
- 按钮「确认并复制清洗提示词」→ `buildCleanPrompt` + `copyText`toast「已复制请粘到 Cursor 跑 AutoRDO」
- 可选 checkbox「粘贴后自动复制」默认关
- 控件:优先 `V2` 封装;按钮 min-height 44px
- [ ] **Step 3: 本地预览**
Run: 打开 Make 预览 `/prototypes/autorodo-web`
Expected: 能粘贴、点确认后剪贴板为 AutoRDO 提示词
- [ ] **Step 4: Commit**(用户要求时)
---
### Task 5: 步骤 2 确认 UI
**Files:**
- Create: `src/prototypes/autorodo-web/components/StepConfirm.tsx`
- Modify: `src/prototypes/autorodo-web/AutorodoWebApp.tsx`
- [ ] **Step 1: 粘回区 + 解析**
- textarea「粘回 AutoRDO 初稿」
- 按钮「解析初稿」→ `parseAutorodoDraft``enrichPendingsWithQuestions` → 对每条 `inferSubmitMeta(description + title)` 预填 meta
- Pill 切换需求 index
- [ ] **Step 2: 左右分栏确认**
- 左:标题(可编辑)+ 描述(只读展示实时稿)
- 右:当前未解决 pending单选 options补充 input「确认并下一题」调用 `applyPendingAnswer`
- 元数据:优先级四选一;标签用可增删 chip自由输入 MVP提交部门/提交人 input类型 新增/优化
- 全部 confirmed 且 `metaComplete` 后可进步骤 3
- [ ] **Step 3: 手动验收路径**
1. 粘贴 Task1 SAMPLE 初稿
2. 答完题后描述含答案且无「待确认」
3. 填齐元数据
- [ ] **Step 4: Commit**(用户要求时)
---
### Task 6: 步骤 3 导出 + 样式打磨
**Files:**
- Create: `src/prototypes/autorodo-web/components/StepExport.tsx`
- Modify: `style.css``AutorodoWebApp.tsx`
- [ ] **Step 1: StepExport**
- 预览 `buildYunxiaoRecordPrompt(drafts)`
- 「一键复制上报提示词」
- 「复制定稿 Markdown」输出多份已确认 `## 原始诉求AutoRDO`,待确认:无)
- 错误态:捕获 throw页面内提示缺哪条哪字段
- [ ] **Step 2: 响应式**
- ≤767px步骤条顶置确认区改为上下堆叠触控 ≥44px正文 ≥14px
- [ ] **Step 3: 预览验收**
全路径走通:粘贴 → 复制清洗词 →(模拟)粘回 SAMPLE → 确认 → 复制上报词,粘贴到文本编辑器检查字段齐全。
- [ ] **Step 4: Commit**(用户要求时)
---
### Task 7: AutoPRD + 标注 + 导航同步
**Files:**
- Create: `src/prototypes/autorodo-web/.spec/confirm-flow.md`
- Create: `src/prototypes/autorodo-web/.spec/requirements-prd.md`
- Create: `src/resources/prd/autorodo-web-autoprd.md`(与 PRD 同步)
- Modify: `annotation-source.json`(产品需求说明节点)
- [ ] **Step 1: 写 confirm-flow.md**
含:判定顺序表、前置条件、数据源(粘回 Markdown / 本地启发式选项)、用户可见结果、标明未接真 API。
- [ ] **Step 2: 写 requirements-prd.md**
按 oneos-autoprd 结构:总览/目标/边界/角色/用户故事(起点→运作→闭环)/验收;链到 `confirm-flow.md`
- [ ] **Step 3: 同步标注与导航**
```bash
npm run nav:sync -- --prototype autorodo-web --note "新增 AutoRDO 网页清洗与云效上报提示词工作台"
```
- [ ] **Step 4: Commit**(用户要求时)
---
### Task 8: YunxiaoPMapp 消费四字段Skill 扩展)
**Files:**
- Modify: `~/.claude/skills/YunxiaoPMapp/references/commands.md`(及项目 `.cursor` / `.claude` 同步副本)
- Modify: YunxiaoPMapp `SKILL.md` 记录需求参数说明
- 可选:`references/record-meta-fields.md` 新文件
- [ ] **Step 1: 文档约定口令字段**
在口令面增加:
```text
记录需求:…;优先级=紧急|高|中|低;标签=…;提交部门=…;提交人=…;推进至=…
```
说明:网页上报词已带齐时,**禁止**再 Plan 重复问这四项(除非缺省);缺省则仍问。
- [ ] **Step 2: 实现侧**
若现有 live 脚本已支持 priority/tag把提交部门/提交人映射到云效字段(查 `runtime-ids.json`;未验证字段则先写入描述尾部 `提交部门/提交人`,并在文档标明「字段 ID 待验证」)。
- [ ] **Step 3: 与网页联调**
用步骤 3 复制出的提示词在 Cursor 跑一次「记录需求」(测试项目或 dry-run 策略按团队惯例)。
- [ ] **Step 4: Commit**(用户要求时)
---
## 规格覆盖自检
| Spec 要求 | Task |
|-----------|------|
| 粘贴文/图/语音 + 复制清洗词 | 4 |
| 粘回初稿 + 分页确认 + 回填 | 1,2,5 |
| 优先级/标签/部门/提交人 | 3,5,6 |
| 一键 Yunxiao 多条口令 | 3,6 |
| 预留组织 Agent | 3 `agentAdapter` |
| AutoPRD / 业务规则文档 | 7 |
| Yunxiao 消费四字段 | 8 |
| 不直连云效 / 无 OCR | 全程遵守 |
---
## 执行说明
- 所有 **Commit 步骤默认跳过**,除非用户明确要求提交。
- Task 8 可与 Task 47 并行由另一会话做;网页 MVP 以 Task 17 为可演示闭环(上报词已含四字段,即使 Skill 暂未写入云效自定义字段,口令仍可用于人工/后续 Skill
---
Plan complete and saved to `docs/superpowers/plans/2026-07-25-autorodo-web.md`.
**两种执行方式:**
1. **Subagent-Driven推荐** — 每任务开新子代理,任务间复核,迭代快
2. **Inline Execution** — 本会话按 executing-plans 连续执行,设检查点
要哪一种?