Compare commits

..

9 Commits

Author SHA1 Message Date
王冕
1e234df768 chore: 合并后同步 AutoRDO 导航注册表元数据。
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-28 16:24:54 +08:00
王冕
c3eaa7c643 merge: 将 feat/message-hub 合入 main,保留功能分支 AutoRDO/导航注册并合并测试配置。
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-28 16:24:43 +08:00
王冕
3fa7ffa4c9 chore: 为 Axhub 版本协作配置默认主分支 main。
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-28 16:24:08 +08:00
王冕
5d51a6bf7a 新增 AutoRDO 需求清洗工作台与消息中枢,迭代 OneOS V2 设计规范及租赁合同/工作台/车辆等原型,同步云效技能与导航注册;并归档一批 legacy 原型快照。
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-28 15:50:35 +08:00
王冕
ff4b7b67dc feat(autorodo-web): add AutoRDO paste-confirm-export workbench
Enable PM clipboard round-trip: multimodal paste → AutoRDO clean prompt → pending Q&A with meta → Yunxiao multi-record prompt copy.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-25 01:06:22 +08:00
王冕
cf82f25611 checkpoint before checking out feat/message-hub 2026-07-25 00:39:20 +08:00
王冕
b14425da5a feat(vehicle-return-settlement): 运维办理人转交与审批中费用明细只读
支持办理人/主管转交运维段任务并记录原因;待审批与审批中可进费用明细但运维费用只读,审批完成不可进入。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-22 17:52:40 +08:00
王冕
a01d2ab708 扩展氢能站点、加氢记录与台账原型链路,新增工作台、车辆资产 H5、自营物流等原型,并同步导航注册、PRD 资源与交付技能。
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-21 17:15:39 +08:00
王冕
e39df1c7c8 迭代加氢订单、站点记录与台账链路,同步审批组件与导航注册,并下线旧工作台入口。
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-21 00:04:50 +08:00
1607 changed files with 591240 additions and 14370 deletions

View File

@@ -0,0 +1,297 @@
---
name: user-story-mapping
argument-hint: "[product or workflow]"
description: Create a user story map that lays out activities, steps, tasks, and release slices. Use when planning a workflow, backlog, or MVP around the user journey.
intent: >-
Visualize the user journey by creating a hierarchical map that breaks down high-level activities into steps and tasks, organized left-to-right as a narrative flow. Use this to build shared understanding across product, design, and engineering, prioritize features based on user workflows, and identify gaps or opportunities in the user experience.
type: component
---
## Purpose
Visualize the user journey by creating a hierarchical map that breaks down high-level activities into steps and tasks, organized left-to-right as a narrative flow. Use this to build shared understanding across product, design, and engineering, prioritize features based on user workflows, and identify gaps or opportunities in the user experience.
This is not a backlog—it's a strategic artifact that shows *how* users accomplish their goals, which then informs *what* to build.
## Input
**Works best with:** The product or user workflow being mapped.
**Also useful:** The primary user, the end-to-end narrative as you understand it, existing backlog items to place, and release goals.
Anything supplied with the invocation itself — text after the skill name, a pasted context dump, or an appended `ARGUMENTS:` line — counts as answers already given. Use it and skip whatever it covers; don't re-ask.
**Arriving empty-handed? That works too.** The skill asks whose journey you're mapping and what they're trying to get done, then builds backbone → tasks → slices.
**Example invocation:** `Story map for our expense-reporting flow, from receipt capture to reimbursement, with an MVP slice for the pilot.`
## Key Concepts
### The Jeff Patton Story Mapping Framework
Invented by Jeff Patton, story mapping organizes work into a 2D structure:
**Horizontal axis (left-to-right):** User journey over time
- **Backbone:** High-level activities the user performs
- **Steps:** Specific actions within each activity
- **Tasks:** Detailed work required to complete each step
**Vertical axis (top-to-bottom):** Priority and releases
- **Top rows:** Essential tasks (MVP / Release 1)
- **Lower rows:** Nice-to-have tasks (Future releases)
### Story Map Structure
```
Segment → Persona → Narrative (User's goal)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[Activity 1] → [Activity 2] → [Activity 3] → [Activity 4] → [Activity 5]
↓ ↓ ↓ ↓ ↓
[Step 1.1] [Step 2.1] [Step 3.1] [Step 4.1] [Step 5.1]
[Step 1.2] [Step 2.2] [Step 3.2] [Step 4.2] [Step 5.2]
[Step 1.3] [Step 2.3] [Step 3.3] [Step 4.3] [Step 5.3]
↓ ↓ ↓ ↓ ↓
[Task 1.1.1] [Task 2.1.1] [Task 3.1.1] [Task 4.1.1] [Task 5.1.1]
[Task 1.1.2] [Task 2.1.2] [Task 3.1.2] [Task 4.1.2] [Task 5.1.2]
[Task 1.1.3] [Task 2.1.3] [Task 3.1.3] [Task 4.1.3] [Task 5.1.3]
... ... ... ... ...
```
### Why This Works
- **User-centric:** Organizes work around user goals, not engineering modules
- **Shared understanding:** Product, design, engineering all see the same journey
- **Prioritization clarity:** Top tasks = MVP, lower tasks = future iterations
- **Gap identification:** Missing steps or tasks become obvious
- **Release planning:** Draw horizontal "release lines" to define scope
### Anti-Patterns (What This Is NOT)
- **Not a Gantt chart:** This isn't project management—it's user journey visualization
- **Not a feature list:** Activities aren't features—they're user behaviors
- **Not static:** Story maps evolve as you learn more about users
### When to Use This
- Kicking off a new product or major feature
- Aligning stakeholders on user workflow
- Prioritizing backlog based on user needs
- Identifying MVP vs. future releases
- Onboarding new team members to the product vision
### When NOT to Use This
- For trivial features (don't map what you already understand)
- When user workflows are constantly changing (map stabilizes workflows)
- As a replacement for user stories (the map informs stories, doesn't replace them)
---
## Application
### Step 1: Define the Context
Use `template.md` for the full fill-in structure.
#### Segment
Who are you building for?
```markdown
### Segment:
- [Specify the target segment, e.g., "Small business owners using DIY accounting software"]
```
**Quality checks:**
- **Specific:** Not "users" but "enterprise IT admins" or "freelance designers"
---
#### Persona
Provide details about the persona within this segment (reference `skills/proto-persona/SKILL.md`).
```markdown
### Persona:
- [Describe the persona: demographics, behaviors, pains, goals]
```
**Example:**
- "Sarah, 35-year-old freelance graphic designer, manages 5-10 client projects at once, struggles with invoicing and payment tracking, wants to spend less time on admin and more time designing"
---
### Step 2: Define the Narrative
What is the user trying to accomplish? Frame this as a Jobs-to-be-Done statement (reference `skills/jobs-to-be-done/SKILL.md`).
```markdown
### Narrative:
- [Concise narrative of the persona's objective, e.g., "Complete a client project from kickoff to final payment"]
```
**Quality checks:**
- **Outcome-focused:** Not "use the product" but "deliver a client project on time and get paid"
- **One sentence:** If it takes more than one sentence, the scope may be too broad
---
### Step 3: Identify Activities (Backbone)
List 3-5 high-level activities the persona engages in to fulfill the narrative. These form the backbone of your map.
```markdown
### Activities:
1. [Activity 1, e.g., "Negotiate project scope and pricing"]
2. [Activity 2, e.g., "Execute design work"]
3. [Activity 3, e.g., "Deliver final assets to client"]
4. [Activity 4, e.g., "Send invoice and receive payment"]
5. [Activity 5, optional]
```
**Quality checks:**
- **Sequential:** Activities happen in order (left-to-right)
- **User actions:** Describe what the user *does*, not what the product *provides*
- **3-5 activities:** Too few = oversimplified, too many = overwhelming
---
### Step 4: Break Activities into Steps
For each activity, list 3-5 steps that detail how the activity is carried out.
```markdown
### Steps:
**For Activity 1: [Activity Name]**
- Step 1: [Detail step 1, e.g., "Review client brief"]
- Step 2: [Detail step 2, e.g., "Draft project proposal"]
- Step 3: [Detail step 3, e.g., "Negotiate timeline and budget"]
- Step 4: [Optional step 4]
- Step 5: [Optional step 5]
**For Activity 2: [Activity Name]**
- Step 1: [Detail step 1]
- Step 2: [Detail step 2]
...
```
**Quality checks:**
- **Actionable:** Each step is something the user does
- **Observable:** You could watch someone perform this step
- **Logical sequence:** Steps follow a natural order
---
### Step 5: Break Steps into Tasks
For each step, list 5-7 tasks that must be completed.
```markdown
### Tasks:
**For Activity 1, Step 1: [Step Name]**
- Task 1: [Detail task 1, e.g., "Read client brief document"]
- Task 2: [Detail task 2, e.g., "Identify key deliverables"]
- Task 3: [Detail task 3, e.g., "Note budget constraints"]
- Task 4: [Detail task 4, e.g., "Clarify timeline expectations"]
- Task 5: [Detail task 5, e.g., "List open questions for client"]
- Task 6: [Optional task 6]
- Task 7: [Optional task 7]
**For Activity 1, Step 2: [Step Name]**
- Task 1: [Detail task 1]
...
```
**Quality checks:**
- **Granular:** Tasks are small, specific actions
- **User-facing or behind-the-scenes:** Include both (e.g., "Send email" and "Receive confirmation")
- **Prioritizable:** You'll prioritize tasks vertically (top = essential, bottom = nice-to-have)
---
### Step 6: Prioritize Vertically
Arrange tasks top-to-bottom by priority:
- **Top rows:** MVP / Release 1 (must-have)
- **Middle rows:** Release 2 (important but not critical)
- **Bottom rows:** Future / Nice-to-have
Draw horizontal "release lines" to demarcate scope.
---
### Step 7: Identify Gaps and Opportunities
Review the map and ask:
- Are there missing steps or tasks?
- Are there pain points we're not addressing?
- Are there opportunities to delight users?
- Do all activities flow logically?
---
## Examples
See `examples/sample.md` for a full story map example.
---
## Common Pitfalls
### Pitfall 1: Activities Are Features, Not User Behaviors
**Symptom:** "Activity 1: Use the dashboard. Activity 2: Generate reports."
**Consequence:** You've mapped the product, not the user journey.
**Fix:** Reframe as user actions: "Activity 1: Monitor project progress. Activity 2: Summarize work for stakeholders."
---
### Pitfall 2: Too Many Activities
**Symptom:** 10+ activities across the backbone
**Consequence:** Map becomes overwhelming and loses focus.
**Fix:** Consolidate. If you have 10 activities, you're likely mixing activities with steps. Aim for 3-5 high-level activities.
---
### Pitfall 3: Tasks Are Too Vague
**Symptom:** "Task 1: Do the thing"
**Consequence:** Can't prioritize or estimate vague tasks.
**Fix:** Be specific: "Task 1: Enter client email address in the 'Bill To' field."
---
### Pitfall 4: Ignoring Vertical Prioritization
**Symptom:** All tasks at the same level—no MVP vs. future releases defined
**Consequence:** No clarity on what to build first.
**Fix:** Explicitly prioritize. Draw release lines. Force hard choices about what's MVP.
---
### Pitfall 5: Mapping in Isolation
**Symptom:** PM creates the map alone, then presents it to the team
**Consequence:** No shared ownership or understanding.
**Fix:** Map collaboratively. Run a story mapping workshop with product, design, and engineering.
---
## References
### Related Skills
- `skills/proto-persona/SKILL.md` — Defines the persona for the story map
- `skills/jobs-to-be-done/SKILL.md` — Informs the narrative and activities
- `skills/user-story/SKILL.md` — Tasks from the map become user stories
- `skills/problem-statement/SKILL.md` — Problem statement frames the narrative
### External Frameworks
- Jeff Patton, *User Story Mapping* (2014) — Origin of the story mapping technique
- Teresa Torres, *Continuous Discovery Habits* (2021) — Opportunity solution trees (complementary to story maps)
### Dean's Work
- User Story Mapping Prompt (adapted from Jeff Patton's methodology)
### Provenance
- Adapted from `prompts/user-story-mapping.md` in the `https://github.com/deanpeters/product-manager-prompts` repo.
---
**Skill type:** Component
**Suggested filename:** `user-story-mapping.md`
**Suggested placement:** `/skills/components/`
**Dependencies:** References `skills/proto-persona/SKILL.md`, `skills/jobs-to-be-done/SKILL.md`, `skills/user-story/SKILL.md`, `skills/problem-statement/SKILL.md`

View File

@@ -0,0 +1,77 @@
# User Story Mapping Example
## Example: Story Map for Freelance Invoicing Product
```markdown
## User Story Map: Freelance Invoicing
### Who
#### Segment:
- Freelance creative professionals (designers, writers, photographers)
#### Persona:
- Sarah, 35, freelance graphic designer
- Manages 5-10 clients at once
- Struggles with invoicing, payment tracking, and follow-ups
- Wants to spend less time on admin, more time designing
- Currently uses Excel + email, which is error-prone and time-consuming
### Backbone
#### Narrative:
- Complete a client project from kickoff to final payment without admin hassle
#### Activities:
1. Negotiate project scope and pricing
2. Execute design work
3. Deliver final assets
4. Send invoice and receive payment
5. Follow up on late payments
### Steps:
**For Activity 1: Negotiate project scope and pricing**
- Step 1: Review client brief
- Step 2: Draft project proposal
- Step 3: Negotiate timeline and budget
**For Activity 2: Execute design work**
- Step 1: Create initial concepts
- Step 2: Share concepts for feedback
- Step 3: Iterate based on feedback
- Step 4: Finalize design
**For Activity 3: Deliver final assets**
- Step 1: Export final files in client-requested formats
- Step 2: Upload files to shared folder or email
- Step 3: Confirm client receipt
**For Activity 4: Send invoice and receive payment**
- Step 1: Create invoice with project details
- Step 2: Send invoice to client
- Step 3: Track payment status
- Step 4: Confirm payment received
**For Activity 5: Follow up on late payments**
- Step 1: Identify overdue invoices
- Step 2: Send payment reminder
- Step 3: Escalate if still unpaid
### Tasks (Sample for Activity 4, Step 1: Create invoice):
**MVP (Release 1):**
- Task 1: Enter client name and contact info
- Task 2: Add line items (description, hours, rate)
- Task 3: Calculate total automatically
- Task 4: Preview invoice before sending
**Release 2:**
- Task 5: Add logo and custom branding
- Task 6: Save invoice templates for repeat clients
- Task 7: Auto-populate line items from project notes
**Future:**
- Task 8: Generate invoices from time tracking data
- Task 9: Multi-currency support
```

View File

@@ -0,0 +1,41 @@
# User Story Map Template
Use this template to create a complete user story map (segment, persona, backbone, steps, and tasks).
## Provenance
Adapted from `prompts/user-story-mapping.md` in the `https://github.com/deanpeters/product-manager-prompts` repo.
## Template
```markdown
## User Story Map Template
### Who
#### Segment:
- [Specify the target segment]
#### Persona:
- [Describe the persona and their key characteristics]
### Backbone
#### Narrative:
- [Insert the concise narrative of the persona's objective]
#### Activities:
1. [Describe Activity 1]
2. [Describe Activity 2]
3. [Continue as necessary for up to 5 activities]
#### Steps:
For [Activity 1]:
- Step 1: [Detail Step 1 for Activity 1]
- Step 2: [Detail Step 2 for Activity 1]
- Step 3: [Detail Step 3 for Activity 1]
#### Tasks:
For [Activity 1, Step 1]:
- Task 1: [Detail Task 1 for Step 1 of Activity 1]
- Task 2: [Detail Task 2 for Step 1 of Activity 1]
- Task 3: [Detail Task 3 for Step 1 of Activity 1]
```

View File

@@ -2,6 +2,7 @@
"server": { "server": {
"host": "localhost", "host": "localhost",
"allowLAN": true, "allowLAN": true,
"lanHost": "192.168.0.102",
"enableCommandAPI": false "enableCommandAPI": false
}, },
"projectDefaults": { "projectDefaults": {
@@ -12,7 +13,8 @@
}, },
"versionCollaboration": { "versionCollaboration": {
"remote": { "remote": {
"url": "https://gitea.lnh2e.com/wangmian/OneOS1.2.git" "url": "https://gitea.lnh2e.com/wangmian/OneOS1.2.git",
"defaultBranch": "main"
} }
}, },
"cloudPublishing": { "cloudPublishing": {

View File

@@ -1,67 +1,48 @@
{ {
"version": 1, "version": 1,
"updatedAt": "2026-07-20T05:34:45.927Z", "updatedAt": "2026-07-24T17:38:43.442Z",
"prototypes": [ "prototypes": [
{ {
"id": "folder-1783875936186-27raza", "id": "item-prototypes-autorodo-web",
"kind": "folder", "kind": "item",
"title": "旧ONEOS", "title": "autorodo web",
"children": [ "itemKey": "prototypes/autorodo-web"
{
"id": "item:prototypes:oneos-web-business",
"kind": "item",
"title": "业务管理",
"itemKey": "prototypes/oneos-web-business"
},
{
"id": "item:prototypes:oneos-web-data-analysis",
"kind": "item",
"title": "数据分析",
"itemKey": "prototypes/oneos-web-data-analysis"
},
{
"id": "item:prototypes:oneos-web-finance",
"kind": "item",
"title": "财务管理(合包)",
"itemKey": "prototypes/oneos-web-finance"
},
{
"id": "item:prototypes:oneos-web-help-center",
"kind": "item",
"title": "帮助中心",
"itemKey": "prototypes/oneos-web-help-center"
},
{
"id": "item:prototypes:oneos-web-lease-contract",
"kind": "item",
"title": "车辆租赁合同",
"itemKey": "prototypes/oneos-web-lease-contract"
},
{
"id": "item:prototypes:oneos-web-ledger-data",
"kind": "item",
"title": "台账数据",
"itemKey": "prototypes/oneos-web-ledger-data"
},
{
"id": "item:prototypes:oneos-web-ops",
"kind": "item",
"title": "运维管理",
"itemKey": "prototypes/oneos-web-ops"
},
{
"id": "item:prototypes:oneos-web-procurement",
"kind": "item",
"title": "采购管理",
"itemKey": "prototypes/oneos-web-procurement"
}
]
}, },
{ {
"id": "item:prototypes:oneos-prototype-nav", "id": "item-prototypes-oneos-v2-h5-vehicle-assets",
"kind": "item", "kind": "item",
"title": "原型导航", "title": "oneos v2 h5 vehicle assets",
"itemKey": "prototypes/oneos-prototype-nav" "itemKey": "prototypes/oneos-v2-h5-vehicle-assets"
},
{
"id": "item-prototypes-oneos-v2-form-kit",
"kind": "item",
"title": "oneos v2 form kit",
"itemKey": "prototypes/oneos-v2-form-kit"
},
{
"id": "item:prototypes:payment-qr-code",
"kind": "item",
"title": "羚牛收款二维码",
"itemKey": "prototypes/payment-qr-code"
},
{
"id": "item:prototypes:lease-contract-redesign",
"kind": "item",
"title": "lease-contract-redesign",
"itemKey": "prototypes/lease-contract-redesign"
},
{
"id": "item:prototypes:vehicle-inspection",
"kind": "item",
"title": "验车入库",
"itemKey": "prototypes/vehicle-inspection"
},
{
"id": "item:prototypes:vehicle-purchase-contract",
"kind": "item",
"title": "车辆采购合同",
"itemKey": "prototypes/vehicle-purchase-contract"
}, },
{ {
"id": "folder-1782874576229-r8atbu", "id": "folder-1782874576229-r8atbu",
@@ -69,10 +50,28 @@
"title": "OneOS", "title": "OneOS",
"children": [ "children": [
{ {
"id": "item:prototypes:oneos-web-workbench", "id": "item:prototypes:oneos-prototype-demo",
"kind": "item",
"title": "原型演示",
"itemKey": "prototypes/oneos-prototype-demo"
},
{
"id": "item:prototypes:oneos-v2",
"kind": "item",
"title": "OneOS V2 全局规范示范",
"itemKey": "prototypes/oneos-v2"
},
{
"id": "item:prototypes:oneos-web-workbench-new",
"kind": "item", "kind": "item",
"title": "工作台", "title": "工作台",
"itemKey": "prototypes/oneos-web-workbench" "itemKey": "prototypes/oneos-web-workbench-new"
},
{
"id": "item:prototypes:message-center",
"kind": "item",
"title": "消息中心",
"itemKey": "prototypes/message-center"
}, },
{ {
"id": "folder-oneos-approval", "id": "folder-oneos-approval",
@@ -118,6 +117,19 @@
} }
] ]
}, },
{
"id": "folder-oneos-vehicle-ops",
"kind": "folder",
"title": "车辆运维",
"children": [
{
"id": "item:prototypes:vehicle-fault-handling",
"kind": "item",
"title": "故障处置",
"itemKey": "prototypes/vehicle-fault-handling"
}
]
},
{ {
"id": "folder-1782874624657-4c8hzv", "id": "folder-1782874624657-4c8hzv",
"kind": "folder", "kind": "folder",
@@ -141,6 +153,12 @@
"title": "租赁合同", "title": "租赁合同",
"itemKey": "prototypes/lease-contract-management" "itemKey": "prototypes/lease-contract-management"
}, },
{
"id": "item:prototypes:self-operated-contract",
"kind": "item",
"title": "自营合同",
"itemKey": "prototypes/self-operated-contract"
},
{ {
"id": "item:prototypes:insurance-procurement", "id": "item:prototypes:insurance-procurement",
"kind": "item", "kind": "item",
@@ -173,12 +191,6 @@
"title": "站点信息", "title": "站点信息",
"itemKey": "prototypes/oneos-web-h2-station-site" "itemKey": "prototypes/oneos-web-h2-station-site"
}, },
{
"id": "item:prototypes:oneos-h5-h2-order",
"kind": "item",
"title": "加氢记录H5",
"itemKey": "prototypes/oneos-h5-h2-order"
},
{ {
"id": "item:prototypes:oneos-web-h2-station", "id": "item:prototypes:oneos-web-h2-station",
"kind": "item", "kind": "item",
@@ -192,9 +204,9 @@
"itemKey": "prototypes/oneos-web-h2-station-weekly" "itemKey": "prototypes/oneos-web-h2-station-weekly"
}, },
{ {
"id": "item-prototypes-oneos-web-h2-station-analysis", "id": "item:prototypes:oneos-web-h2-station-analysis",
"kind": "item", "kind": "item",
"title": "oneos web h2 station analysis", "title": "加氢站分析",
"itemKey": "prototypes/oneos-web-h2-station-analysis" "itemKey": "prototypes/oneos-web-h2-station-analysis"
} }
] ]
@@ -296,6 +308,12 @@
"kind": "item", "kind": "item",
"title": "任务工单", "title": "任务工单",
"itemKey": "prototypes/task-work-order" "itemKey": "prototypes/task-work-order"
},
{
"id": "item:prototypes:self-operated-dispatch-task",
"kind": "item",
"title": "调度任务",
"itemKey": "prototypes/self-operated-dispatch-task"
} }
] ]
}, },
@@ -303,22 +321,390 @@
"id": "folder-1784341576489-spa7ms", "id": "folder-1784341576489-spa7ms",
"kind": "folder", "kind": "folder",
"title": "审批中心", "title": "审批中心",
"children": [ "children": []
{
"id": "item:prototypes:oneos-web-approval",
"kind": "item",
"title": "审批中心",
"itemKey": "prototypes/oneos-web-approval"
}
]
}, },
{ {
"id": "item:prototypes:lease-business-line-overview", "id": "item:prototypes:lease-business-line-overview",
"kind": "item", "kind": "item",
"title": "业务条线说明", "title": "业务条线说明",
"itemKey": "prototypes/lease-business-line-overview" "itemKey": "prototypes/lease-business-line-overview"
},
{
"id": "item:prototypes:autorodo-web",
"kind": "item",
"title": "AutoRDO 需求清洗工作台",
"itemKey": "prototypes/autorodo-web"
},
{
"id": "item:prototypes:yunxiao-pipeline-handbook",
"kind": "item",
"title": "云效生产线手册",
"itemKey": "prototypes/yunxiao-pipeline-handbook"
},
{
"id": "folder-ds-v2-legacy-snapshots",
"kind": "folder",
"title": "设计规范对照·旧版",
"children": [
{
"id": "item:prototypes:business-dept-ledger-legacy",
"kind": "item",
"title": "【旧版】项目盈亏情况",
"itemKey": "prototypes/business-dept-ledger-legacy"
},
{
"id": "item:prototypes:contract-template-management-legacy",
"kind": "item",
"title": "【旧版】合同模板管理",
"itemKey": "prototypes/contract-template-management-legacy"
},
{
"id": "item:prototypes:customer-management-legacy",
"kind": "item",
"title": "【旧版】客户管理",
"itemKey": "prototypes/customer-management-legacy"
},
{
"id": "item:prototypes:customer-payment-collection-legacy",
"kind": "item",
"title": "【旧版】客户回款情况",
"itemKey": "prototypes/customer-payment-collection-legacy"
},
{
"id": "item:prototypes:insurance-procurement-legacy",
"kind": "item",
"title": "【旧版】保险采购",
"itemKey": "prototypes/insurance-procurement-legacy"
},
{
"id": "item:prototypes:lease-business-detail-legacy",
"kind": "item",
"title": "【旧版】租赁业务明细",
"itemKey": "prototypes/lease-business-detail-legacy"
},
{
"id": "item:prototypes:lease-business-ledger-legacy",
"kind": "item",
"title": "【旧版】租赁业务台账",
"itemKey": "prototypes/lease-business-ledger-legacy"
},
{
"id": "item:prototypes:lease-business-line-overview-legacy",
"kind": "item",
"title": "【旧版】业务条线说明",
"itemKey": "prototypes/lease-business-line-overview-legacy"
},
{
"id": "item:prototypes:lease-contract-management-legacy",
"kind": "item",
"title": "【旧版】租赁合同",
"itemKey": "prototypes/lease-contract-management-legacy"
},
{
"id": "item:prototypes:message-center-legacy",
"kind": "item",
"title": "【旧版】消息中心",
"itemKey": "prototypes/message-center-legacy"
},
{
"id": "item:prototypes:oneos-h5-h2-order-legacy",
"kind": "item",
"title": "【旧版】加氢记录H5",
"itemKey": "prototypes/oneos-h5-h2-order-legacy"
},
{
"id": "item:prototypes:oneos-h5-vehicle-assets-legacy",
"kind": "item",
"title": "【旧版】车辆资产H5",
"itemKey": "prototypes/oneos-h5-vehicle-assets-legacy"
},
{
"id": "item:prototypes:oneos-prototype-demo-legacy",
"kind": "item",
"title": "【旧版】原型演示",
"itemKey": "prototypes/oneos-prototype-demo-legacy"
},
{
"id": "item:prototypes:oneos-web-approval-cc-legacy",
"kind": "item",
"title": "【旧版】我的抄送",
"itemKey": "prototypes/oneos-web-approval-cc-legacy"
},
{
"id": "item:prototypes:oneos-web-approval-done-legacy",
"kind": "item",
"title": "【旧版】我的已办",
"itemKey": "prototypes/oneos-web-approval-done-legacy"
},
{
"id": "item:prototypes:oneos-web-approval-initiated-legacy",
"kind": "item",
"title": "【旧版】我发起的",
"itemKey": "prototypes/oneos-web-approval-initiated-legacy"
},
{
"id": "item:prototypes:oneos-web-approval-todo-legacy",
"kind": "item",
"title": "【旧版】我的待办",
"itemKey": "prototypes/oneos-web-approval-todo-legacy"
},
{
"id": "item:prototypes:oneos-web-business-legacy",
"kind": "item",
"title": "【旧版】业务管理",
"itemKey": "prototypes/oneos-web-business-legacy"
},
{
"id": "item:prototypes:oneos-web-data-analysis-legacy",
"kind": "item",
"title": "【旧版】数据分析",
"itemKey": "prototypes/oneos-web-data-analysis-legacy"
},
{
"id": "item:prototypes:oneos-web-finance-legacy",
"kind": "item",
"title": "【旧版】财务管理(合包)",
"itemKey": "prototypes/oneos-web-finance-legacy"
},
{
"id": "item:prototypes:oneos-web-h2-station-legacy",
"kind": "item",
"title": "【旧版】加氢记录",
"itemKey": "prototypes/oneos-web-h2-station-legacy"
},
{
"id": "item:prototypes:oneos-web-h2-station-analysis-legacy",
"kind": "item",
"title": "【旧版】加氢站分析",
"itemKey": "prototypes/oneos-web-h2-station-analysis-legacy"
},
{
"id": "item:prototypes:oneos-web-h2-station-site-legacy",
"kind": "item",
"title": "【旧版】站点信息",
"itemKey": "prototypes/oneos-web-h2-station-site-legacy"
},
{
"id": "item:prototypes:oneos-web-h2-station-stats-legacy",
"kind": "item",
"title": "【旧版】加氢站数量统计",
"itemKey": "prototypes/oneos-web-h2-station-stats-legacy"
},
{
"id": "item:prototypes:oneos-web-h2-station-weekly-legacy",
"kind": "item",
"title": "【旧版】站点周报统计",
"itemKey": "prototypes/oneos-web-h2-station-weekly-legacy"
},
{
"id": "item:prototypes:oneos-web-help-center-legacy",
"kind": "item",
"title": "【旧版】帮助中心",
"itemKey": "prototypes/oneos-web-help-center-legacy"
},
{
"id": "item:prototypes:oneos-web-lease-contract-legacy",
"kind": "item",
"title": "【旧版】车辆租赁合同",
"itemKey": "prototypes/oneos-web-lease-contract-legacy"
},
{
"id": "item:prototypes:oneos-web-ledger-data-legacy",
"kind": "item",
"title": "【旧版】台账数据",
"itemKey": "prototypes/oneos-web-ledger-data-legacy"
},
{
"id": "item:prototypes:oneos-web-ops-legacy",
"kind": "item",
"title": "【旧版】运维管理",
"itemKey": "prototypes/oneos-web-ops-legacy"
},
{
"id": "item:prototypes:oneos-web-procurement-legacy",
"kind": "item",
"title": "【旧版】采购管理",
"itemKey": "prototypes/oneos-web-procurement-legacy"
},
{
"id": "item:prototypes:oneos-web-workbench-new-legacy",
"kind": "item",
"title": "【旧版】工作台",
"itemKey": "prototypes/oneos-web-workbench-new-legacy"
},
{
"id": "item:prototypes:payment-records-legacy",
"kind": "item",
"title": "【旧版】收款记录",
"itemKey": "prototypes/payment-records-legacy"
},
{
"id": "item:prototypes:self-operated-business-ledger-legacy",
"kind": "item",
"title": "【旧版】物流业务明细",
"itemKey": "prototypes/self-operated-business-ledger-legacy"
},
{
"id": "item:prototypes:self-operated-contract-legacy",
"kind": "item",
"title": "【旧版】自营合同",
"itemKey": "prototypes/self-operated-contract-legacy"
},
{
"id": "item:prototypes:self-operated-dispatch-task-legacy",
"kind": "item",
"title": "【旧版】调度任务",
"itemKey": "prototypes/self-operated-dispatch-task-legacy"
},
{
"id": "item:prototypes:supplier-management-legacy",
"kind": "item",
"title": "【旧版】供应商管理",
"itemKey": "prototypes/supplier-management-legacy"
},
{
"id": "item:prototypes:task-work-order-legacy",
"kind": "item",
"title": "【旧版】任务工单",
"itemKey": "prototypes/task-work-order-legacy"
},
{
"id": "item:prototypes:vehicle-fault-handling-legacy",
"kind": "item",
"title": "【旧版】故障处置",
"itemKey": "prototypes/vehicle-fault-handling-legacy"
},
{
"id": "item:prototypes:vehicle-h2-fee-ledger-legacy",
"kind": "item",
"title": "【旧版】车辆氢费明细",
"itemKey": "prototypes/vehicle-h2-fee-ledger-legacy"
},
{
"id": "item:prototypes:vehicle-inspection-legacy",
"kind": "item",
"title": "【旧版】vehicle inspection",
"itemKey": "prototypes/vehicle-inspection-legacy"
},
{
"id": "item:prototypes:vehicle-maintenance-ledger-legacy",
"kind": "item",
"title": "【旧版】维修保养台账",
"itemKey": "prototypes/vehicle-maintenance-ledger-legacy"
},
{
"id": "item:prototypes:vehicle-management-legacy",
"kind": "item",
"title": "【旧版】车辆资产",
"itemKey": "prototypes/vehicle-management-legacy"
},
{
"id": "item:prototypes:vehicle-pickup-receivable-legacy",
"kind": "item",
"title": "【旧版】提车应收款",
"itemKey": "prototypes/vehicle-pickup-receivable-legacy"
},
{
"id": "item:prototypes:vehicle-purchase-contract-legacy",
"kind": "item",
"title": "【旧版】vehicle purchase contract",
"itemKey": "prototypes/vehicle-purchase-contract-legacy"
},
{
"id": "item:prototypes:vehicle-return-settlement-legacy",
"kind": "item",
"title": "【旧版】还车应结款",
"itemKey": "prototypes/vehicle-return-settlement-legacy"
},
{
"id": "item:prototypes:yunxiao-pipeline-handbook-legacy",
"kind": "item",
"title": "【旧版】云效生产线手册",
"itemKey": "prototypes/yunxiao-pipeline-handbook-legacy"
}
]
} }
] ]
},
{
"id": "folder-1784563868850-xi0guc",
"kind": "folder",
"title": "小羚羚",
"children": [
{
"id": "item:prototypes:oneos-h5-vehicle-assets",
"kind": "item",
"title": "车辆资产H5",
"itemKey": "prototypes/oneos-h5-vehicle-assets"
},
{
"id": "item:prototypes:oneos-h5-h2-order",
"kind": "item",
"title": "加氢记录H5",
"itemKey": "prototypes/oneos-h5-h2-order"
}
]
},
{
"id": "folder-1783875936186-27raza",
"kind": "folder",
"title": "旧ONEOS",
"children": [
{
"id": "item:prototypes:oneos-web-business",
"kind": "item",
"title": "业务管理",
"itemKey": "prototypes/oneos-web-business"
},
{
"id": "item:prototypes:oneos-web-data-analysis",
"kind": "item",
"title": "数据分析",
"itemKey": "prototypes/oneos-web-data-analysis"
},
{
"id": "item:prototypes:oneos-web-finance",
"kind": "item",
"title": "财务管理(合包)",
"itemKey": "prototypes/oneos-web-finance"
},
{
"id": "item:prototypes:oneos-web-help-center",
"kind": "item",
"title": "帮助中心",
"itemKey": "prototypes/oneos-web-help-center"
},
{
"id": "item:prototypes:oneos-web-lease-contract",
"kind": "item",
"title": "车辆租赁合同",
"itemKey": "prototypes/oneos-web-lease-contract"
},
{
"id": "item:prototypes:oneos-web-ledger-data",
"kind": "item",
"title": "台账数据",
"itemKey": "prototypes/oneos-web-ledger-data"
},
{
"id": "item:prototypes:oneos-web-ops",
"kind": "item",
"title": "运维管理",
"itemKey": "prototypes/oneos-web-ops"
},
{
"id": "item:prototypes:oneos-web-procurement",
"kind": "item",
"title": "采购管理",
"itemKey": "prototypes/oneos-web-procurement"
}
]
},
{
"id": "item:prototypes:oneos-prototype-nav",
"kind": "item",
"title": "原型导航",
"itemKey": "prototypes/oneos-prototype-nav"
} }
], ],
"docs": [], "docs": [],
@@ -1105,4 +1491,4 @@
"templates": [], "templates": [],
"components": [], "components": [],
"canvas": [] "canvas": []
} }

View File

@@ -0,0 +1,83 @@
---
name: AutoRDO
description: >-
AutoRDO (Requirement Description Optimization): cleans fragmented chat logs,
voice transcripts, oral notes, and feedback ledgers into written title and description;
auto-detects 类型/优先级/标签/提交部门/提交人 from content; maps OneOS modules via oneos-domain.md;
splits multi-line into multiple results; if any 待确认 exists, MUST switch to Plan mode
for choice-based confirmation. Does not change Yunxiao status or create tasks.
Pair with YunxiaoPMapp for cloud write; never load yunxiao-requirement-lifecycle.
---
# AutoRDO
**Requirement Description Optimization**(需求描述优化)。
将碎片化、通俗化文字(聊天/录音/反馈台账)在**保留原意**前提下拆解为**标题、描述**,并**自动识别**类型、优先级、标签、提交部门、提交人,供入库写入云效需求。
多行/多条独立诉求 → **自动拆成多份**转译结果。
**强制**:清洗结果中**只要存在任意「待确认」**Agent **必须立刻** `SwitchMode`**plan**,逐条用选择题消解;**无需**用户再说「确认待确认」。无待确认则可直接交定稿。
## 边界(强制)
| 做 | 不做 |
|---|---|
| 提炼标题与书面描述;自动识别类型/优先级/标签/提交部门/提交人 | 改云效状态 / 建任务 / **直接**打云效标签 |
| 多行/多条 → 多份转译结果 | 写成完整 AutoPRD / 臆造业务结论 |
| 有待确认 → 强制 Plan 逐条确认 | 停在初稿等口令;把猜测写入定稿 |
| 去除描述**结尾句号** | 加载 `yunxiao-requirement-lifecycle` |
云效建单与打标由 **`$YunxiaoPMapp`** 负责;本 Skill 只出清洗稿与**推荐元数据**。
## 何时使用
- 口令含 `AutoRDO` / `清洗聊天` / `录音整理` / `原始诉求`
- 粘贴反馈台账(含部门/优先级/模块列)或口述碎片
- YunxiaoPMapp「记录需求」前必须先跑本 Skill材料为碎片/台账时)
## 输入
- 聊天、会议速记、口述、录音转写
- **多行/台账**含反馈人、所属部门、业务模块、优先级、PC或移动端等列时优先采信列值
- 确认阶段补充文字
## 处理规则
**强制前置**ONE-OS 材料先 Read [references/oneos-domain.md](references/oneos-domain.md),元数据规则见 [references/meta-fields.md](references/meta-fields.md),再按 [references/rules.md](references/rules.md) 执行。
1. **多条拆解** → 每条独立成稿
2. **OneOS 对齐** → 模块/部门标准名
3. **元数据识别** → 类型、优先级、标签、提交部门、提交人(显式列 > 正文标记 > 语义推断;不确定 → 待确认)
4. **标题 + 描述转译** → 去口语、去结尾句号
5. **有待确认 → 强制 Plan** → 见 [references/confirm-pending.md](references/confirm-pending.md)
## 输出
```markdown
## 原始诉求AutoRDO
**标题**<清晰标题>
**类型**:【新增】|【优化】
**优先级**P1-高|P2-中|P3-低
**标签**<标准模块>[, PC端|小程序]
**提交部门**<标准部门名或空>
**提交人**<姓名或空>
**描述**
<转译正文;无结尾句号>
反馈:<有则附日期/禅道/状态/端>
待确认:
-
```
多条时先写「共 N 条」,再 `### 1``### N`
交 YunxiaoPMapp 示例:`记录需求:标题=…;类型=…;优先级=…;标签=…;提交部门=…;提交人=…;描述=…`
## 口令
```text
AutoRDO<粘贴聊天或台账行>
AutoRDO录音转写如下 …
按下列补充消解待确认:
<补充说明>
```

View File

@@ -0,0 +1,4 @@
interface:
display_name: "AutoRDO"
short_description: "清洗诉求并识别类型优先级标签部门提交人"
default_prompt: "按 AutoRDO 清洗:先读 oneos-domain.md 与 meta-fields.md多行拆多条出标题+描述+类型/优先级/标签/提交部门/提交人。有待确认则同轮强制切 Plan 用选择题消解;不改云效、不直接打标、不贴词典全文。"

View File

@@ -0,0 +1,126 @@
# AutoRDO · 待确认逐条 Plan 确认
## 目标
清洗稿中的「待确认」经产品经理**逐条人工确认**后,回填进标题/描述,得到可交 YunxiaoPMapp 的定稿。
确认过程**优先选择题**;选项用 [oneos-domain.md](oneos-domain.md) 辅助生成;也支持用补充说明/需求描述文字直接消解待确认点。
## 何时进入(强制)
```text
清洗初稿产出后:
若任一需求含「待确认」→ 同轮必须 SwitchMode → plan
若全部无待确认 → 不必进 Plan初稿即定稿
```
- **触发条件只有一条**:存在待确认(单条或多条中任意一点)
- **禁止**要求用户再说「确认待确认」「开始确认」才进 Plan
- 用户在 Plan 中可用选择题作答,也可粘贴补充说明消解
**不进 Plan 的唯一情况**:清洗结果中没有任何「待确认」条目。
## Plan 门禁(强制)
1. 清洗初稿写出后(可先展示初稿摘要),**立刻** `SwitchMode`**plan**,说明:存在待确认,须逐条确认后再回填定稿;本阶段仍**不写云效**
2. Plan 列出:待确认的**需求条号**、每条下的待确认点清单、推荐确认方式(选择题 / 文字补充)
3. **用户确认 / 批准 Plan / 「执行」之前**:禁止把未确认内容写进定稿描述
4. 批准后:按条推进确认 → 回填 → 输出定稿
## 逐条确认顺序
```text
需求 1 的待确认点 1 → 点 2 → … → 需求 1 定稿片段
需求 2 的待确认点 1 → …
全部完成后输出「已确认定稿」全集
```
- **一次只推进一个待确认点**(或同一点下的一组互斥选项),避免一屏堆十几个问题
- 多条需求时Plan 清单可注明建议从第 1 条起;用户可指定跳过或改序
- 某条无「待确认」→ 跳过,保留初稿即可
## 确认方式(优先选择)
每个待确认点按下列优先级出题:
| 优先级 | 方式 | 适用 |
|---|---|---|
| 1 | **选择题**25 个互斥选项 + 可选「其他/我补充」) | 模块归属、部门名称、类型/优先级、是否/范围、枚举字段、拆条边界等 |
| 2 | **多选** | 明确可多选的范围如适用端PC+H5 |
| 3 | **文字补充** | 无法枚举、需自由描述字段清单/规则细节时 |
### 选项如何用 OneOS 词典生成
先 Read `oneos-domain.md`,再出选项:
- **模块名不清**:候选 = 词典中相关条线的标准模块名(如还车应结款 / 违章管理 / 还车管理),勿自造模块
- **部门/角色口语**:候选 = 第 1 节标准名(业管→业务管理组,安全小组→安全部 等)+「保持单据原文分区名」
- **跨条线联动**:选项写清主责模块 vs 联动对象;标题只挂主责,联动写描述
- **故事点细节**:仅当材料或用户补充已暗示时,才把词典闭环中的合理分支列为选项;**禁止**把未提及的故事点细节默认选中
每题结构建议:
```text
【需求 n · 待确认 k】<待确认原文>
依据词典,请选择:
A. …
B. …
C. …
D. 其他(请补充一句)
也可用一段需求描述直接回答本点
```
## 用需求描述补充
用户可用以下任一方式消解待确认,**不必**每题都点选:
- 粘贴一段补充说明 / 功能规则 / 字段清单
- 回复「按下列描述确认:…」
- 对某一待确认点直接写答案句
Agent 须:
1. 将补充文字**映射**到对应待确认点(可一次消解多点)
2. 写入该条**描述**(书面化、去结尾句号),从「待确认」列表**移除已消解项**
3. 补充仍含糊的部分 → 保留或新开「待确认」,继续选择题
4. **不**把补充里未说的内容脑补进去
## 回填定稿规则
确认完成后,对该条输出「已确认」版本:
```markdown
### n已确认
## 原始诉求AutoRDO
**标题**:…
**描述**
<初稿 + 已确认信息合并;无结尾句号>
待确认:
- (无则写「无」或省略本段)
```
- 标题若因模块/动作确认而需微调,可改,并在确认回合说明改了什么
- 未确认点**不得**假装已确认;可标「本条暂缓,待确认仍保留」
- 全部条完成后,给总览:已确认条数 / 仍含待确认条数
## 口令
```text
AutoRDO<材料> → 有待确认则自动进 Plan
按下列补充消解待确认:
<粘贴补充说明>
第 6 条待确认选 A第 7 条补充:字段非必填,计入应补汇总
```
(「确认待确认」等口令**不再作为**进 Plan 的前置条件;有待确认即强制进。)
## 不做
- 确认阶段仍不改云效、不建任务
- 不把 `oneos-domain.md` 全文贴进定稿
- 不跳过 Plan 直接把「猜的答案」写进描述
- 不等用户额外口令才进 Plan有待确认必须进

View File

@@ -0,0 +1,96 @@
# AutoRDO · 元数据自动识别
从粘贴内容(台账表格行、聊天、口述)自动识别下列字段,写入每条原始诉求输出;**不**直接改云效打标(打标由 YunxiaoPMapp 执行)。
## 输出字段
| 字段 | 说明 | 无依据时 |
|---|---|---|
| **类型** | `【新增】` / `【优化】`(与云效标题前缀一致) | 默认 `【优化】`,并列入待确认 |
| **优先级** | `P1-高` / `P2-中` / `P3-低` | 默认 `P2-中`,高不确定则待确认 |
| **标签** | 主模块标签(对齐 `oneos-domain.md` 标准模块名);可附端标签 `PC端` / `小程序` | 仅模块不确定则待确认 |
| **提交部门** | 映射到词典标准部门名 | 材料无部门且无法推断 → 待确认或空 |
| **提交人** | 反馈人/用户姓名 | 材料无人名 → 空(不臆造) |
## 识别优先级
```text
1. 显式列/字段反馈台账优先级、所属部门、反馈方、业务模块、PC或移动端…
2. 正文中的明确标记P1、【优化】、@某人、部门署名)
3. 语义推断(用词 + oneos-domain 模块/部门)
4. 仍不确定 → 待确认(选择题),禁止假装已确认
```
## 类型(【新增】/【优化】)
| 信号 | 类型 |
|---|---|
| 新增、增加、支持、允许、增加列/字段/入口、批量导入(首次能力) | 【新增】 |
| 优化、调整、修改、放开、更清晰、重构、移动至、改由、精确到、兼容 | 【优化】 |
| 台账/口令已写 `【新增】`/`【优化】` | 以显式为准 |
| 同时含新增与优化语义 | 以**主诉求**定类型;次要点写在描述 |
标题可带类型前缀供入库:`【优化】交车管理:…`;若用户只要裸标题,类型仍单独输出字段。
## 优先级
| 信号 | 优先级 |
|---|---|
| 列值 `P1-高` / `P1` / 紧急、阻塞、无法办理、P1 | `P1-高` |
| 列值 `P2-中` / `P2` | `P2-中` |
| 列值 `P3-低` / `P3` / 文案、置灰、体验微调 | `P3-低` |
| 无信号 | 默认 `P2-中` |
## 标签
1. **主标签** = 归属标准模块名(`oneos-domain.md`),如 `还车应结款``违章管理``交车管理`
2. 台账「业务模块」列优先;口语映射到标准名(验车管理→验车入库,调拨管理→车辆调拨)
3. **端标签**(可选,可多选):材料含 `PC端`/`小程序`/`PC及小程序` 时写入
4. 「其他」「全局优化」「小程序审批中心」等非模块名:主标签用最贴近模块或 `系统全局`;勿发明云效不存在的随意标签名
5. 输出格式:逗号分隔,如 `还车应结款, PC端`
## 提交部门
| 材料常见写法 | 标准输出 |
|---|---|
| 业务管理部、业管、业务管理 | 业务管理组 |
| 运维部、运维 | 运维部 |
| 数智中心、数智、信息化 | 数智部 |
| 安全部、安全 | 安全部 |
| 财务部、财务 | 财务部 |
| 法务部、法务 | 法务部 |
| 采购部/采购组 | 按词典区分输出 |
台账「所属部门」列优先;聊天中「我们运维…」可推断,低置信度则待确认。
## 提交人
- 台账「反馈方/用户」「反馈人」列 → 原样作为提交人
- 聊天 @姓名、署名「张三:」→ 取该名
- 多人联合反馈 → 取主反馈人(首列/首个署名);其余可写描述附注
- **禁止**用当前对话用户名冒充提交人(除非材料写明)
## 与描述附注的关系
- **结构化字段**(类型/优先级/标签/提交部门/提交人)单独成行,供 YunxiaoPMapp 建单口令复用
- 禅道编号、处理状态、反馈日期等 → 可放描述末行「反馈:…」附注,不升格为强制字段
## 输出模板(每条)
```markdown
## 原始诉求AutoRDO
**标题**<清晰标题;可选带【新增】/【优化】前缀>
**类型**:【新增】|【优化】
**优先级**P1-高|P2-中|P3-低
**标签**<模块>[, PC端|小程序]
**提交部门**<标准部门名或空>
**提交人**<姓名或空>
**描述**
<转译正文;无结尾句号>
反馈:<日期 · 原文部门 · 状态 · 禅道号 · 端 …>(有则写)
待确认:
-
```

View File

@@ -0,0 +1,399 @@
# ONE-OS 业务领域词典(供 AutoRDO 对齐)
> 来源:业务条线说明原型 `lease-business-line-overview`
> 用途:清洗标题/描述时,优先用下列**标准模块名、部门名、闭环表述**对齐,避免口语臆造模块或错挂条线。
> 系统定位1 套系统 · 5 大业务条线闭环 · 3 大数据底座 · 演进方向为业财一体
> **强制**:本文件只用于理解与用词对齐;**禁止**把本词典全文贴进云效描述或 AutoRDO 输出稿。
---
## 0. 系统总览
| 维度 | 口径 |
|---|---|
| 平台名 | ONE-OS亦写作 OneOS |
| 五大业务条线 | 租赁 · 能源 · 运维 · 安全 · 物流 |
| 三大数据底座 | 车辆资产运营情况 · 各业务条线盈亏情况 · 里程调度情况 |
| 现阶段 | 业务驱动 · 财务手工维护(收款/付款/核销多人工) |
| 演进方向 | 业财闭环一体化(打通财务 YS「收款记录」「付款记录」与业务台账双向回写 |
**标题提炼提示**:口述涉及合同/台账/交还车/氢费/证照/调度时,先归入对应条线再落模块名;跨条线联动(如还车应结款联动违章事故)在描述中写明联动对象,标题以主责模块为准。
---
## 1. 业务部门 / 角色词典(标准用词)
清洗时统一下列名称;同义口语请映射到标准名。
| 标准名称 | 常见口语/别称 | 主要出现条线 |
|---|---|---|
| 业务管理组 | 业管、业务管理 | 租赁、运维、安全、物流 |
| 业务管理组-能源部 | 能源组、业管能源、业务管理部-能源组 | 能源、租赁还车 |
| 业务服务组 | 业务服务 | 物流 |
| 业务员 | 业务 | 租赁 |
| 调度岗 | 调度 | 物流 |
| 法务部 | 法务 | 租赁、运维采购合同 |
| 财务部 | 财务 | 租赁评级、能源账户、运维付款/维保、安全违章事故、物流台账 |
| 安全部 | 安全 | 租赁评级、证照、安全条线 |
| 运维部 | 运维、区域操作员 | 运维全链路、交还车、租赁提车后交车 |
| 采购部 | 采购 | 能源加氢站、运维采购合同/验车 |
| 采购组 | 采购组 | 供应商管理(能源/运维) |
| 数智部 | 数智、信息化 | 合同模板电子化、能源扩展 |
| 董事长 | 老板、总 | 非标合同、资产出售过户报废确认 |
| 司机 | 提车司机、内部司机 | 交车培训、故障、安全培训 |
| 加氢站 / 签约加氢站 | 站点、站方 | 能源 |
**组织边界提示**
- 「采购组」侧重供应商主数据;「采购部」侧重站点管理与采购/三方租赁合同。
- 「业务管理组」与「业务管理组-能源部」勿混用;氢费、加氢对账默认能源部。
- 物流调度明确:**非 TMS**,不做配载与承运商调度。
---
## 2. 功能模块总表(按条线)
### 2.1 租赁业务条线6 模块 · 全链路闭环)
**条线闭环**:客户评级决定是否可签 → 标准模板支撑签约 → 租赁合同进入履约 → 提车应收对齐后交车 → 台账承接租期账单 → 还车应结款会签归档。
| 步 | 模块名 | 一句话定位 | 责任部门 |
|---|---|---|---|
| 1 | 客户管理 | 准入评级 · 决定能否签约、走哪条流程 | 业务管理组、法务部、财务部、安全部 |
| 2 | 标准合同管理 | 模板配置 · 支撑电子合同一键发起 | 法务部、数智部 |
| 3 | 租赁合同 | 签约发起 · 标准 / 非标 / 禁止三条路径 | 业务员、法务部 |
| 4 | 提车应收款 | 应收生成 · 实收对齐 · 触发交车 | 业务员、法务部、业务管理组、运维部 |
| 5 | 租赁业务台账 | 交车后账单 · 周期收费与实收延续 | 运维部、业务员、业务管理组 |
| 6 | 还车应结款 | 还车结算 · 多部门会签 · 归档闭环 | 业务管理组、安全部、运维部、业务管理组-能源部 |
**关键结果标签(客户管理)**:可标准签约 · 可签·走非标 · 禁止签约·高风险
---
### 2.2 能源业务条线6 模块 · 业财闭环)
**条线闭环**:供应商主数据支撑站点绑定 → 签约站账号与订单主动上报 → 非签约站氢费补录对账 → 客户对账单关联收款 → 加氢记录标记已付款 → 成熟后向采购端与司机端延伸。
| 步 | 模块名 | 一句话定位 | 责任部门 |
|---|---|---|---|
| 1 | 供应商管理 | 加氢/充电站供应商 · 站点绑定与业财直连 | 采购组、财务部 |
| 2 | 加氢站管理 | 签约站 / 非签约站 · 账号、余额与价格 | 采购部、加氢站 |
| 3 | 加氢订单 | 主动上报 · PLC 自动采集 · 预约接单 | 签约加氢站、业务管理组-能源部 |
| 4 | 车辆氢费明细 | 非签约站补录 · 对账归档 · 余额关联 | 业务管理组-能源部 |
| 5 | 氢费账户 | 客户预付款 · 对账单 · 业财收款闭环 | 业务管理组-能源部、财务部 |
| 6 | 扩展规划 | 上游采购 · 下游司机服务 | 采购部、业务管理组-能源部、数智部 |
---
### 2.3 运维管理条线15 模块)
**主线main**:验车入库 → 上牌 → 证照 → 备车 → 交车 → 还车 → 出售/过户/报废出库
**并行能力support**:供应商、采购合同、替换车、故障、年审、维保、异动、调拨(无严格先后)
**条线闭环**:供应商与采购合同入库 → 上牌证照与备车整备 → 交车/替换/还车闭环 → 故障与年审维保 → 异动调拨 → 出售/过户/报废审批出库。
| 步 | 模块名 | 轨道 | 一句话定位 | 责任部门 |
|---|---|---|---|---|
| 1 | 供应商管理 | support | 整车厂 / 三方租赁 · 付款底座 | 采购组、财务部 |
| 2 | 车辆采购 / 三方租赁合同 | support | 车型数量 · 付款关联 · 验车任务 | 采购部、法务部、财务部 |
| 3 | 验车入库 | main | 采购 / 三方来源 · 验完自动入库 | 运维部、采购部 |
| 4 | 车辆上牌 | main | 车架号入库 · 完成牌证登记 | 运维部 |
| 5 | 证照管理 | main | 一车一档 · 到期待办推送 | 运维部、安全部 |
| 6 | 备车管理 | main | 交车前整备 · 随时可交付 | 运维部 |
| 7 | 交车管理 | main | 司机培训留痕 · 区域派单 · OCR 比对 · 电子签 | 运维部、业务管理组、司机 |
| 8 | 替换车管理 | support | 临时 / 永久替换 · 费用自动核算 | 运维部、业务管理组 |
| 9 | 还车管理 | main | 区域派单 · 费用自动计算 · 电子签 | 运维部、业务管理组 |
| 10 | 故障管理 | support | AI 助手 + 人工 · 证据链归档 | 运维部、司机 |
| 11 | 年审记录 | support | 提前 3 个月 · OCR 刷新证照 | 运维部 |
| 12 | 维修与保养记录 | support | 费用汇总 · 业财一体 · 盈亏核算 | 运维部、财务部 |
| 13 | 车辆异动 | support | 出库维修 / 年审 / 保养 · 成本归集 | 运维部 |
| 14 | 车辆调拨 | support | 跨区调拨 · 运维权转移 | 运维部、业务管理组 |
| 15 | 车辆出售、过户、报废 | main | 资产变更审批 · 过程留痕 · 自动出库 | 运维部、董事长、财务部 |
---
### 2.4 安全管理条线6 模块 · 安全闭环)
**条线闭环**:司机信息与证照 → 定期培训与资料库学习 → 违规记录关联评级 → 违章/事故登记 → 联动还车应结款与代处理费用。
| 步 | 模块名 | 一句话定位 | 责任部门 |
|---|---|---|---|
| 1 | 司机管理 | 物流内部司机 · 信息证照一体 | 安全部、业务管理组 |
| 2 | 内部司机培训 | 定期安全培训 · 证据链留痕 | 安全部、司机 |
| 3 | 安全培训资料库 | 资料上传 · APP / 小程序学习 | 安全部、司机 |
| 4 | 违规记录 | 司机违规 · 关联评级 | 安全部、业务管理组 |
| 5 | 违章管理 | 分值罚款 · 还车联动 · 代处理 | 安全部、财务部、业务管理组 |
| 6 | 事故管理 | 权责划分 · 保险赔付 · 还车联动 | 安全部、财务部、业务管理组 |
---
### 2.5 物流业务条线3 模块 · 经营闭环)
**条线闭环**:物流合同生效 → 轻量调度派车(交车后可办结)→ 办结自动生成物流业务明细 → 汇总盈亏 → 汇集项目盈亏表 → 演进关联收款记录完成业财闭环。
| 步 | 模块名 | 一句话定位 | 责任部门 |
|---|---|---|---|
| 1 | 物流合同 | 关键信息录入 · 业务确认生效 · 可派车 | 业务管理组、业务服务组 |
| 2 | 调度任务 | 轻量派车 · 交还车校验 · 办结出车 | 业务服务组、调度岗、运维部 |
| 3 | 物流台账 | 任务自动生成 · 补录导入 · 盈亏核算 | 业务服务组、财务部 |
---
### 2.6 三大数据底座(管理决策层,非业务条线)
| 底座 | 看什么 | 主要数据来源条线 |
|---|---|---|
| 车辆资产运营情况 | 规模 · 结构 · 健康度 · 品牌型号出勤率下钻省市 | 运维、车辆管理、证照/保险、交车/备车 |
| 各业务条线盈亏情况 | 收入 · 成本 · 利润(条线/项目/单车) | 租赁台账、物流台账、氢费账户、收款、维保/事故/违章 |
| 里程调度情况 | 里程补贴 · 客户履约 · 智能替换与运维干预 | 车机/GPS/人工里程、客户里程约定、替换车、运维干预 |
---
## 3. 流程闭环速查(端到端一句话)
| 条线 | 闭环一句话 |
|---|---|
| 租赁 | 客户 → 模板 → 签约 → 提车应收 → 交车 → 台账账单 → 还车应结款归档 |
| 能源 | 供应商 → 加氢站 → 订单采集 → 氢费明细 → 客户账户收款 → 记录已付款 |
| 运维 | 采购/验车入库 → 牌证备车 → 交还车 → 维保故障 → 异动调拨 → 处置出库 |
| 安全 | 司机档案 → 培训资料 → 违规评级 → 违章事故 → 还车应结款费用 |
| 物流 | 合同生效 → 调度派车办结 → 台账明细/盈亏 →(演进)收款业财闭环 |
| 系统级 | 五条线业务闭环 → 三大数据底座决策 → 打通财务 YS 业财一体 |
**高频跨模块联动(写描述时勿漏)**
- 租赁签约路径依赖**客户管理**评级(标准 / 非标 / 禁止)
- **提车应收**对齐后触发运维**交车**;交车成功生成**租赁业务台账**
- **还车管理**完成后生成**还车应结款**;安全**违章/事故**费用写入应结项
- 运维**采购/三方租赁合同**自动生成**验车入库**任务
- 物流**调度办结**须车辆已**交车**;办结自动写**物流台账**
- 能源签约站**加氢订单**与非签约站**氢费明细**统一进入**氢费账户**对账收款
---
## 4. 故事点(按模块:起点 → 怎么运作 → 闭环)
> 结构对齐页面「起点 / 怎么运作 / 闭环」。标题用「模块名 + 核心动作」;描述保留谁发起、关键规则、闭环结果,不升格成完整 PRD。
> 下列为各模块业务事实摘要,用于**识别归属与用词**;材料未提及的细节**不得**脑补进描述。
### 4.1 租赁
#### 客户管理
- **起点**:业务管理组维护客户基础信息,作为后续合同与账单的统一客户主数据
- **怎么运作**:法务每 3 个月评估法律风险;财务实时维护财务风险等级;安全实时维护安全风险等级;系统综合形成签约策略
- **闭环**:未达禁止标准可签;偏离常规范式走「非标准流程」;达禁止标准禁止新签,现有合同标「高风险」并通知业务跟进或终止
#### 标准合同管理
- **起点**:法务部维护各车型试用/正式等标准模板,明确条款边界与风控要求
- **怎么运作**:数智部按模板配置电子合同;条款可设「触发车型」;「风控红线」被改进非标审批;「锁定区域」不可随意改
- **闭环**:业务员直选模板走标准流程;触碰红线或锁定区外修改转法务非标审批
#### 租赁合同
- **起点**:业务员选羚牛签约主体与乙方客户;系统按评级判标准/非标/禁止
- **怎么运作**:合同要素实时反写电子合同预览;生成电子合同/条款附件/授权委托书;越界转非标;支持续签、转正式、转三方、增值服务、授权委托书、主动终止等
- **闭环**:审批通过进入履约并串联提车应收、交车、台账;非标须法务与董事长确认后放行
#### 提车应收款
- **起点**:提交租赁合同审批时,按合同条款自动生成提车应收金额
- **怎么运作**:法务在「收款记录」导入到账(后期对接 YS/银企直联);业务/业管关联账单并分配金额;实收对齐后标记完成
- **闭环**:应收完成后按约定生成交车任务,属地运维执行交车
#### 租赁业务台账
- **起点**:运维交车成功后自动生成该车租赁账单,应付款日初始「待设置」
- **怎么运作**:设置应付款日后生成首期应收;提车实收写入首期;溢出并入第二期减免
- **闭环**:持续记录每期应收/实收/状态,支撑租期运营与还车结算
#### 还车应结款
- **起点**:运维完成还车后自动生成还车应结款任务
- **怎么运作**:业管、安全、运维、能源各自完成部门审批;汇总应退/应补;应补关联收款记录、应退关联付款记录
- **闭环**:业管发起总审批;完成后自动归档,租赁单条业务全链路闭环
---
### 4.2 能源
#### 供应商管理
- **起点**:加氢站/充电站作为供应商纳入统一体系,采购组维护基础信息与结算要素
- **怎么运作**:创建站点时绑定供应商;氢费/电费对账支持直连付款;收付款明细关联财务记录;支撑付款/收款申请审批
- **闭环**:供应商主数据与站点、对账、财务贯通,打好能源业财基础
#### 加氢站管理
- **起点**:采购部统一管理签约站/非签约站;签约站须关联供应商与系统账号
- **怎么运作**签约站账号登录加氢订单PC/移动/H5预付款余额营业状态成本价关联氢费记录能源部形成对账单并发起付款后期对接 YS
- **闭环**:站点/账号/余额/价格/营业状态集中管理,签约站可自助上报
#### 加氢订单
- **起点**签约站登录后多渠道上报订单PLC 站点可自动获取
- **怎么运作**多端快速识别记录PLC 自动获取;联动「小羚羚」预约接单,司机确认;进入加氢记录供对账
- **闭环**:主动上报或自动采集,预约在线闭环,减少手工补录
#### 车辆氢费明细
- **起点**:非签约站氢费由业务管理组-能源部手动维护
- **怎么运作**:录入并关联站点/车辆/客户对账后标「已对账」归档联动预付款余额与客户能源账户OCR 与电子围栏辅助核对
- **闭环**:签约/非签约氢费统一归集,余额变动可追溯
#### 氢费账户
- **起点**:管理客户氢费预付款余额与客户对账单
- **怎么运作**:维护余额变动;生成对账单;关联「收款记录」;收款后加氢记录标「已付款」;支持充值/开票直达财务(替代钉钉,对接 YS
- **闭环**:明细→对账→收款全链路可核对,付款状态与财务实收一致
#### 扩展规划
- **起点**:条线成熟后向上游采购与下游司机服务延伸
- **怎么运作**:上游氢气采购;下游外部氢能车司机服务;与现有供应商/站点/订单/账户衔接
- **闭环**:覆盖「采购—站点—用氢—结算—司机服务」更大范围生态
---
### 4.3 运维
#### 供应商管理
- **起点**:整车厂、三方租赁企业纳入供应商体系
- **怎么运作**:维护档案;为采购/三方租赁合同提供主数据;支撑付款底座
- **闭环**:与采购合同、付款记录贯通
#### 车辆采购 / 三方租赁合同
- **起点**:向整车厂/三方租赁厂商发起采购或三方租赁合同
- **怎么运作**:创建审批;关联付款记录;按条款自动生成验车任务
- **闭环**:合同、付款、验车联动,入库合规入口
#### 验车入库
- **起点**:对采购或三方来源氢能车执行验车
- **怎么运作**:接收验车任务;记录过程与问题;验完自动入库
- **闭环**:验车结果与合同、库存绑定,来源可审计
#### 车辆上牌
- **起点**:对仅有车架号的新车执行上牌
- **怎么运作**:筛选待上牌车;录入/同步牌照;更新库存状态
- **闭环**:牌证完整,为证照与交车提供前置条件
#### 证照管理
- **起点**:行驶证、道路运输证、登记证、特种设备证/标识、加氢卡、安全阀、压力表等一车一档
- **怎么运作**:维护档案与有效期;临近到期生成年审/等评/换证待办;推送运维/安全
- **闭环**:证照全生命周期管理,降低漏办与违规风险
#### 备车管理
- **起点**:日常提前整备,确保交车任务可随时交付
- **怎么运作**:按计划/库存策略发起检查;记录整备项与责任人
- **闭环**:交车前置完成,提升交付效率与质量一致性
#### 交车管理
- **起点**:承接租赁/物流交车任务,按区域派属地运维;司机先完成在线培训并留痕
- **怎么运作**:司机上传身份证/驾驶证/从业资格证、签名与现场拍照;交付证照及保险有效车辆;记录里程/氢量/电量/位置OCR 胎纹还车时比对算磨损等费用E 签宝电子签归档
- **闭环**:培训与交车数据完整可查,为还车费用与争议提供依据
#### 替换车管理
- **起点**:因客户或车辆原因发起临时/永久替换
- **怎么运作**:选类型与新旧车;完成替换交还;客户原因自动算费用差
- **闭环**:过程可追踪、费用可核算,履约不中断
#### 还车管理
- **起点**:处理业务/业管还车任务,按区域派属地运维
- **怎么运作**:记录还车时间/里程/氢电量/位置OCR 胎纹对比算磨损费按里程与氢电差算费用E 签宝确认归档
- **闭环**:费用依据交还对比自动出具
#### 故障管理
- **起点**:微信 AI 故障助手或人工记录故障关键信息
- **怎么运作**:记时间地点车型紧急程度;留存图文视频聊天证据;运维处理至关闭;形成待办统计;沉淀品牌故障类型统计支撑采购论证
- **闭环**:全过程留痕,证据链完整
#### 年审记录
- **起点**:按行驶证审验有效期提前 3 个月生成年审任务
- **怎么运作**:按车按月归集;完成后 OCR 新行驶证刷新证照;按月量化完成率
- **闭环**:任务不遗漏,证照与办理结果同步
#### 维修与保养记录
- **起点**:运维手动维护负责车辆维保记录(首期)
- **怎么运作**:配件费/人工费汇总;按承担方(客户/我司)生成客户账单或计入运维成本;计入车辆盈亏
- **闭环**:维保成本可追溯可分摊,支撑单车盈亏与对客户计费
#### 车辆异动
- **起点**:因当地维修/年审/保养出库异动,须提前审批
- **怎么运作**:记异动前后氢电量里程;异动期间加氢记录归集为异动成本
- **闭环**:可审批可计量,避免成本漏记
#### 车辆调拨
- **起点**:车辆从 A 地调至 B 地运营,须提前审批
- **怎么运作**:记发起方/费用/运输;接收方确认;运维操作权由 A 转 B
- **闭环**:跨区调拨透明,责任属地随车切换
#### 车辆出售、过户、报废
- **起点**:达出售/过户/报废条件发起资产变更,录入交易方价格过户残值等
- **怎么运作**:提交申请;董事长确认;运维记录全过程归档;完成后退出运营并出库
- **闭环**:处置审批留痕,生命周期闭环至出库归档
---
### 4.4 安全
#### 司机管理
- **起点**:管理物流内部司机,支撑快速选取与档案维护
- **怎么运作**:维护基础信息与在职状态;管理驾驶证/从业资格证;与交车、台账联动
- **闭环**:主数据统一、证照可查,支撑调度与合规
#### 内部司机培训
- **起点**:定期开展安全培训并形成可追溯记录
- **怎么运作**:制定计划组织参训;记录时间内容参训人;形成证据链供交管查询
- **闭环**:培训电子归档,随时可调阅
#### 安全培训资料库
- **起点**:安全部上传培训与安全运营资料供司机学习
- **怎么运作**:维护课件制度指引;分类发布版本检索;司机经 APP/小程序学习
- **闭环**:资料集中更新,移动端可学可查
#### 违规记录
- **起点**:记录内部司机运营违规
- **怎么运作**:登记事件类型时间结果;关联司机档案;联动客户安全评级
- **闭环**:违规可追踪汇总,支撑选用与评级
#### 违章管理
- **起点**:记录交通违章并与还车应结款联动
- **怎么运作**:登记时间地点分值罚款及是否缴纳;未处理纳入还车结算;逾期未缴自动生成代处理费用
- **闭环**:违章可查,代处理费用与还车/财务口径一致
#### 事故管理
- **起点**:记录事故信息,支撑定责理赔与还车结算
- **怎么运作**:登记权责划分;记保险介入/赔付/上浮;联动还车应结款写入安全费用
- **闭环**:登记→赔付→上浮→应结款贯通,费用不遗漏
---
### 4.5 物流
#### 物流合同
- **起点**:创建物流运力服务合同,录客户/车型/车辆数/交车时间地点,上传附件
- **怎么运作**:录入项目与合同要素;业务确认生效后可创建轻量调度并提示运维交车
- **闭环**:合同成为调度派车与交车的上游凭证
#### 调度任务
- **起点**:在生效合同下创建出车任务,派车派司机;非 TMS
- **怎么运作**:选合同、计划出车日、线路、是否多趟与计价口径;未交车须先交车;办结确认实际出车后自动生成物流业务明细一行
- **闭环**:出车事实追溯到合同与车牌,驱动台账落账
#### 物流台账
- **起点**:承接调度办结自动生成的出车明细,导入/行编辑补录异常与历史
- **怎么运作**:办结写入营收侧并算金额/总成本/盈亏;氢费/ETC 等成本可手工补录;汇集项目盈亏表;演进关联「收款记录」
- **闭环**:收入与司机/车辆成本同台账可核对,盈亏可对接财务实收
---
## 5. AutoRDO 应用约定
1. **标题**:优先 `模块标准名:核心动作/结果`1030 字),模块名以本词典为准(例:`验车入库:采购与三方租赁合同自动生成验车记录及入库`
2. **条线归属**:一句需求只挂一个主模块;跨条线联动写在描述里,不硬塞进标题
3. **部门用词**:口语「业管/能源组/运维」等映射到第 1 节标准名
4. **闭环口径**:若材料只讲做到一半,闭环写实际说到的结果,缺的标「待确认」
5. **不做**:不把本词典全文贴进云效描述或输出稿;不脑补材料未出现的故事点细节
6. **业财关键词**:收款记录、付款记录、对账单、应收/实收、YS、银企直联、E 签宝、小羚羚、PLC——保留原文业务对象名勿随意改写
---
## 6. 条线演进(辅助理解,非强制写入描述)
| 条线 | 现阶段 | 演进方向 |
|---|---|---|
| 租赁 | 合同电子化 · 业务闭环化 | 移动端商城直连发起合同,后续自动打通 |
| 能源 | 手工维护氢费明细 | 签约站主动上报,能源部转为核对确认 |
| 运维 | 车辆使用环节闭环 | 入库→运作→出库全链路 |
| 安全 | 司机安全全链条 | 与客户安全评级挂钩、事前预判 |
| 物流 | 合同 + 调度办结落账 | 成本自动回填、司机在线、关联收款;不做完整 TMS |
| 系统 | 业务驱动 · 财务手工 | 打通 YS · 业财一体 |

View File

@@ -0,0 +1,67 @@
# AutoRDO 清洗与拆解细则
## 目标
碎片 → 可入库的书面「标题」与「描述」。保留原意;不写成产品 PRD。
多行/多条独立输入 → **多份**转译结果(一份需求一份稿)。
## 必做与精炼规则
| 规则 | 说明 |
|---|---|
| **多条拆解** | 输入为多条独立诉求时,**先拆后洗**<br>• **拆分信号**(满足任一即可):换行且每行一句独立诉求;`1. 2. 3.` / `-` / `*` 列表;表格多行;空行分段;「另外」「还有」「第二条」等显式分条<br>• **每条**各自输出一份标题+描述+待确认,**禁止**合并成一条大需求<br>• **不拆**:同一条需求内部的续写、补充说明、功能规则子点(属于描述细节,挂在该条下)<br>• **边界不清**:无法判断是一条还是多条时,在文首标「待确认:拆条边界」,并按最可能的分条给出结果,请用户校对 |
| **OneOS 领域对齐** | 涉及 ONE-OS / 羚牛业务时,**先读** [oneos-domain.md](oneos-domain.md)<br>• 部门口语映射到标准名(业管→业务管理组,能源组→业务管理组-能源部 等)<br>• 标题模块名优先用词典标准名(如「验车入库」而非口语「验车管理」——若材料确指该模块)<br>• 跨条线联动写在描述,标题只挂主责模块<br>• **禁止**把词典全文或未在材料中出现的故事点细节写入输出 |
| **标题提炼** | 根据材料内容理解,自动概括简炼、清晰的标准需求标题:<br>• **内容理解**:准确识别归属的业务模块与核心动作/诉求(如:`验车入库:采购与三方租赁合同自动生成验车记录及入库`)。<br>• **自然流畅**:表达自然书面化,无需死板强求拼接固定句式;彻底剔除“我们要做一个”、“主要是用于”、“完成之后才能”等口语废话。<br>• **字数适中**:控制在 10-30 字内,能让读者一眼看懂需求核心。 |
| **元数据识别** | 详见 [meta-fields.md](meta-fields.md)。从台账列或正文自动识别并输出:<br>• **类型**`【新增】`/`【优化】`<br>• **优先级**`P1-高`/`P2-中`/`P3-低`<br>• **标签**:标准模块名(+ 可选 PC端/小程序)<br>• **提交部门**:映射词典标准名(业务管理部→业务管理组,数智中心→数智部 等)<br>• **提交人**:反馈方/用户列或署名<br>• 显式列优先;推断不确定则待确认;**不**直接写云效打标 |
| **描述转译** | 原文的转译结果,将口述/碎片材料转译为规范书面表达保留原意不改变谁要求什么、约束与例外不替换成「更优方案」业财对象名收款记录、付款记录、YS、E 签宝、小羚羚、PLC 等)按词典保留 |
| 书面化 | 口语改成完整句子或清晰短条目;主谓齐全 |
| 去口头禅 | 删除:嗯、啊、那个、就是说、然后呢、对对对、你懂吧 等 |
| 自我修正 | 以最后一次明确口径为准;若前后矛盾且未决,列入「待确认」 |
| 去重复 | 同一意思多轮确认只保留一处;多条拆解时,各条之间不要互相抄写无关内容 |
| 轻度格式 | 可用短标题/条目;禁止展开成总览/角色/流程图/故事点等 PRD 结构 |
| 去结尾句号 | 描述中每个句子或条目末尾去掉 `。`;保留 `` `` 若确为疑问/感叹 |
| 待确认 | 材料含糊处写 `待确认:…`,不臆造;**只要存在待确认,同轮强制**进入 [confirm-pending.md](confirm-pending.md) 的 Plan 逐条确认(无需用户再说「确认待确认」) |
| **待确认 Plan 确认** | 详见 [confirm-pending.md](confirm-pending.md)<br>• 清洗结果含待确认 → **立刻** `SwitchMode` → plan<br>• 按需求条号**逐点**确认;**优先选择题**25 项 +「其他/我补充」),选项用 `oneos-domain.md` 辅助<br>• 也支持用户粘贴**需求描述/补充说明**一次消解多点<br>• 确认后回填描述并移除已消解项;未确认不得写入定稿 |
## 多条拆解示例
**输入(多行):**
```text
还车应结款生成后自动展示违章事故信息,不必等安全员提交
验车完成后才能车辆入库
氢费账户对账单要能关联收款记录
```
**输出**3 份独立的「原始诉求AutoRDO每份各自标题+描述;不要揉成一条。
## 标题提炼对比示例
-**坏标题(直抄口语/带废话)**`我们现在要做一个验车管理功能主要是采购合同和三方租赁合同自动形成验车记录验车完成之后才能车辆入库`
-**好标题(自然清晰,覆盖标准模块)**`验车入库:采购与三方租赁合同自动生成验车记录及入库`(模块名对齐 oneos-domain
## 不做
- 不生成 AutoPRD 十章或「产品说明」
- 不写验收清单、故事点、mermaid
- 不改云效、不建【交付】/分析/设计
- 不加载 `yunxiao-requirement-lifecycle`
- 不把多条独立诉求合并成一条「大杂烩」需求
## 录音
1. 已有转写 → 按上文清洗转写稿并拆解标题与描述;转写中若含多条独立诉求,同样先拆后洗
2. 仅音频 → 回报「请提供转写文本后再 AutoRDO」停止声称已清洗完成
## 质量自检
- [ ] 多行/多条输入时,已按条拆成多份结果(条数与输入独立诉求数一致或已说明待确认边界)
- [ ] 已对照 `oneos-domain.md`ONE-OS 相关材料)
- [ ] **标题清晰通顺**(标准模块名 + 核心动作,无死板句式绑定,无口语废话)
- [ ] 部门/业财关键词已映射或保留为词典标准口径
- [ ] **描述为原文的转译结果**,干系人能认出这是自己说的意思;未脑补词典故事点
- [ ] 无口头禅堆砌、无未决矛盾被写成定论
- [ ] 描述末尾无 `。`
- [ ] 未冒充完整 PRD未把词典全文写入输出
- [ ] 已输出类型/优先级/标签/提交部门/提交人(有依据或已标待确认;未臆造提交人)
- [ ] 若存在待确认:已同轮强制进 Plan未等「确认待确认」口令优先选择题、选项有词典依据文字补充已映射到对应点定稿无未确认臆造
- [ ] 若无待确认:未多余进 Plan

View File

@@ -0,0 +1,139 @@
---
name: AutoVUL
description: >-
Generates OneOS PC version update logs from a Yunxiao (云效) iteration name by
loading all linked requirements, or from a pasted changelog list. Use when testers
or PMs say AutoVUL, 版本更新日志, 按迭代生成更新日志, 发版公告, or give a 迭代名称.
---
# AutoVULOneOS PC 版本更新日志)
面向**测试人员发版**:输入云效**迭代名称** → 拉取该迭代关联需求 → 自动生成对外版本更新日志。
也可手动粘贴变更清单(兜底)。**预计维护时长**由人工单独通知,不写进日志。
## 何时使用
- 测试说:`按 $AutoVUL` / `生成版本更新日志` / `按迭代 xxx 出更新日志`
- 输入含云效「迭代名称」
- 发版前需要统一文案口径
## 主流程(测试 · 按迭代,默认)
完整取数步骤见 [references/yunxiao-sprint.md](references/yunxiao-sprint.md)。
```text
1. 确认云效项目缺省统一运营管理平台PC端可改
2. 向用户索取「迭代名称」(若口令里已带则直接用)
3. 在云效查找该迭代 → 立即反馈成功或失败(见下)
4. 成功:列出迭代内关联「需求」清单(编号 + 标题 + 状态)供用户快速核对
5. 从每条需求提取变更素材(优先级见「素材优先级」)
6. 按本文格式分类、合并、润色 → 输出成稿正文
```
### 迭代读取 · 成功 / 失败反馈(强制)
查找迭代后**必须先反馈**,再继续或停止:
| 结果 | 反馈文案(可微调,语义不变) | 下一步 |
|------|------------------------------|--------|
| 精确命中 1 个迭代 | `✅ 已找到迭代「{名称}」(状态:{状态}),关联需求 {N} 条。` | 继续拉需求并生成 |
| 0 个匹配 | `❌ 未找到迭代「{输入}」。请核对后重新输入迭代名称(可复制云效迭代标题)。` | **停止生成**;等待用户重输 |
| 多个模糊匹配 | `⚠️ 找到多个相似迭代1)… 2)… 请回复序号或完整精确名称。` | 等用户选定后再继续 |
| 登录/权限失败 | `❌ 无法访问云效(未登录或无权限)。请在浏览器登录云效后重试,或改用手动清单。` | 停止;提示登录或兜底 |
| 迭代存在但 0 条需求 | `⚠️ 迭代「{名称}」已找到,但暂无关联需求。请确认规划后再试,或改用手动清单。` | 停止生成对外正文 |
**失败后**:用户只需再发一次迭代名称(或纠正项目名),从步骤 2 重跑;不要要求用户重装 Skill。
### 素材优先级(每条需求)
| 顺序 | 来源 | 用法 |
|------|------|------|
| 1 | 需求描述中的「更新内容」段(非「更新内容·历史」) | 首选,直接改写成日志条目 |
| 2 | AutoPRD「功能变更记录」中可对外部分 | 次选 |
| 3 | 需求标题 + 简短描述摘要 | 仅当前两者皆空时;价值句可合理补全 |
| — | 纯技术债、内部监控、未对用户开放 | **不写入**对外日志 |
Bug 类需求(类型/标签含缺陷修复、或更新内容写「修复」归入【Bug修复】其余归【新功能】。边界不清优先 Bug修复。
### 版本号与更新时间
| 字段 | 规则 |
|------|------|
| 版本号 | 优先从迭代名解析(如含 `V1.1.5` / `1.1.5`);解析不到再问用户 |
| 更新时间 | 用户提供则用;未提供可写迭代计划开始日的 `MM月DD日HH:MM`,或先问 |
| 产品线 | 默认 `OneOS PC版` |
## 兜底流程(手动清单)
无云效权限、或迭代为空时:用 [input-template.md](input-template.md) 粘贴清单,跳过迭代步骤,直接分类润色。
## 固定输出格式
```text
OneOS PC版V{主.次.修订}更新日志:
更新时间:{MM}月{DD}日{HH}:{MM}
----------------------------------------------------
【新功能】
1「{模块名}」{做了什么}{责任部门}可{用户价值 / 解决的问题}
2「{模块名}」{…}
【Bug修复】
3「{模块名}」{修复了什么}{责任部门}可{恢复的能力 / 避免的影响}
```
### 版式硬约束
| 项 | 规则 |
|----|------|
| 标题 | `OneOS PC版V` + 版本号 + `更新日志:`(如 `V1.1.5`,无空格) |
| 更新时间 | 仅开始时刻;`MM月DD日HH:MM`**禁止**「预计x分钟内完成」 |
| 分隔线 | `----------------------------------------------------` |
| 分区 | 仅 `【新功能】` / `【Bug修复】`;空类整段省略 |
| 序号 | 全篇连续,从 1 起 |
| 模块名 | `「」`;与产品菜单正式名一致 |
| 对外正文 | **不写**需求号、缺陷号、迭代 ID核对清单可另附 |
| 结尾 | 无签名、无「感谢使用」、无技术附录 |
## 分类 / 合并 / 文案(成稿规则)
| 归入【新功能】 | 归入【Bug修复】 | 不写进对外日志 |
|----------------|-----------------|----------------|
| 新增能力、新入口、新字段/流程、可感知体验优化 | 原有能力异常、报错、数据错、交互失效 | 技术债、无感性能、未开放灰度、仅内部监控 |
- **同分区同模块**合并为一条,分点用 ``
- **跨分区**同模块分栏各写一条
- 每条含:做什么 + 用户价值 + 责任部门自然嵌入(`{部门}人员可…`
- **禁止**「供…条线…使用」;部门对照 [module-role-mapping.md](module-role-mapping.md)
- 禁止编造迭代内不存在的能力;存疑跳过或标待确认(不进正式成稿)
- 单条建议 ≤100 字
排序:先新功能后修复;同分区全员影响优先;资金/合规修复置修复区最前。
## 输出纪律
1. **先**输出迭代读取反馈(✅/❌/⚠️)
2. 成功时:可先给「本迭代需求清单」短表(含编号,便于测试核对)
3. 再输出**纯文本成稿正文**(默认不要 Markdown 大标题包裹成稿)
4. 用户明确要求时,可在正文后附「分类依据 / 跳过项」
## 发布前自检
- [ ] 已反馈迭代查找结果;失败时未强行编造成稿
- [ ] 成稿条目均可追溯到本迭代关联需求素材
- [ ] 标题、时间行、分隔线正确;无预计时长
- [ ] 同模块合并正确;每条含价值 + 部门自然嵌入
- [ ] 对外正文无需求号/缺陷号/技术黑话;序号连续
## 给测试同事的口令
```text
按 $AutoVUL 生成版本更新日志。
项目统一运营管理平台PC端
迭代名称V1.1.5发版迭代
更新时间07月16日16:00
```
迭代名写错时,按提示改完再发一次即可。
手动兜底见 [input-template.md](input-template.md);成稿范例见 [examples.md](examples.md)。

View File

@@ -0,0 +1,77 @@
# AutoVUL 成稿与交互范例
## 1. 迭代读取失败 → 重输
**用户:**
```text
按 $AutoVUL迭代名称V1.1.5
```
**Agent**
```text
❌ 未找到迭代「V1.1.5」。请核对后重新输入迭代名称(可复制云效迭代标题)。
```
**用户:**
```text
V1.1.5发版迭代
```
**Agent**
```text
✅ 已找到迭代「V1.1.5发版迭代」(进行中),关联需求 3 条:
1. ONEOSP-201 车辆管理运营城市展示优化
2. ONEOSP-202 还车应结款租金计算修复
3. ONEOSP-203 业务管理新增租赁物流统计
OneOS PC版V1.1.5更新日志:
更新时间07月16日16:00
----------------------------------------------------
【新功能】
1「车辆管理」优化车辆「运营城市」展示运维部人员可快速辨认车辆所属运营区域及数据来源
2「业务管理」新增租赁、物流业务统计模块业务管理组、业务员可查看租赁经营数据业务服务组、财务部可跟踪自营物流经营情况
【Bug修复】
3「还车应结款」修复租金费用项重复及计算错误业务管理组、安全部、运维部、能源部人员还车结算金额更准确
```
## 2. 完整成稿风格基准(手动/迭代素材均可)
> 责任部门对照:`module-role-mapping.md`OneOS 业务条线说明)
```text
OneOS PC版V1.1.5更新日志:
更新时间07月16日16:00
----------------------------------------------------
【新功能】
1「加氢站管理」升级新版加氢站模块采购部可统一维护签约站与非签约站信息签约加氢站可便捷管理站点日常运营
2「车辆管理」优化车辆「运营城市」展示运维部人员可快速辨认车辆所属运营区域及数据来源
3「审批中心」支持按客户名称搜索关联合同业务员、法务部审批时可快速定位合同还车应结款添加照片附件后业务管理组、安全部、运维部、能源部会签人员可在审批流中查看完整附件
4「保险采购」支持保比价单按车辆单独勾选并分开提交审批运维部、安全部人员可按车辆分批推进投保审批
5「故障管理」增加「故障来源」字段展示运维部人员可区分上报渠道并跟进处理
6「证照管理」特种设备使用登记证/使用标识照片支持OCR识别运维部、安全部人员可减少手工录入、加快证照建档
7「全局显示」统一各模块列表分页样式与交互各模块操作人员跨页面浏览时体验一致、上手更快
8「交还车管理」支持交车/还车签章文件在线预览,运维部、业务管理组、司机可现场核对签章文件;提交时增加胎纹数据必填校验,减少漏填导致的后续结算争议
9「还车应结款」调整安全部待办区域权限安全部人员仅处理职责范围内的还车应结款审批
10「业务管理」新增租赁、物流业务统计模块业务管理组、业务员可查看租赁经营数据业务服务组、财务部可跟踪自营物流经营情况
【Bug修复】
11「还车管理」修复签字单与还车检查单/还车应结款轮胎数据不一致,运维部、业务管理组人员还车验收与结算依据保持一致
12「租赁合同」修复编辑合同提交时异常提示内容冗余业务员、法务部人员可快速定位真正错误原因
13「交还车管理」修复交车/还车签章客户名称关联错误,避免运维部、业务管理组、司机现场核对时客户信息张冠李戴
14「车辆氢费明细」修复同客户不同生效时段、以及不同客户成本单价显示异常能源部人员可准确核对氢费核算单价
15「还车应结款」修复租金费用项重复及计算错误业务管理组、安全部、运维部、能源部人员还车结算金额更准确
```
## 对照要点
| 规则 | 体现 |
|------|------|
| 先反馈迭代结果 | 失败可重输;成功列出需求再成稿 |
| 无预计时长 | 更新时间仅 `07月16日16:00` |
| 对外无需求号 | 成稿正文不出现 ONEOSP-xxx |
| 部门自然嵌入 | `运维部人员可…`,无「供…条线使用」 |

View File

@@ -0,0 +1,69 @@
# AutoVUL · 输入模板
## A. 测试人员 · 按云效迭代(推荐)
复制下面口令发给 AI改迭代名即可
```text
按 $AutoVUL 生成版本更新日志。
项目统一运营管理平台PC端
迭代名称:
更新时间:
```
### 期望反馈
- 成功:`✅ 已找到迭代「…」,关联需求 N 条` → 随后输出成稿
- 失败:`❌ 未找到迭代「…」。请重新输入迭代名称` → 改名后再发一次即可
**说明**:预计维护时长由人工单独通知,不写入版本更新日志。
---
## B. 手动清单(云效不可用时兜底)
### 版本元信息
| 字段 | 填写 | 示例 |
|------|------|------|
| 产品线 | | OneOS PC版 |
| 版本号 | | V1.1.5 |
| 更新开始时间 | | 07月16日16:00 |
| 发布范围 | 全量 / 灰度(说明) | 全量 |
| 是否对外发布 | 是 / 否 | 是 |
### 新功能(原始材料,可粗糙)
| 模块 | 做了什么 | 解决什么问题 / 用户故事 | 业务条线 | 责任部门 | 是否写入日志 |
|------|----------|-------------------------|----------|----------|--------------|
| 例:加氢站管理 | 升级新版模块 | 统一维护站点 | 能源业务条线 | 采购部、加氢站 | 是 |
| | | | | | |
### Bug修复原始材料可粗糙
| 模块 | 原问题现象 | 修复后表现 | 对用户的影响 | 业务条线 | 责任部门 | 是否写入日志 |
|------|------------|------------|--------------|----------|----------|--------------|
| 例:还车应结款 | 租金费用项重复 | 金额正确 | 避免结算偏差 | 租赁业务条线 | 业务管理组、安全部、运维部、业务管理组-能源部 | 是 |
| | | | | | | |
### 明确不要写入对外日志
- (如:重构、依赖升级、仅内部监控、未上线配置)
### 粘贴给 AI
```text
请按 $AutoVUL 用下方手动清单生成成稿(跳过云效迭代)。
要求:同模块合并;每条含「做什么 + 用户价值」;责任部门自然融入;只输出正文。
【版本元信息】
- 产品线OneOS PC版
- 版本号V
- 更新开始时间:
【新功能】
(粘贴)
【Bug修复】
(粘贴)
```

View File

@@ -0,0 +1,60 @@
# 模块 → 业务条线 / 责任部门对照
> 数据源OneOS「业务条线说明」页责任部门定义租赁 / 能源 / 运维 / 安全 / 自营)
> 生成更新日志时,**适用对象**须从此表取 `roles`,不得自造部门名。
## 五条业务条线
| ID | 条线名称 |
|----|----------|
| lease | 租赁业务条线 |
| energy | 能源业务条线 |
| ops | 运维管理条线 |
| safety | 安全管理条线 |
| self-operated | 自营业务条线 |
## 本版变更模块对照
| 更新日志模块名 | 业务条线 | lines.ts 模块 | 责任部门roles原文 |
|----------------|----------|---------------|-------------------------|
| 加氢站管理 | 能源业务条线 | 加氢站管理 | 采购部、加氢站 |
| 车辆管理 | 运维管理条线 | 验车入库 / 车辆管理(资产底座) | 运维部、采购部 |
| 审批中心 | 跨条线 | 租赁合同 + 还车应结款(审批场景) | 业务员、法务部、业务管理组、安全部、运维部、业务管理组-能源部 |
| 保险采购 | 运维管理条线 | 证照 / 保险(车辆资产关联) | 运维部、安全部 |
| 故障管理 | 运维管理条线 | 故障管理 | 运维部、司机 |
| 租赁合同 | 租赁业务条线 | 租赁合同 | 业务员、法务部 |
| 证照管理 | 运维管理条线 | 证照管理 | 运维部、安全部 |
| 全局显示 | 全系统 | 系统介绍(五条条线) | 业务管理组、运维部、采购部、安全部、法务部、财务部、业务管理组-能源部、业务服务组 |
| 交还车管理 | 运维管理条线 | 交车管理 + 还车管理 | 运维部、业务管理组、司机 |
| 还车应结款 | 租赁业务条线 | 还车应结款 | 业务管理组、安全部、运维部、业务管理组-能源部 |
| 还车管理 | 运维管理条线 | 还车管理 | 运维部、业务管理组 |
| 车辆氢费明细 | 能源业务条线 | 车辆氢费明细 | 业务管理组-能源部 |
| 业务管理 · 租赁统计 | 租赁业务条线 | 租赁业务台账 / 客户管理 | 业务管理组、业务员 |
| 业务管理 · 物流统计 | 自营业务条线 | 自营台账 | 业务服务组、财务部 |
## 写法规则
- 部门名与 `roles` **完全一致**`业务管理组-能源部` 对外可简写「能源部人员」)
- **禁止**「供…业务条线…使用」「供…人员使用」
- **推荐**`{部门}人员可…` / `{部门}可…` / `{部门}审批时可…`
- 同模块合并后,多部门用顿号或分号自然串联
- 找不到模块时:查 `lines.ts`;仍无则标「待产品确认」不进成稿
## 自然表述示例
| 模块 | 生硬(禁止) | 自然(推荐) |
|------|--------------|--------------|
| 车辆管理 | 供运维管理条线运维部使用 | 运维部人员可快速辨认车辆所属运营区域 |
| 加氢站管理 | 供能源业务条线采购部、加氢站使用 | 采购部可统一维护站点信息,加氢站可便捷管理日常运营 |
| 还车应结款 | 供租赁业务条线业务管理组…使用 | 业务管理组、安全部、运维部、能源部还车结算金额更准确 |
## 常见错误(禁止)
| 错误写法 | 正确写法 |
|----------|----------|
| 氢能运营业务人员 | 采购部、加氢站(能源 · 加氢站管理) |
| 车辆运营及资产管理业务人员 | 运维部、采购部(运维 · 车辆管理) |
| 各业务条线审批人员 | 业务员、法务部、…(按审批场景枚举) |
| 保险采购业务人员 | 运维部、安全部 |
| 还车结算业务人员 | 业务管理组、安全部、运维部、业务管理组-能源部 |
| 经营分析及管理部门 | 业务管理组、业务服务组(分租赁 / 自营) |

View File

@@ -0,0 +1,81 @@
# 云效迭代 → 需求清单AutoVUL 取数)
测试人员只提供**迭代名称**Agent 负责在云效定位迭代、拉取关联需求、抽出更新素材。
## 安全边界(强制)
- **禁止**在对话、Skill、日志、成稿中写入 Token、密码、Cookie、私钥。
- 优先复用**已登录浏览器会话**操作云效 Projex`yunxiao-requirement-lifecycle` 一致)。
- 若团队已配置本机环境变量访问 OpenAPI可走 APIToken 只读自环境,永不回显。
建议环境变量(可选,名称可按团队调整):
| 变量 | 用途 |
|------|------|
| `YUNXIAO_TOKEN` | 个人访问令牌(`x-yunxiao-token` |
| `YUNXIAO_DOMAIN` | 服务接入点域名 |
| `YUNXIAO_ORG_ID` | 组织 ID中心版 |
| `YUNXIAO_PROJECT_ID` | 默认项目 ID或运行时按项目名解析 |
## 默认项目
口令未指定时:`统一运营管理平台PC端`。项目名不精确时先问清再查迭代。
## 判定顺序:解析迭代
| 顺序 | 条件 | 结果 |
|------|------|------|
| 1 | 用户未给迭代名称 | 询问:「请输入云效迭代名称(可复制标题)」;不继续 |
| 2 | 项目未确定 | 询问精确项目名;不继续 |
| 3 | 云效不可访问 | `❌ 无法访问云效…`;不继续 |
| 4 | 名称精确匹配 1 条迭代 | `✅ 已找到迭代…`;进入拉需求 |
| 5 | 0 条 | `❌ 未找到迭代…请重新输入`;不继续 |
| 6 | >1 条相似 | `⚠️ 多个相似…请回复序号或精确名称`;等用户选定 |
| 7 | 命中但关联需求 0 | `⚠️ …暂无关联需求`;不生成对外正文 |
匹配规则:先**全等**(去首尾空格);全等失败再做包含/去空格模糊;模糊多条必须让用户确认,禁止擅自挑一个。
## 拉取关联需求
只收集工作项类型为**需求Req**且正式关联到该迭代的项。
- **浏览器路径**:打开项目 → 迭代 → 该迭代规划/工作项列表 → 筛选类型=需求 → 导出或逐条打开描述。
- **OpenAPI 路径(示意)**
1. `ListSprints`:按项目列迭代,用 `name` 匹配用户输入,得到 `sprintId`
2. `SearchWorkitems``category=Req``spaceId=项目Id``conditions` 中按字段 `sprint` CONTAINS `[sprintId]`(以租户实际 fieldIdentifier 为准;可先在需求列表页过滤后复制 `workitem/list` 的 conditions
3. 分页直到收齐(关注响应头 `x-total`
4. 需要正文时再 `GetWorkitem` 取 description
每条需求最少记录:
| 字段 | 说明 |
|------|------|
| serialNumber | 如 ONEOSP-123仅用于核对清单**不进对外成稿** |
| subject | 标题 |
| status | 状态展示名 |
| description | 用于抽取「更新内容」 |
| category / type / labels | 辅助判断新功能 vs 修复 |
## 从描述抽「更新内容」
1. 定位标题「更新内容」或「## 更新内容」段落
2. **不要**把「更新内容·历史」并入本版素材(历史仅备查)
3. 若无「更新内容」:用标题 + 需求说明摘要;仍无有效产品语义则跳过并在内部备注
## 成功反馈后的核对清单(推荐短表)
在生成成稿前输出,例如:
```text
✅ 已找到迭代「V1.1.5发版迭代」(进行中),关联需求 5 条:
1. ONEOSP-101 保险采购比价分车提交
2. ONEOSP-102 交还车签章预览
正在按 AutoVUL 格式生成更新日志…
```
用户若立刻纠正「某条不要进日志」,从素材中剔除后再出成稿。
## 与发版任务关系
本 Skill **只读**迭代与需求,**不创建**【发版】任务、不改云效状态。发版挂链仍用 `yunxiao-requirement-lifecycle`(如「准备发布」口令 / A08

View File

@@ -0,0 +1,113 @@
---
name: YunxiaoPM
description: >-
产品经理云效Projex自动化记录需求压缩点选 1a2b3a4d类型/项目/优先级/标签)、
实时点选云效项目、推进 待处理→已确认→分析中→设计中→设计完成→待开发,
交付树【交付】ASSOCIATED /【分析】【设计】TASK_SUB无单快轨与编号直推交棒何斐
创建迭代并挂【交付】(不挂需求)。用户说 YunxiaoPM、YunxiaoPMapp、需求任务、记录需求、受理确认、开始分析、
开始设计、设计完成、交棒开发、快轨待开发、编号直推、创建迭代 时使用。
不建【开发】/【测试】。凡写云效先 Plan 确认再一口气 apply禁止对齐
yunxiao-requirement-lifecycle。
---
# 需求任务YunxiaoPM
产品部云效自动化。斜杠调起 **`/YunxiaoPM`**;对外中文名 **需求任务**(原名 YunxiaoPMapp。本 Skill **自洽成篇****禁止** fork / include / 「对齐」`yunxiao-requirement-lifecycle`
产品经理会话**不要**同时挂载旧 lifecycle Skill避免双建任务。
## Plan 模式门禁(强制 · 凡写云效)
凡会改云效的操作(建单、改状态、建/改任务、打标、传附件、改负责人、建迭代等Agent **第一步**必须:
1. `SwitchMode`**plan**(说明:先对齐参数与执行清单,确认后再一口气 apply
2. **新建**依赖项目空间时:先按 [references/project-selection.md](references/project-selection.md) **实时拉项目列表并点选(门禁 PJ**;禁止静默使用 `runtime-ids.json` 默认 `spaceIdentifier`。口令/选项**无法对应**时:**自动重拉项目列表一次**再匹配;仍失败则停请用户重选(禁止第 3 次空转拉取)。
3. Plan 写清:**已选项目名 + spaceId**、目标需求/任务**编号**、将改状态、将建/复用的交付·分析·设计编号策略、迭代版本类型若适用、§0.1① 占位风险勾选(若适用)、**不会做的事**(不建【开发】/【测试】、不按标题查重)。**记录需求**须按 [compact-select.md](references/compact-select.md) 给出 14 题字母表,接受压缩答复如 `1a2b3a4d`
4. **用户确认 / 批准 Plan / 「执行」之前**:禁止 apply项目未点选同禁。压缩串须先解析回显再等「执行」。
5. 确认后切回 Agent**同一轮按清单一口气执行到底**,再一次性校验回报;中途缺参才停下。
**例外(可读可不进 Plan** 仅查状态 / 为什么没流转 / 给我方案。
**禁止:** 以「参数已齐」「速度路径」「用户很熟」跳过 Plan「批准计划」若清单未点齐关键参数**PJ 项目**),仍视为未完成门禁。
## 真相源模型
```text
需求状态 = 阶段看板唯一真相
【交付】 = 每需求最多 1 条容器ASSOCIATED→需求
【分析】/【设计】 = TASK_SUB→交付交付「子项」必可见与 ASSOCIATED 同 create 互斥)
【开发】/【测试】 = 不进本 Skill
查重/复用唯一渠道 = 任务编号ONEOS-xx禁止按标题
```
编号权威:需求描述 `## 工作项编号(系统)`(见 [references/workitem-ids.md](references/workitem-ids.md))。
操作顺序:口令显式编号 > 读该区块 > ASSOCIATED/SUB 校验;冲突则停。
## 外置调用(禁止本 Skill 内嵌对方全文)
| 时机 | 调用 |
|---|---|
| 入库清洗聊天/录音 | **`$AutoRDO`**(独立 Skill路径 `AutoRDO/SKILL.md`;不内嵌清洗细则) |
| 设计完成 PRD + 对象存储链接 + 回填【交付】 | **`$oneos-autoprd`AutoPRD**;创建【交付】仍占位,设计完成才灌 MD |
| 人员 / 状态 / 字段 ID项目 catalog 仅缓存 | [assets/runtime-ids.json](assets/runtime-ids.json) |
| **PJ 云效项目点选**(新建必选;实时列表) | [references/project-selection.md](references/project-selection.md) · [scripts/list_projects.py](scripts/list_projects.py) |
| **压缩点选 `1a2b3a4d`**(类型/项目/优先级/标签) | [references/compact-select.md](references/compact-select.md) · [scripts/list_tags.py](scripts/list_tags.py) |
| 阶段日历工时 | [references/work-hours.md](references/work-hours.md) + [assets/cn-workday-calendar.json](assets/cn-workday-calendar.json) + [scripts/workday_hours.py](scripts/workday_hours.py) |
## 路由(按需完整阅读)
| 场景 | 模块 |
|---|---|
| 交付树、关联约定、禁止项 | [references/model.md](references/model.md) |
| 描述双段 · AutoRDO / 占位 / AutoPRD | [references/description-split.md](references/description-split.md) |
| 步骤 05 标准路径 | [references/stage-flow.md](references/stage-flow.md) |
| 无单快轨到待开发 | [references/fast-track.md](references/fast-track.md) |
| 编号直推交棒 | [references/number-push.md](references/number-push.md) |
| 交棒门禁 · 回退最小集 | [references/handoff-and-rollback.md](references/handoff-and-rollback.md) |
| 计划开始/完成 · 阶段日历工时 | [references/work-hours.md](references/work-hours.md) |
| Make 导出 ZIP + 复制截图 | [references/make-export-attach.md](references/make-export-attach.md) |
| 创建迭代 · V主.副.子 · 只挂交付 | [references/sprint.md](references/sprint.md) |
| 口令面 | [references/commands.md](references/commands.md) |
| 记录需求元字段(优先级/标签/提交部门/提交人) | [references/record-meta-fields.md](references/record-meta-fields.md) |
| 云效项目点选 PJ | [references/project-selection.md](references/project-selection.md) |
| 验收清单 · 回报模板 | [references/acceptance.md](references/acceptance.md) |
| 交接契约(开发 Skill 入口) | [references/handoff-contract.md](references/handoff-contract.md) |
| 已验证实写 API · 极速建单 | [references/live-api.md](references/live-api.md) · [scripts/live_create_fast.py](scripts/live_create_fast.py) |
| 2026-07-23 复盘与耗时对比 | [references/live-perf-2026-07-23.md](references/live-perf-2026-07-23.md) |
## 口令速查
```text
记录需求:…;项目=Plan 点选,勿默认);优先级=紧急|高|中|低;标签=…;提交部门=…;提交人=…;推进至=暂不推进|已确认|分析中|设计中|设计完成|待开发|待开发(快轨)
受理确认ONEOS-xx
开始分析ONEOS-xx
开始设计ONEOS-xx交付任务=…;分析任务=…
设计完成ONEOS-xx设计任务=…;原型=…
交棒开发ONEOS-xx交付任务=…
快轨待开发ONEOS-xx
编号直推:分析任务=ONEOS-b / 设计任务=ONEOS-c / 交付任务=ONEOS-a
创建迭代:版本类型=主|副|子;交付任务=ONEOS-a,ONEOS-b,…;名称前缀=…
```
**PJ 项目**:新建前必须从云效实时列表点选(见 [project-selection.md](references/project-selection.md));口令带项目名仅作预填建议。
**压缩点选**:记录需求 Plan 展示 `1.类型 2.项目 3.优先级 4.标签` 字母表;你可回 `1a2b3a4d`(见 [compact-select.md](references/compact-select.md))。标签未命中会自动重拉一次标签候选并重生选项。
**记录需求**元字段(优先级/标签/提交部门/提交人):与压缩点选并用;缺项用字母表补齐。见 [references/record-meta-fields.md](references/record-meta-fields.md)。
后续口令**优先带任务编号**;未带则读「工作项编号(系统)」;仍无则询问;**禁止按标题补全**。
## 本 Skill 终点
交棒完成(需求=待开发;【交付】负责人=何斐)后结束。可一句:「请技术经理使用开发 Skill」。
例外:交棒后「创建迭代并关联交付」仍属 YunxiaoPM。
**明确不做:** 创建【开发】/【测试】、挂仓库、开分支、提测、写用例。
## §0.1 五条补齐(摘要)
1. **交棒占位**:标准路径下交付仍为 `等待设计任务完成后自动填入` 时**允许**交棒,但 Plan 必须勾选风险,回报首行标红。**快轨**有手工/原型时禁止占位(见 [fast-track.md](references/fast-track.md))。
2. **预计工时**:标准路径 = **阶段日历工时**工作日×8**快轨待开发**需求默认预计/实际各 **2**
3. **编号真相源**在需求「工作项编号(系统)」;新建后立即 PATCH 该区块。
4. **无单快轨**:【设计】描述同步需求;计划起止=当日TASK_SUB→交付后补 ASSOCIATED→需求【交付】描述手工同步或 AutoPRD交付/设计与需求同标签;设计当日完成态。
5. **描述双段**不互相覆盖;迭代**只挂【交付】**(需求不挂迭代);回退重做设计则**新开设计编号**,交付计划开始不改。
细则见各 references。

View File

@@ -0,0 +1,49 @@
# 验收清单与回报
## apply 后必须自检
| # | 项 | 通过标准 |
|---|---|---|
| 1 | 需求编号 | 回报含 ONEOS-xx |
| 2 | 任务编号 | 交付/分析/设计凡新建或操作均回报编号;禁止只报标题 |
| 3 | 编号区块 | 需求「工作项编号(系统)」与实际一致 |
| 4 | ASSOCIATED | **仅交付**详情关联项可见需求(`createWorkitemRelationInfo=ASSOCIATED`;禁止 PARENT 冒充) |
| 5 | SUB | **必过**:分析/设计 create 用 `TASK_SUB→交付`(含 `parent`+`parentIdentifier`交付「子项」tab 须可见。与 ASSOCIATED 同 create 互斥,阶段任务关联项可空(见 live-api.md |
| 6 | 计划开始 | 未误覆盖已有值 |
| 7 | 阶段日历工时 | 有计划完成时已写入;脚注存在;回报用语正确 |
| 8 | 交棒 | 需求=待开发;交付负责人=何斐(交棒场景) |
| 9 | 占位风险 | 交付仍占位时首行标红 |
| 10 | 负向 | 本轮**无**【开发】/【测试】任务;未按标题查重 |
设计完成额外AutoPRD 段已写交付非占位除非失败停下ZIP+截图已挂或已列出缺项。
迭代额外:只挂【交付】(需求不挂);版本号符合递增规则。
## 回报模板(精简)
```text
【YunxiaoPMapp】
风险:(若有占位交棒则首行标红)
需求ONEOS-xx | 状态=…
交付ONEOS-a | 负责人=…
分析ONEOS-b | …(无则写无)
设计ONEOS-c | …(无则写无)
阶段日历工时:分析 Hh / 设计 Hh若本轮写入
附件:…(若本轮)
迭代:…(若本轮)
下一步:请技术经理使用开发 Skill交棒后
```
## 适合全自动 vs 人工门禁
| 适合全自动 | 建议半自动/人工门禁 |
|---|---|
| 建单、打标签、挂迭代、写描述、建交付树、改状态、交棒负责人、幂等查重 | 受理(已确认)、是否快轨、设计完成是否真可开发、跨需求优先级与迭代容量、回退与取消 |
## 实写性能2026-07-23 复盘)
| 项 | 要求 |
|---|---|
| 改状态 | 只用 `status/transit`(见 [live-api.md](live-api.md) |
| 改【交付】负责人 | 只用 `PATCH …/{id}` + `propertyKey=assignedTo` |
| 极速复测 | `scripts/live_create_fast.py`;默认不开浏览器 |

View File

@@ -0,0 +1,4 @@
interface:
display_name: "需求任务"
short_description: "云效:压缩点选记录需求→分析/设计→交棒待开发→挂迭代"
default_prompt: "按需求任务(/YunxiaoPM处理先 Plan 出压缩点选字母表并确认项目,用户回 1a2b3a4d 与「执行」后再 apply。"

View File

@@ -0,0 +1,95 @@
{
"schema_version": 1,
"timezone": "Asia/Shanghai",
"note": "法定放假日 holidays国务院公布的周末调休补班日 workdays_on_weekend。缺年则禁止静默按仅去周末计算。",
"source": {
"2025": "国办发明电202412号 https://www.gov.cn/zhengce/zhengceku/202411/content_6986383.htm",
"2026": "国办发明电20257号 https://www.gov.cn/zhengce/content/202511/content_7047090.htm"
},
"years": {
"2025": {
"holidays": [
"2025-01-01",
"2025-01-28",
"2025-01-29",
"2025-01-30",
"2025-01-31",
"2025-02-01",
"2025-02-02",
"2025-02-03",
"2025-02-04",
"2025-04-04",
"2025-04-05",
"2025-04-06",
"2025-05-01",
"2025-05-02",
"2025-05-03",
"2025-05-04",
"2025-05-05",
"2025-05-31",
"2025-06-01",
"2025-06-02",
"2025-10-01",
"2025-10-02",
"2025-10-03",
"2025-10-04",
"2025-10-05",
"2025-10-06",
"2025-10-07",
"2025-10-08"
],
"workdays_on_weekend": [
"2025-01-26",
"2025-02-08",
"2025-04-27",
"2025-09-28",
"2025-10-11"
]
},
"2026": {
"holidays": [
"2026-01-01",
"2026-01-02",
"2026-01-03",
"2026-02-15",
"2026-02-16",
"2026-02-17",
"2026-02-18",
"2026-02-19",
"2026-02-20",
"2026-02-21",
"2026-02-22",
"2026-02-23",
"2026-04-04",
"2026-04-05",
"2026-04-06",
"2026-05-01",
"2026-05-02",
"2026-05-03",
"2026-05-04",
"2026-05-05",
"2026-06-19",
"2026-06-20",
"2026-06-21",
"2026-09-25",
"2026-09-26",
"2026-09-27",
"2026-10-01",
"2026-10-02",
"2026-10-03",
"2026-10-04",
"2026-10-05",
"2026-10-06",
"2026-10-07"
],
"workdays_on_weekend": [
"2026-01-04",
"2026-02-14",
"2026-02-28",
"2026-05-09",
"2026-09-20",
"2026-10-10"
]
}
}
}

View File

@@ -0,0 +1,221 @@
{
"schema_version": 1,
"skill": "YunxiaoPM",
"verified_at": "2026-07-25",
"note": "YunxiaoPM constants. Project space MUST be user-selected (PJ gate); project.spaceIdentifier is last-known cache only — never auto-apply. See references/project-selection.md.",
"project": {
"selection_mode": "user_pick_required",
"name": null,
"name_aliases": [
"01_ONEOS",
"ONEOS",
"统一运营管理平台",
"统一运营管理平台PC端",
"统一运营管理平台 PC 端"
],
"spaceIdentifier": null,
"customCode": null,
"spaceType": "Project",
"organizationIdentifier": "697c54a19df7fdfa65466405",
"default_sprint_name_prefix": "统一运营管理平台PC端",
"list_api": "GET /projex/api/workspace/project/search/list",
"last_selected": {
"name": "01_ONEOS",
"spaceIdentifier": "1280be963a5a2cc126a4118dca",
"customCode": "ONEOS",
"note": "历史常用项;仅作预填建议,禁止未点选即使用"
},
"refreshed_at": "2026-07-25"
},
"projects_catalog": [
{
"name": "05_羚牛碳资产平台",
"identifier": "ff104a3bce09463da136a97999",
"customCode": "CARBON"
},
{
"name": "06_对外客户项目",
"identifier": "baca8b4d676c5af67e475caec0",
"customCode": "CUST"
},
{
"name": "07_LNBOX",
"identifier": "35e1e915a052379bbdfb993aac",
"customCode": "LNBOX"
},
{
"name": "04_AI应用",
"identifier": "d9002ea72c6c3a1a97b02be750",
"customCode": "AIAPP"
},
{
"name": "03_数据中台",
"identifier": "a801cef5c9a68fa051c07432c7",
"customCode": "DATA"
},
{
"name": "02_小羚羚APP",
"identifier": "db771a2cca07bed43b369af077",
"customCode": "XLLAPP"
},
{
"name": "01_ONEOS",
"identifier": "1280be963a5a2cc126a4118dca",
"customCode": "ONEOS"
},
{
"name": "敏捷研发示例项目",
"identifier": "65eca0c2e16a23939081e19e14",
"customCode": "DEMO"
}
],
"people": {
"wangmian": {
"displayName": "王冕",
"identifier": "6811df000601d2fea60144a9",
"role": "产品创建人/默认负责人"
},
"hefei": {
"displayName": "何斐",
"identifier": "695f0400562f09713f9c3a93",
"role": "待开发交棒【交付】负责人"
}
},
"tags": {
"故障管理": "ceb526a7343995577645317e9a",
"还车应结款": "4204960ce658c94b17abb7c5f6",
"工作台": "b62d21beac55c0b43389915eab",
"交车管理": "b6947b5aca82a8c759612ba039",
"合同管理": "23873be81931cb0dc1bf87a456",
"安全培训": "76988b5f73ef515de5930d59b9",
"证照管理": "11f4c2ec65901a8f3199c81706",
"还车管理": "1e0fce2d6929ff4ac13b310e97"
},
"status": {
"req": {
"待处理": "100005",
"已确认": "32",
"分析中": "154395",
"设计中": "156603",
"设计完成": "307012",
"待开发": "1582fc929d429111b925309493"
},
"task": {
"待处理": "100005",
"已完成": "100014"
},
"transit_api": "POST /projex/api/workitem/workitem/{id}/status/transit",
"fast_handoff_hops": [
"设计完成",
"待开发"
],
"note": "见 references/live-api.md禁止再用 updateStatus"
},
"workitem_types": {
"product_req": {
"name": "产品类需求",
"category": "Req",
"identifier": "9uy29901re573f561d69jn40"
},
"task": {
"name": "任务",
"category": "Task",
"identifier": "ba102e46bc6a8483d9b7f25c"
}
},
"priority": {
"紧急": "646004e97f54bb77fec7b455df",
"高": "95b89e0a524d9693e1f335ffe5",
"中": "fa155d1214f9f8db222d39db3b",
"低": "92924feff9c1085891e7511872"
},
"fields": {
"plan_start": {
"fieldIdentifier": "79",
"name": "计划开始时间",
"value_shape": "YYYY-MM-DD HH:mm:ss China wall time preferred; epoch ms string also accepted",
"example": "2026-07-27 12:00:00",
"update_api": "POST /projex/api/workitem/workitem/field/value/{workitemId} form fieldValueList=JSON"
},
"plan_end": {
"fieldIdentifier": "80",
"name": "计划完成时间",
"value_shape": "YYYY-MM-DD HH:mm:ss or epoch ms string",
"update_api": "POST /projex/api/workitem/workitem/field/value/{workitemId} form fieldValueList=JSON"
},
"estimated_hours": {
"fieldIdentifier": "101586",
"name": "预计工时",
"note": "不可直接改字段;须工时预估登记",
"create_api": "POST /projex/api/workitem/workitem/time/estimate body spentTime,type,recordUserIdentifier,workitemIdentifier",
"delete_api": "DELETE /projex/api/workitem/workitem/time/estimate/{workitemId}/{estimateId}",
"list_api": "GET /projex/api/workitem/workitem/time/estimate/list?workitemIdentifier="
},
"actual_hours": {
"name": "实际工时",
"note": "快轨待开发默认 2",
"create_api": "POST /projex/api/workitem/workitem/time body actualTime,type,recordUserIdentifier,workitemIdentifier,gmtStart,gmtEnd (epoch ms string)",
"list_api": "GET /projex/api/workitem/workitem/time/list?workitemIdentifier=",
"fast_track_default": 2,
"verified_at": "2026-07-27",
"verified_on": "ONEOS-293"
},
"fast_track": {
"req_estimated_hours": 2,
"req_actual_hours": 2,
"design_plan_start_end_same_day": true,
"design_description": "copy_req_document",
"delivery_description": "manual_sync_or_autoprd",
"delivery_design_same_tags_as_req": true,
"design_associated_to_req_after_task_sub": true,
"document_update_api": "PATCH /projex/api/workitem/workitem/{id}/document {content,formatType:RICHTEXT}"
},
"submit_department": {
"fieldIdentifier": "3132597a9718d1c282b7ba5a0c",
"name": "提交部门",
"format": "string input",
"update_api": "POST /projex/api/workitem/workitem/field/value/{workitemId} form fieldValueList=JSON",
"verified_at": "2026-07-27",
"verified_on": "ONEOS-293"
},
"submitter": {
"fieldIdentifier": "9e01269e96f91fbb97d36bf5b3",
"name": "提交人",
"format": "string input",
"update_api": "POST /projex/api/workitem/workitem/field/value/{workitemId} form fieldValueList=JSON",
"verified_at": "2026-07-27",
"verified_on": "ONEOS-293"
},
"tag": {
"fieldIdentifier": "tag",
"name": "标签",
"propertyKey": "tag"
}
},
"assignee_rules": {
"待开发_交付任务": "hefei",
"分析中_交付与分析": "creator",
"设计中_设计": "creator"
},
"relation": {
"delivery_to_req": "ASSOCIATED",
"stage_to_delivery": "TASK_SUB",
"create_field": "createWorkitemRelationInfo",
"forbid": [
"PARENT_as_关联项",
"ASSOCIATED_only_for_stage_tasks_without_TASK_SUB"
],
"note": "交付必须 ASSOCIATED→需求。分析/设计默认 TASK_SUB→交付子项 tab。二者同 create 互斥。见 references/live-api.md"
},
"delivery_placeholder": "等待设计任务完成后自动填入",
"task_title_prefixes": {
"delivery": "【交付】",
"analysis": "【分析】",
"design": "【设计】"
},
"publish_url": {
"shape": "{baseUrl}/{prototype-id}/index.html",
"forbid_prototypes_prefix": true,
"require_index_html": true
}
}

View File

@@ -0,0 +1,317 @@
# YunxiaoPMapp 实现原理说明
> 供**开发部门**设计 / 制作「开发侧 Skill」暂称 **YunxiaoDevapp**)时对齐契约。
> 本文描述产品侧 Skill **YunxiaoPMapp** 的模型、边界、数据契约与交棒接口;**不是**对 `yunxiao-requirement-lifecycle` 的兼容说明。
> 技能包https://github.com/15810879921-coder/oneos-pm-skills · `skills/YunxiaoPMapp/`
> 文档版本2026-07-24
---
## 1. 为什么拆成两个 Skill
| | YunxiaoPMapp产品 | 开发 Skill待建 |
|---|---|---|
| 职责 | 需求从「待处理」到「待开发」交棒 | 从「待开发」到开发完成 / 提测前 |
| 任务类型 | 【交付】【分析】【设计】 | 【开发】(可多条)、可选挂仓库/分支 |
| 负责人交接 | 交棒时【交付】→ **何斐** | 拆【开发】子任务并指派研发 |
| 明确不做 | 建【开发】/【测试】、开分支、提测 | 不建【分析】/【设计】、不改 AutoRDO 段 |
**硬规则:** 两个 Skill **禁止互相 include / fork 全文**;只认本文第 6 章「交棒契约」。产品会话与开发会话不要同时挂载旧 `yunxiao-requirement-lifecycle`,避免双建任务树。
---
## 2. 核心真相源(必须先统一)
```text
需求状态 = 阶段看板唯一真相(分析中 / 设计中 / 待开发 …)
【交付】任务 = 每需求最多 1 条「交付容器」
【分析】【设计】 = 【交付】下的阶段子项(产品侧建)
【开发】【测试】 = 开发 / 测试 Skill 建(产品侧永不创建)
查重 / 复用 = 只认云效任务编号 ONEOS-xx禁止按标题
```
### 2.1 关系模型(云效)
```mermaid
flowchart TB
Req["产品类需求 ONEOS-R"]
DEL["【交付】ONEOS-a"]
AN["【分析】ONEOS-b"]
DE["【设计】ONEOS-c"]
DEV["【开发】… 开发 Skill"]
TEST["【测试】… 测试 Skill"]
DEL -->|"ASSOCIATED 关联项"| REQ
AN -->|"TASK_SUB 子项"| DEL
DE -->|"TASK_SUB 子项"| DEL
DEV -.->|"建议SUB→交付 或 ASSOCIATED→需求+交付"| DEL
TEST -.->|"测试 Skill"| REQ
```
| 关系 | 谁写 | 验收 |
|---|---|---|
| `ASSOCIATED` | **仅【交付】→ 需求** | 交付详情「关联项」可见需求 |
| `TASK_SUB` | 【分析】/【设计】→【交付】 | 交付详情「子项」可见阶段任务 |
| (开发侧建议) | 【开发】→【交付】或需求 | 由开发 Skill 自定,但须可编号查重 |
**踩坑(已复现):** 对分析/设计只写 `parentIdentifier` + `ASSOCIATED→需求`交付「子项」会为空。正确create 时 `createWorkitemRelationInfo=TASK_SUB` + `parent`/`parentIdentifier`=交付。同一 create **只能**带一条关系ASSOCIATED 与 TASK_SUB 互斥。
### 2.2 标题只是展示
- 形式:`【交付】`/`【分析】`/`【设计】` + 需求标题
- **不参与查重**;改标题不影响幂等
- 开发侧【开发】标题建议 `【开发】` + 范围简述,同样**只认编号**
---
## 3. 编号权威源
需求描述固定区块(机器可解析):
```markdown
## 工作项编号(系统)
- 交付ONEOS-a
- 分析ONEOS-b无则写无
- 设计ONEOS-c无则写无
```
| 规则 | 说明 |
|---|---|
| 新建后立即 PATCH | 只改本区块,不动 AutoRDO / AutoPRD |
| 操作顺序 | 口令显式编号 > 读本区块 > ASSOCIATED/SUB 反查 |
| 冲突 | 停下人工;**禁止按标题猜** |
| 多交付编号 | 停止并列号请人合并 |
**开发 Skill 入口建议:** 口令必须带 `需求=ONEOS-R` + `交付任务=ONEOS-a`;缺则读本区块;仍无则询问。
---
## 4. 需求描述双段(产品写 · 开发只读)
```markdown
## 原始诉求AutoRDO
(聊天/录音清洗稿;设计完成也不删)
## 产品说明AutoPRD
(设计完成才灌满;含对象存储预览链接)
## 工作项编号(系统)
- 交付 / 分析 / 设计
```
| 段 | 谁写 | 开发侧用法 |
|---|---|---|
| AutoRDO | `$AutoRDO` → 产品记需求时 | 占位交棒时**唯一可信**业务原文 |
| AutoPRD | `$oneos-autoprd` → 设计完成时 | 正式需求说明;缺则有权要求产品补设计完成 |
| 编号区块 | YunxiaoPMapp | 定位交付树 |
**【交付】描述:** 设计完成前固定占位文案 `等待设计任务完成后自动填入`;设计完成后替换为 AutoPRD 正文。
**允许占位交棒**,但产品回报必须标红风险;开发 Skill 应检测占位并提示「材料不齐,可凭 AutoRDO 开工或退回补设计」。
对象存储预览 URL 形态:`{baseUrl}/{prototype-id}/index.html`(禁止加 `prototypes/` 前缀、禁止去掉 `index.html`)。
---
## 5. 产品侧阶段状态机0→5
```text
0 创建需求(待处理) ─AutoRDO→ 仅需求,不建任务
1 受理确认(已确认) 仍不建任务
2 分析中 建【交付】+【分析】
3 设计中 建【设计】;收口【分析】计划完成
4 设计完成 收口【设计】AutoPRD+附件;灌【交付】描述
5 待开发交棒 ★ 需求→待开发;【交付】负责人→何斐
★ = YunxiaoPMapp 终点 / 开发 Skill 起点
```
### 5.1 各步要点(开发需知道的副作用)
| 步骤 | 需求状态 | 任务侧关键动作 |
|---|---|---|
| 2 分析中 | 分析中 | 新建【交付】ASSOCIATED→需求描述=占位;计划开始仅空写当日且**此后不可改**新建【分析】TASK_SUB→交付 |
| 3 设计中 | 设计中 | 新建【设计】;【分析】计划完成=当日 + 阶段日历工时 |
| 4 设计完成 | 设计完成 | 【设计】完成态;需求+交付挂 ZIP/截图;交付描述换正式说明 |
| 5 交棒 | **待开发** | **只改交付负责人→何斐**;不新建分析/设计;不写交付计划完成 |
### 5.2 两条旁路(仍交到同一终点)
| 路径 | 前提 | 行为 |
|---|---|---|
| **无单快轨** | 尚无分析路径 / 明确跳过分析 | 待开发 + 新建交付+设计(设计当日收口);**不建分析**;默认可不跑 AutoPRD |
| **编号直推** | 已有分析/设计**编号** | 收口空计划完成 → 待开发 + 交付交棒何斐;不新建冗余单 |
---
## 6. 交棒契约(开发 Skill 必须实现)
### 6.1 入口条件(产品已完成)
```text
需求状态 = 待开发
【交付】任务编号 = ONEOS-a唯一
【交付】负责人 = 何斐
【交付】ASSOCIATED → 该需求
可选:分析/设计编号在「工作项编号(系统)」中
```
### 6.2 开发 Skill 建议入口口令
```text
接手开发:需求=ONEOS-R交付任务=ONEOS-a
拆分开发:交付任务=ONEOS-a范围=前端|后端|…;负责人=…
开始开发:开发任务=ONEOS-d
开发完成:开发任务=ONEOS-d
```
### 6.3 开发 Skill 建议职责边界
| 应做 | 不应做 |
|---|---|
| 在【交付】下建一条或多条【开发】(编号幂等) | 再建【分析】/【设计】或第二套【交付】 |
| 正式关联:建议 SUB→交付或同时 ASSOCIATED→需求 | 只按标题「【开发】xxx」查重 |
| 挂仓库 / 分支 / MR按你们 Codeup 规范) | 覆盖需求 AutoRDO 段 |
| 改【开发】状态与负责人 | 擅自把需求从待开发退回(除非产品授权回退口令) |
| 检测交付描述是否仍为占位并提示 | 假装 AutoPRD 已齐全 |
| 全部【开发】完成后通知测试 Skill / 建【测试】 | 在产品 Skill 会话里混跑 |
### 6.4 共享常量(可引用,勿整包加载)
路径均在 `skills/YunxiaoPMapp/assets/`
| 文件 | 内容 |
|---|---|
| `runtime-ids.json` | 项目 spaceId、何斐 ID、工作项类型、状态 transit、字段 79/80 |
| `cn-workday-calendar.json` | 法定节假日 / 调休(阶段日历工时) |
开发侧可复制一份到自己的 `assets/`,或只读引用短路径;**不要**把 YunxiaoPMapp 的 references 全文 include 进开发 Skill。
---
## 7. 计划时间与「阶段日历工时」
产品侧口径(开发侧若写计划时间建议对齐语义):
| 对象 | 计划开始 | 计划完成 | 预计工时 |
|---|---|---|---|
| 【交付】 | 首次分析中空则写当日,**永不覆盖** | 产品侧不写(留给上线) | 一般不推全周期 |
| 【分析】【设计】 | 创建时空则写当日,**永不覆盖** | 阶段收口日 | `工作日×8` |
```text
预计工时 = 阶段日历工时Lead Time≠ 人力投入人天
算法起止日含首尾扣周末与法定假计入调休补班×8 小时
禁止:(结束−开始+1×8 的自然日算法
```
脚注固定:`【系统】预计工时=阶段日历工时工作日×8非人力投入预估`
脚本:`scripts/workday_hours.py`
**建议:** 开发 Skill 若给【开发】写预计工时,在文档中明确是「人力投入预估」还是「阶段日历工时」,避免与产品侧混称。
---
## 8. Agent 运行时原理(制作 Skill 时照抄模式)
### 8.1 Plan 门禁
凡写云效:`SwitchMode → plan` → 用户确认 → 一口气 apply → 一次校验回报。
禁止用「参数已齐 / 速度路径」跳过 Plan。
### 8.2 模块化路由
`SKILL.md` 只做路由与门禁;细则在 `references/*.md`;常量在 `assets/`;脚本在 `scripts/`
外置能力AutoRDO、AutoPRD**调用对方 Skill**,不内嵌对方全文。
### 8.3 幂等
```text
幂等键 = 项目 + 需求编号 + 任务类型角色(交付/分析/设计/开发…)+ 已登记任务编号
命中编号 → 复用并补缺字段;禁止新建第二条同角色主容器(交付唯一)
```
### 8.4 验收与回报
每次 apply 后自检(产品侧清单见 `references/acceptance.md`)。开发侧建议至少回报:
```text
【YunxiaoDevapp】
需求ONEOS-R | 状态=待开发|开发中|…
交付ONEOS-a | 负责人=…
开发ONEOS-d1, ONEOS-d2 | …
仓库/分支:…
下一步:…
```
### 8.5 已验证写路径(可复用思路)
| 动作 | 约定(见 live-api.md |
|---|---|
| 改状态 | `POST …/status/transit`(勿用错误 updateStatus |
| 改负责人 | `PATCH …/{id}` + `propertyKey=assignedTo` |
| 建单关系 | create 带 `createWorkitemRelationInfo` |
| 极速复测 | `scripts/live_create_fast.py`(可参考,开发侧另写自己的脚本) |
---
## 9. 回退最小集(开发需配合)
| 场景 | 产品侧规则 | 开发侧注意 |
|---|---|---|
| 待开发 → 退回设计中 | 需求回退;交付负责人可改回产品;**交付计划开始不改**;重做设计则**新开设计编号** | 已建【开发】是否取消 / 暂停由开发 Skill 定义;勿静默删编号 |
| 设计完成后需求大变 | Plan 问是否回退;更新 AutoPRDAutoRDO 保留+变更纪要 | 勿覆盖 AutoRDO |
| 取消需求 | 任务标取消;不删编号区块 | 同步取消未完成【开发】 |
---
## 10. 建议的「YunxiaoDevapp」目录骨架
```text
YunxiaoDevapp/
├── SKILL.md # 门禁 + 路由 + 边界(引用本文契约,不 include PMapp
├── assets/
│ └── runtime-ids.json # 可从 PMapp 复制/裁剪
├── references/
│ ├── model.md # 【开发】与交付/需求的关系约定
│ ├── handoff-intake.md # 认交付编号 + 占位检测
│ ├── split-dev-tasks.md # 拆前端/后端多【开发】
│ ├── codeup.md # 分支 / MR / 关联
│ ├── commands.md # 口令面
│ └── acceptance.md
└── scripts/ # 可选极速 API
```
`SKILL.md` description 建议写明:触发词「接手开发 / 拆分开发 / 开始开发」;**Does NOT create 【分析】/【设计】**;入口条件需求=待开发。
---
## 11. 对照检查表(开发 Skill 评审用)
- [ ] 是否只认「需求编号 + 交付任务编号」,禁止标题查重
- [ ] 是否拒绝创建第二套【交付】或【分析】【设计】
- [ ] 占位交棒时是否提示风险且不假装 PRD 齐全
- [ ] 【开发】是否可编号幂等、可挂到交付树
- [ ] 是否与 YunxiaoPMapp **会话隔离**(不同 Skill、不同口令
- [ ] 计划开始字段是否遵守「已有值不覆盖」(若沿用同一字段)
- [ ] 提测 / 【测试】是否交给测试 Skill本包边界清晰
---
## 12. 相关文档索引
| 主题 | 路径(仓库内) |
|---|---|
| Skill 入口 | `skills/YunxiaoPMapp/SKILL.md` |
| 交付树模型 | `skills/YunxiaoPMapp/references/model.md` |
| 交棒契约 | `skills/YunxiaoPMapp/references/handoff-contract.md` |
| 标准路径 05 | `skills/YunxiaoPMapp/references/stage-flow.md` |
| 交棒门禁 / 回退 | `skills/YunxiaoPMapp/references/handoff-and-rollback.md` |
| 描述双段 | `skills/YunxiaoPMapp/references/description-split.md` |
| 编号区块 | `skills/YunxiaoPMapp/references/workitem-ids.md` |
| 快轨 / 编号直推 | `references/fast-track.md` · `number-push.md` |
| 工时算法 | `references/work-hours.md` |
| 实写 API | `references/live-api.md` |
安装产品 Skill
```bash
npx skills add 15810879921-coder/oneos-pm-skills --skill YunxiaoPMapp -a cursor -g -y
```

View File

@@ -0,0 +1,179 @@
# 产品部流转YunxiaoPMapp到交棒为止
> 用途:先把**产品部**在云效上的工作流转说清楚;开发 / 测试 / 发版不在本 Skill 内,仅在文末标出交接点。
> 依据:`references/stage-flow.md` · `model.md` · `fast-track.md` · `handoff-contract.md`
> 日期2026-07-24
---
## 1. 产品部管到哪里
```text
产品部YunxiaoPMapp终点 = 需求状态「待开发」+【交付】负责人「何斐」
之后 = 请技术经理使用开发 Skill不建【开发】/【测试】)
```
| 谁 | 做什么 | 不做什么 |
|---|---|---|
| 产品 / YunxiaoPMapp | 建需求、打标签、建【交付】【分析】【设计】、推进状态、设计完成灌 AutoPRD、交棒 | 建【开发】【测试】、开分支、提测、发版 |
| 技术经理(接手) | 从「待开发」起拆开发 | 不改写 AutoRDO不新建第二套【交付】 |
---
## 2. 总览流程图(标准路径)
```mermaid
flowchart TB
subgraph inputs [材料入口]
Chat[聊天/录音/口述]
AutoRDO["$AutoRDO 清洗"]
Proto[原型页 Make]
end
subgraph pm [产品部 · YunxiaoPMapp]
S0["0 创建需求\n状态=待处理\n只写 AutoRDO\n不建任务"]
S1["1 受理确认\n状态=已确认\n仍不建任务"]
S2["2 分析中\n建【交付】+【分析】"]
S3["3 设计中\n建【设计】\n收口【分析】"]
S4["4 设计完成\n收口【设计】\nAutoPRD+附件\n灌【交付】描述"]
S5["5 待开发交棒\n交付负责人→何斐\n★ 产品终点"]
end
subgraph after [产品之后 · 不在本 Skill]
Dev["开发 Skill\n拆【开发】…"]
Test["测试 Skill"]
Rel["发版"]
end
Chat --> AutoRDO --> S0
Proto -.-> S4
S0 --> S1 --> S2 --> S3 --> S4 --> S5
S5 -->|"交棒契约:需求编号+交付编号"| Dev
Dev --> Test --> Rel
```
---
## 3. 各步说明(产品侧)
| 步骤 | 需求状态 | 云效任务动作 | 描述写什么 | 口令示例 |
|---|---|---|---|---|
| 0 创建 | 待处理 | 无 | `## 原始诉求AutoRDO`;编号区块待建 | `记录需求:…;推进至=暂不推进` |
| 1 受理 | 已确认 | 仍无 | 不动 | `受理确认ONEOS-xx` |
| 2 分析中 | 分析中 | 新建【交付】ASSOCIATED→需求新建【分析】TASK_SUB→交付 | 交付=占位文案 | `开始分析ONEOS-xx` |
| 3 设计中 | 设计中 | 新建【设计】TASK_SUB→交付分析计划完成=当日+阶段日历工时 | — | `开始设计ONEOS-xx交付=…;分析=…` |
| 4 设计完成 | 设计完成 | 设计完成态;需求+交付挂 ZIP/截图;交付描述换 AutoPRD | `$oneos-autoprd``## 产品说明` | `设计完成ONEOS-xx设计=…;原型=…` |
| 5 交棒 | **待开发** | **只**把【交付】负责人改为何斐 | 若仍占位须标红风险 | `交棒开发ONEOS-xx交付=…` |
**编号权威:** 需求描述 `## 工作项编号(系统)`(交付 / 分析 / 设计)。后续口令优先带 `ONEOS-xx`,禁止按标题查重。
---
## 4. 交付树(产品建出来的结构)
```mermaid
flowchart TB
REQ["产品类需求 ONEOS-R\n状态=阶段真相"]
DEL["【交付】ONEOS-a\nASSOCIATED→需求"]
AN["【分析】ONEOS-b"]
DE["【设计】ONEOS-c"]
DEL -->|"关联项 ASSOCIATED"| REQ
AN -->|"子项 TASK_SUB"| DEL
DE -->|"子项 TASK_SUB"| DEL
```
验收口诀:
- 打开【交付】→「关联项」能看到需求
- 打开【交付】→「子项」能看到分析/设计(必须 `TASK_SUB`,不能只写 parentIdentifier
---
## 5. 两条旁路(仍交到同一终点)
```mermaid
flowchart LR
subgraph standard [标准]
A1[分析中] --> A2[设计中] --> A3[设计完成] --> A4[待开发]
end
subgraph fast [无单快轨]
B1[待处理/已确认等] --> B2["待开发\n建交付+设计当日收口\n不建分析"]
end
subgraph push [编号直推]
C1[已有分析/设计编号] --> C2[收口空计划完成] --> C3[待开发+交棒何斐]
end
```
| 路径 | 何时用 | 注意 |
|---|---|---|
| 标准 0→5 | 正常产品节奏 | 设计完成才灌 AutoPRD |
| 快轨 | 明确跳过分析、急交棒 | 默认可不跑 AutoPRD交付常占位→回报标红 |
| 编号直推 | 树上已有阶段任务编号 | 不新建冗余单;只认编号 |
---
## 6. 产品部人机边界Plan 门禁)
```text
凡写云效Plan 对齐 → 人确认 → 一口气 apply → 一次校验回报
```
| 适合全自动 | 建议人点一下 |
|---|---|
| 建单、打标、建树、改状态、交棒负责人、幂等复用 | 优先级、标签、是否快轨、设计是否真可开发、占位是否接受交棒 |
---
## 7. 交棒给下游时交出什么
产品回报至少包含:
```text
【YunxiaoPMapp】
风险:(占位交棒则首行标红)
需求ONEOS-R | 状态=待开发
交付ONEOS-a | 负责人=何斐
分析ONEOS-b 或 无
设计ONEOS-c 或 快轨占位说明
下一步:请技术经理使用开发 Skill
```
下游入口条件见 `references/handoff-contract.md`:认 **需求编号 + 交付任务编号**
---
## 8. 和全链路的关系(本文件边界)
```mermaid
flowchart LR
PM[产品部本文] --> Handoff[待开发交棒]
Handoff --> Dev[开发]
Dev --> QA[测试]
QA --> Rel[发版]
```
全链路(含谢佳伟 / 时生亮)见仓库原型:
`src/prototypes/yunxiao-pipeline-handbook/`
产品 Skill 对接开发说明:
`docs-YunxiaoPMapp-实现原理-开发Skill对接.md`
---
## 9. 相关 references
| 主题 | 路径 |
|---|---|
| 标准 05 | `references/stage-flow.md` |
| 交付树 / 子项 | `references/model.md` |
| 快轨 | `references/fast-track.md` |
| 编号直推 | `references/number-push.md` |
| 交棒门禁 | `references/handoff-and-rollback.md` |
| 交棒契约 | `references/handoff-contract.md` |
| 口令 | `references/commands.md` |
---
## 延伸阅读
- 四角色泳道(产品/开发/测试/发版):`docs-四角色泳道流程图.md`
- 开发侧草案:`docs-开发侧流转草案.md`

View File

@@ -0,0 +1,318 @@
# 全流程分步说明:产品 → 开发 → 测试 → 发版
> 把整条链路拆成**按顺序执行的步骤**,每步说清:谁做、做什么、云效上变成什么、下一步谁接。
> 读完应能照着口令/动作走完一轮(标准路径)。
> 日期2026-07-24
---
## 先记住三件事
1. **需求状态 = 阶段真相**
看需求状态就知道现在卡在哪一段(分析中 / 待开发 / 开发中 / 待测试…)。
2. **每条需求只有 1 个【交付】容器**
分析、设计、开发、测试都挂在这个交付下面(子项),不要再建第二个【交付】。
3. **编号说话,不靠标题查**
口令尽量带 `ONEOS-xx`;改标题不影响关联。
```text
需求(状态主轴)
└─【交付】(容器,关联到需求)
├─【分析】【设计】 ← 产品建
├─【开发】… ← 开发建
└─【测试】 ← 开发提测时建
【发版】另建,挂迭代 + 范围内需求
```
---
## 总步骤一览(共 18 步)
| 阶段 | 步骤 | 一句话 |
|---|---|---|
| **产品** | 16 | 从记诉求到交棒给何斐 |
| **开发** | 712 | 从拆任务到提测 |
| **测试** | 1315 | 从接测到测试完成 |
| **发版** | 1617 | 从建发版到发布结果 |
| **收口** | 18 | 产品验收关闭 |
---
## 阶段 A产品步骤 16
### 步骤 1记录需求
| | |
|---|---|
| **谁** | 产品 / AIYunxiaoPMapp |
| **做什么** | 把聊天、录音、口述先洗成 AutoRDO再建一条**产品类需求** |
| **需求状态** | **待处理** |
| **云效任务** | 不建任何任务 |
| **描述里写** | `## 原始诉求AutoRDO`;编号区先空着 |
| **口令例** | `记录需求:…;推进至=暂不推进` |
| **为什么** | 先落盘,避免口头需求丢;还没确认值不值得做 |
---
### 步骤 2受理确认
| | |
|---|---|
| **谁** | 产品 |
| **做什么** | 确认要做:定优先级、打标签(从云效标签里点选) |
| **需求状态** | **已确认** |
| **云效任务** | 仍不建任务 |
| **口令例** | `受理确认ONEOS-xx` |
| **为什么** | 和「还没想清楚」的待处理分开;确认后才进分析/设计 |
---
### 步骤 3开始分析
| | |
|---|---|
| **谁** | 产品 / AI |
| **做什么** | ① 建 **【交付】**(整条需求的唯一容器,关联到需求)② 建 **【分析】**(挂在交付**子项**下) |
| **需求状态** | **分析中** |
| **云效任务** | 【交付】+【分析】 |
| **口令例** | `开始分析ONEOS-xx` |
| **验收** | 打开【交付】→「关联项」有需求;「子项」有【分析】 |
| **为什么** | 分析要有落点;后续设计/开发/测试都挂同一棵树 |
---
### 步骤 4开始设计
| | |
|---|---|
| **谁** | 产品 / AI |
| **做什么** | 建 **【设计】**(子项挂交付);收口【分析】计划时间 |
| **需求状态** | **设计中** |
| **云效任务** | 新增【设计】 |
| **口令例** | `开始设计ONEOS-xx交付=…;分析=…` |
| **为什么** | 进入原型/方案设计;分析阶段收口 |
---
### 步骤 5设计完成
| | |
|---|---|
| **谁** | 产品 / AI |
| **做什么** | 收口【设计】;跑 AutoPRD把**产品说明**灌进【交付】描述;挂原型 ZIP/截图等附件 |
| **需求状态** | **设计完成** |
| **口令例** | `设计完成ONEOS-xx设计=…;原型=…` |
| **为什么** | 开发接手时看的是【交付】里的产品说明,不是聊天记录 |
---
### 步骤 6交棒开发产品终点
| | |
|---|---|
| **谁** | 产品 / AI |
| **做什么** | 需求改为待开发;**【交付】负责人改为何斐**(不新建开发/测试任务) |
| **需求状态** | **待开发** ★ |
| **交出什么** | 需求编号 +【交付】编号 |
| **口令例** | `交棒开发ONEOS-xx交付=…` |
| **为什么** | 产品部到此结束;技术经理从这里拆开发 |
> 旁路:急单可用**快轨**(跳过分析、直接待开发),仍交到同一终点「待开发 + 交付→何斐」。
---
## 阶段 B开发步骤 712
### 步骤 7分配开发任务
| | |
|---|---|
| **谁** | 开发主管何斐 / 开发 Skill |
| **做什么** | 输入**交付任务编号** → 自动建 **【开发】**;标题=`【开发】`+需求标题;**描述人工补**;指定开发人;自动写计划时间 |
| **关联** | 子项挂【交付】;关联项挂需求 |
| **需求状态** | 仍为 **待开发**(确认即可,一般不用再改) |
| **口令例** | `分配任务:交付=ONEOS-a开发人=张三` |
| **为什么** | 一条需求可拆多个开发任务;都挂在同一交付下 |
---
### 步骤 8开始开发
| | |
|---|---|
| **谁** | 开发人员 |
| **做什么** | 口令带上**开发任务编号** |
| **开发任务** | → **处理中** |
| **需求状态** | → **开发中** |
| **口令例** | `开始开发ONEOS-d` |
| **为什么** | 看板一眼能看出「正在写代码」 |
---
### 步骤 9写代码 / 提 MR
| | |
|---|---|
| **谁** | 开发人员 |
| **做什么** | 按【交付】里的产品说明实现;分支/MR 建议挂上开发任务编号与需求编号 |
| **需求状态** | 仍为 **开发中** |
| **为什么** | 代码可追溯到哪条开发任务、哪条需求 |
---
### 步骤 10AI 自测门禁(开发侧草案)
| | |
|---|---|
| **谁** | AI开发完成后触发 |
| **做什么** | 找与**需求同标题**的测试计划 → 按用例自测 → 不过则自动提缺陷(标题含开发任务编号)并尝试修复,直到本计划用例全过 |
| **需求状态** | 仍为 **开发中**(未全过前) |
| **为什么** | 在正式提测前先挡住明显问题(属草案,规则可再收紧) |
---
### 步骤 11开发任务完成
| | |
|---|---|
| **谁** | 系统 / AI用例全过之后 |
| **做什么** | 该条【开发】标为**已完成** |
| **需求状态** | → **开发完成**(若有多条开发,建议等**全部**完成再改,避免过早) |
| **为什么** | 标记「代码+门禁」这一段结束 |
---
### 步骤 12完成开发 · 正式提测
| | |
|---|---|
| **谁** | 开发人员(自测也完成) |
| **做什么** | 口令「完成开发」→ 自动建 **【测试】**(标题=`【测试】`+任务名);子项挂【交付】;建议再关联需求;指派测试(如谢佳伟) |
| **需求状态** | → **待测试** ★ |
| **口令例** | `完成开发ONEOS-d` |
| **为什么** | 开发交棒给测试;测试侧开始接单 |
---
## 阶段 C测试步骤 1315
### 步骤 13接测试任务
| | |
|---|---|
| **谁** | 测试(谢佳伟等) |
| **做什么** | 打开【测试】任务;确认关联的需求与交付;准备/核对测试计划与用例包(建议按**需求编号**分包,比「同标题」更稳) |
| **需求状态** | **待测试** → 开始执行后改为 **测试中** |
| **为什么** | 正式测试以计划用例为准,不靠口头「测过了」 |
---
### 步骤 14执行用例 · 缺陷回流
| | |
|---|---|
| **谁** | 测试执行;失败时回流开发修 |
| **做什么** | 按用例执行;失败建缺陷 → 开发修复 → 再测 |
| **需求状态** | **测试中** |
| **为什么** | 质量关口;未绿不能进发版 |
---
### 步骤 15测试完成
| | |
|---|---|
| **谁** | 测试 / AI 辅助判定 |
| **做什么** | **本需求**相关用例全绿 →【测试】收口;通知发版对接人 |
| **需求状态** | → **测试完成** ★ |
| **注意** | 只卡本需求,不卡同迭代里别的需求 |
| **为什么** | 发版范围以「测试完成」的需求为准 |
---
## 阶段 D发版步骤 1617
### 步骤 16建发版任务
| | |
|---|---|
| **谁** | 发版对接人(时生亮)· 手工或 AI |
| **做什么** | 建 **【发版】**;关联**迭代** + 本期内要上的需求(建议再挂交付/测试);汇总更新说明 |
| **需求状态** | 进入发布流程时 → **发布中** |
| **为什么** | 一次发版可能含多条需求;要有明确范围清单 |
---
### 步骤 17发布结果回写
| | |
|---|---|
| **谁** | 发版对接人 / 流水线 |
| **做什么** | 执行发布 |
| **结果** | 成功 → **发布完成**;失败 → **发布失败**(可重试再进发布中) |
| **为什么** | 成败要回写云效,避免「以为发了其实没发」 |
---
## 阶段 E收口步骤 18
### 步骤 18业务验收 · 关闭
| | |
|---|---|
| **谁** | 产品 |
| **做什么** | 业务验收通过后,关闭需求,并收口【交付】 |
| **需求状态** | → **已关闭** |
| **为什么** | 全链路结束;树上任务与需求一致收口 |
---
## 状态主链(串起来看)
```text
待处理 → 已确认 → 分析中 → 设计中 → 设计完成
→ 待开发 ← 产品交棒给何斐
→ 开发中 → 开发完成
→ 待测试 → 测试中 → 测试完成
→ 发布中 → 发布完成(或发布失败可重试)
→ 已关闭 ← 产品验收关单
```
---
## 四个交棒口(最重要)
| 交棒 | 交出人 | 接棒人 | 交出物 | 状态落点 |
|---|---|---|---|---|
| ① 产品→开发 | 产品 | 何斐 | 需求号 + 交付号 | 待开发 |
| ② 开发→测试 | 开发人 | 测试 | 【测试】任务已建好 | 待测试 |
| ③ 测试→发版 | 测试 | 发版 | 本需求用例全绿 | 测试完成 |
| ④ 发版→产品 | 发版 | 产品 | 发布完成 / 更新说明 | 发布完成 → 已关闭 |
---
## 谁在什么时候动(对照表)
| 步骤 | 产品 | 开发主管 | 开发人 | 测试 | 发版 |
|---|---|---|---|---|---|
| 12 记需求/确认 | ● | | | | |
| 35 分析设计 | ● | | | | |
| 6 交棒 | ● | 接 | | | |
| 7 分配任务 | | ● | | | |
| 89 开始写码 | | | ● | | |
| 1011 AI门禁/完成任务 | | | ●/AI | | |
| 12 提测 | | | ● | 接 | |
| 1315 测试 | | | 修缺陷 | ● | |
| 1617 发版 | | | | | ● |
| 18 关闭 | ● | | | | |
---
## 相关文档
| 文档 | 用途 |
|---|---|
| `docs-四角色泳道流程图.md` | 泳道图总览 |
| `docs-产品部流转流程图.md` | 产品 16 细规 |
| `docs-开发侧流转草案.md` | 开发 712 细规与待拍板 |
| `yunxiao-pipeline-handbook` | 云效规则与配置 |

View File

@@ -0,0 +1,181 @@
# 四角色泳道图:产品 · 开发 · 测试 · 发版
> 用途:一张图看清从建需求到发版关闭,四条泳道各自做什么、在哪交棒。
> 依据:产品部流转 · 开发侧草案 · 生产线手册(测试/发版)
> 日期2026-07-24
> 说明开发泳道含「AI 用例门禁」草案;测试泳道为正式提测后的人/计划执行。
---
## 1. 泳道总览(推荐主图)
```mermaid
flowchart TB
subgraph PM["泳道① 产品"]
direction TB
P0["建需求 · 待处理<br/>只写 AutoRDO"]
P1["受理确认 · 已确认"]
P2["分析中<br/>建【交付】+【分析】"]
P3["设计中<br/>建【设计】"]
P4["设计完成<br/>AutoPRD 灌交付"]
P5["交棒 · 待开发<br/>交付负责人→何斐"]
P6["业务验收后<br/>关闭需求+交付"]
P0 --> P1 --> P2 --> P3 --> P4 --> P5
end
subgraph DEV["泳道② 开发"]
direction TB
D1["何斐:分配任务<br/>建【开发】SUB→交付"]
D2["开发人:开始开发<br/>任务处理中 · 需求开发中"]
D3["写代码 / 提 MR"]
D4["AI 按同标题测试计划自测<br/>不过→提缺陷并修"]
D5["开发任务已完成<br/>需求→开发完成"]
D6["完成开发(含自测)<br/>建【测试】· 需求待测试"]
D1 --> D2 --> D3 --> D4 --> D5 --> D6
end
subgraph QA["泳道③ 测试"]
direction TB
T1["接【测试】任务<br/>需求=待测试"]
T2["建/挂测试计划与用例<br/>(建议按需求编号分包)"]
T3["测试中 · 执行用例"]
T4["缺陷回流开发修复"]
T5["本需求用例全绿<br/>需求→测试完成"]
T1 --> T2 --> T3
T3 -.->|失败| T4
T4 -.->|再测| T3
T3 -->|通过| T5
end
subgraph REL["泳道④ 发版"]
direction TB
R1["建【发版】任务<br/>挂迭代+范围内需求"]
R2["汇总更新说明"]
R3["发布中"]
R4{"发布结果"}
R5["发布完成"]
R6["发布失败 · 可重试"]
R1 --> R2 --> R3 --> R4
R4 -->|成功| R5
R4 -->|失败| R6
R6 -.-> R3
end
P5 -->|"交棒契约<br/>需求编号+交付编号"| D1
D6 -->|"提测<br/>【测试】已挂交付"| T1
T5 -->|"交棒发版"| R1
R5 -->|"业务可验收"| P6
```
---
## 2. 横向时间轴版(谁在哪一阶段动)
从左到右是需求状态主链;上下是四个角色。空格表示该角色此阶段无主动动作。
```mermaid
flowchart LR
subgraph S_PM["产品阶段"]
direction TB
sp0["待处理→已确认"]
sp1["分析/设计/设计完成"]
sp2["待开发交棒"]
sp3["已关闭"]
end
subgraph S_DEV["开发阶段"]
direction TB
sd0["拆【开发】"]
sd1["开发中"]
sd2["AI门禁→开发完成"]
sd3["建【测试】→待测试"]
end
subgraph S_QA["测试阶段"]
direction TB
sq0["待测试"]
sq1["测试中"]
sq2["测试完成"]
end
subgraph S_REL["发版阶段"]
direction TB
sr0["建【发版】"]
sr1["发布中"]
sr2["完成/失败"]
end
sp0 --> sp1 --> sp2
sp2 --> sd0 --> sd1 --> sd2 --> sd3
sd3 --> sq0 --> sq1 --> sq2
sq2 --> sr0 --> sr1 --> sr2
sr2 --> sp3
```
---
## 3. 交接点一览
| # | 从 → 到 | 交出什么 | 需求状态落点 |
|---|---|---|---|
| 1 | 产品 → 开发 | 需求编号 +【交付】编号;交付负责人=何斐 | **待开发** |
| 2 | 开发 → 测试 | 【测试】任务(子项挂交付);用例计划可先备好 | **待测试** |
| 3 | 测试 → 发版 | 本需求用例全绿;范围内需求清单 | **测试完成** |
| 4 | 发版 → 产品 | 发布完成证据 / 更新说明 | **发布完成** → 产品关单 **已关闭** |
---
## 4. 各泳道职责边界(一句话)
| 角色 | 管什么 | 不管什么 |
|---|---|---|
| **产品** | 建需求、【交付】【分析】【设计】、AutoPRD、交棒待开发、验收关闭 | 不建【开发】【测试】【发版】、不开分支 |
| **开发** | 拆【开发】、写码、AI 自测门禁、建【测试】提测 | 不改写产品 AutoRDO不建第二套【交付】 |
| **测试** | 接【测试】、跑计划用例、缺陷回流、判测试完成 | 不擅自改需求状态到开发中;不建【发版】(可催) |
| **发版** | 建【发版】、挂迭代与范围、发布与回写成败 | 不替代测试判绿;不关闭需求(交给产品) |
---
## 5. 云效工作项树(跨角色)
```mermaid
flowchart TB
REQ["需求 · 状态=阶段真相"]
DEL["【交付】ASSOCIATED→需求"]
AN["【分析】"]
DE["【设计】"]
DV["【开发】"]
TE["【测试】"]
RE["【发版】ASSOCIATED→迭代/需求"]
DEL --> REQ
AN -->|TASK_SUB| DEL
DE -->|TASK_SUB| DEL
DV -->|TASK_SUB| DEL
TE -->|TASK_SUB| DEL
DV -.->|ASSOCIATED| REQ
TE -.->|ASSOCIATED| REQ
RE -.->|关联范围| REQ
```
---
## 6. 典型负责人(手册约定,可按项目改)
| 泳道 | 典型对接人 |
|---|---|
| 产品 | 王冕 · YunxiaoPMapp / AI |
| 开发 | 何斐(拆任务)→ 王雨昊 / 李振等(执行) |
| 测试 | 谢佳伟 |
| 发版 | 时生亮 |
---
## 相关文档
| 文档 | 说明 |
|---|---|
| `docs-全流程分步说明.md` | **整条链路逐步说明(推荐先读)** |
| `docs-产品部流转流程图.md` | 产品 0→5 细图 |
| `docs-开发侧流转草案.md` | 开发 D1D5 细图 |
| `yunxiao-pipeline-handbook` | 全链路配置与规则 |

View File

@@ -0,0 +1,230 @@
# 开发侧流转草案(产品交棒之后)
> 来源产品经理口述规则整理2026-07-24
> 上游终点:产品部 `docs-产品部流转流程图.md` → 需求=**待开发**,【交付】负责人=**何斐**
> 本文件目标:把「何斐拆任务 → 开发执行 → AI 用例门禁 → 提测」画清,供后续 **YunxiaoDevapp** Skill 定稿
> 状态:**草案**(文末有待拍板项)
---
## 1. 总览流程图
```mermaid
flowchart TB
subgraph handoff [产品已交棒]
Ready["需求=待开发\n【交付】负责人=何斐"]
end
subgraph d1 [D1 分配开发]
Assign["何斐:分配任务 + 交付任务编号"]
CreateDev["自动建【开发】+需求标题\n描述人工补\n指定开发人\n写计划时间"]
Link["子项 TASK_SUB→交付\n关联项 ASSOCIATED→需求"]
StReady["需求保持/确认为 待开发"]
end
subgraph d2 [D2 开始开发]
Start["开发人:开始开发 + 开发任务编号"]
DevDoing["开发任务→处理中"]
ReqDoing["需求→开发中"]
end
subgraph d3 [D3 AI 用例门禁]
CodeDone["代码开发完成触发"]
FindPlan["按需求同标题找测试计划"]
AITest["AI 按用例自测"]
Fail["未通过→自动提缺陷\n标题含开发任务编号\nAI 写标题描述"]
Fix["自动修复→再测"]
PassGate["用例全部通过"]
end
subgraph d4 [D4 开发任务完成]
DevDone["该条【开发】→已完成"]
ReqDevDone["需求→开发完成"]
end
subgraph d5 [D5 完成开发·提测]
Finish["开发人:完成开发\n含自测完成"]
CreateTest["自动建【测试】+任务名\n子项→交付"]
PendingTest["需求→待测试"]
end
Ready --> Assign --> CreateDev --> Link --> StReady
StReady --> Start --> DevDoing --> ReqDoing
ReqDoing --> CodeDone --> FindPlan --> AITest
AITest -->|未通过| Fail --> Fix --> AITest
AITest -->|全通过| PassGate --> DevDone --> ReqDevDone
ReqDevDone --> Finish --> CreateTest --> PendingTest
```
---
## 2. 分步说明(按你的 5 条)
### D1何斐分配任务
| 项 | 规则 |
|---|---|
| 触发 | Skill 口令:`分配任务` + **交付任务编号** |
| 新建 | 【开发】任务;标题 = `【开发】` + **需求标题** |
| 描述 | **人工添加**Skill 不代写正文,或只留空模板) |
| 负责人 | 口令指定开发人员 |
| 计划时间 | **自动创建**计划开始/计划完成(算法待定:阶段日历工时 or 人力预估,见待拍板) |
| 关联 | **子项** `TASK_SUB` →【交付】;**关联项** `ASSOCIATED` → 需求 |
| 需求状态 | 改为 / 确认为 **待开发**(见待拍板:与产品交棒是否重复) |
### D2开始开发
| 项 | 规则 |
|---|---|
| 触发 | `开始开发` + **开发任务编号** |
| 开发任务 | → **处理中** |
| 需求 | → **开发中**(有 ≥1 条开发进入处理中即可,或本条触发即改,见待拍板) |
### D3代码完成后 · AI 按测试计划自测
| 项 | 规则 |
|---|---|
| 触发 | 「代码开发完成」MR 合并 / 口令 / Webhook触发源待定 |
| 找计划 | **自动寻找与需求同标题的测试计划** |
| 执行 | AI 按该计划中用例自行测试 |
| 失败 | 自动提缺陷:标题含 **开发任务编号** + AI 生成标题/描述;再自动修复,循环直到用例全过 |
### D4用例全通过
| 项 | 规则 |
|---|---|
| 该条【开发】 | → **已完成** |
| 需求 | → **开发完成** |
### D5开发人「完成开发」自测也完成
| 项 | 规则 |
|---|---|
| 触发 | `完成开发` +(建议带)开发任务编号 |
| 新建 | 【测试】任务;标题 = `【测试】` + 任务名称(建议=需求标题) |
| 关联 | 子项 →【交付】(建议同时 ASSOCIATED→需求 |
| 需求 | → **待测试** |
---
## 3. 与产品部的衔接
```mermaid
flowchart LR
PM["产品 YunxiaoPMapp\n待开发 + 交付→何斐"] --> DevSkill["开发 Skill 草案\n本文 D1D5"]
DevSkill --> QA["测试执行人/Skill\n待测试之后"]
```
| 上游已具备 | 开发侧依赖 |
|---|---|
| 需求编号 +【交付】编号 | D1 入口只认编号,不按标题拆第二套交付 |
| 交付 ASSOCIATED→需求 | D1 开发任务再 ASSOCIATED→需求、SUB→交付 |
| 产品不建【开发】【测试】 | 仅开发 Skill 建这两类 |
---
## 4. 待拍板(建议你先定这几条)
### 4.1 状态顺序是否自洽
你现在的顺序是:
```text
D3 AI 用例全过 → 开发任务已完成 + 需求「开发完成」
D5 完成开发 → 建【测试】+ 需求「待测试」
```
与现有手册常见顺序对比:
```text
手册常见:开发人完成自测 → 待测试 →(测试执行)→ 测试完成
你草案: AI 先跑测试计划用例过关 → 开发完成 → 人再点完成开发 → 待测试
```
需要确认:
1. D3 的「测试计划」是 **开发自测门禁**,正式【测试】任务仍留给谢佳伟?
2. 还是 D3 已等同正式测试,那 D5 再建【测试】是否重复?
### 4.2 「需求→待开发」写在 D1
产品交棒时需求**已经是待开发**。D1 再改一次通常多余。建议改为:
- D1 **校验**需求已是待开发;若不是则停下或只允许从设计完成快轨补交棒
- 有开发任务进入处理中时,需求才变为 **开发中**(即你的 D2
### 4.3 「与需求同标题的测试计划」
标题易改、易撞名。更稳的是:
- 测试计划关联 **需求编号 / 迭代**,或
- 用例包命名 `CP-{需求编号}-…`
否则同名需求/改标题会导致找错计划。
### 4.4 AI 自动提缺陷并自动修复
风险高:无上限循环、误报、改回旧逻辑。建议门禁:
- 最多 N 轮;失败转人工
- 缺陷必须关联 **开发任务编号 + 需求编号 + 用例 ID**
- 与「防回归」清单联动,禁止静默改无关模块
### 4.5 多条【开发】时需求状态
| 场景 | 建议 |
|---|---|
| 任一条开始开发 | 需求 → 开发中 |
| 需求 → 开发完成 | **全部**未取消【开发】均为已完成(与手册 Y21 一致) |
| 需求 → 待测试 | 全部【开发】完成后,由末位「完成开发」或系统自动建【测试】 |
你原文 D4 写「该条」通过就把需求改成开发完成——多开发人并行时会过早。建议改成「全员开发任务完成」。
### 4.6 关联写法(与产品侧一致)
同一 create 只能带一条 `createWorkitemRelationInfo`
- 优先保证【开发】/【测试】**子项挂在交付**(交付详情「子项」可见)
- ASSOCIATED→需求若同 create 互斥,需约定:先 SUB再补 ASSOCIATED或 OpenAPI 双挂
---
## 5. 建议口令面(草案)
```text
分配任务:交付任务=ONEOS-a开发人=张三,李四;计划开始=…;计划完成=…
开始开发:开发任务=ONEOS-d
代码完成:开发任务=ONEOS-d → 触发 AI 用例门禁(或 Webhook
完成开发:开发任务=ONEOS-d → 建【测试】;需求→待测试
```
---
## 6. 推荐定稿后的状态主链(供你勾选)
**方案 A贴近你原文AI 测作开发门禁)**
```text
待开发 → 开发中 →AI 用例门禁)→ 开发完成 → 待测试 → 测试中 → 测试完成 → …
```
**方案 B贴近现有生产线手册**
```text
待开发 → 开发中 → 开发完成(人自测+MR→ 待测试 → 测试中(人/AI 跑计划)→ 测试完成 → …
```
AI 跑测试计划放在 **待测试之后**,与【测试】任务负责人(如谢佳伟)对齐。
---
## 7. 下一步
1. 你拍板:**方案 A 或 B**,以及多【开发】时「开发完成 / 待测试」的聚合规则
2. 我按定稿输出 `YunxiaoDevapp``SKILL.md` 骨架 + 与产品交棒契约对齐段落
3. 再补一版「仅开发侧」验收清单10 条以内)
---
## 相关文档
| 文档 | 路径 |
|---|---|
| 产品部流转 | `docs-产品部流转流程图.md` |
| 产品↔开发契约 | `docs-YunxiaoPMapp-实现原理-开发Skill对接.md` |
| 全链路手册 | `src/prototypes/yunxiao-pipeline-handbook/` |

View File

@@ -0,0 +1,47 @@
# 无单快轨到待开发
适用:口令明确「快轨」或「推进至待开发」且当前需求尚无标准分析路径任务(或用户确认跳过分析)。
## 动作表
| 对象 | 动作 |
|---|---|
| 需求 | 状态 → **待开发****预计工时=2**、**实际工时=2**(覆盖同日 8h 日历工时默认);标签按口令;更新编号区块 |
| 【交付】 | 无则新建ASSOCIATED→需求勿用 PARENT负责人→何斐**计划开始=创建当日**`79`**不写**计划完成;**描述双路径**(见下);**标签与需求相同**;更新编号区块 |
| 【设计】 | **必须新建****TASK_SUB→交付**(交付「子项」须可见);**描述=复制需求当前描述正文**;计划开始/完成均=当日create 后 `field/value``79`+`80`);任务→完成态;**标签与需求相同**;建后再尝试 **ASSOCIATED→原始需求**Cookie 常失败,见 live-api失败须标红**子项优先于关联项**);更新编号区块 |
| 【分析】 | **禁止创建** |
## 交付描述双路径A1
| 口令/材料 | 【交付】描述 |
|---|---|
| **手工描述**(无指定原型) | 同步需求当前手工/AutoRDO 正文(与设计一致可复制 document |
| **指定原型页面** | 调用 `$oneos-autoprd`,从原型生成 AutoPRD「产品说明」写入【交付】 |
| 既无手工可同步正文、又无原型 | 才允许占位 `等待设计任务完成后自动填入`Plan 勾选交棒占位风险,回报首行标红 |
有手工或原型时**禁止**交棒占位。
## AutoPRD
- 快轨默认可不跑 AutoPRD**例外**:口令指定原型 → 交付走 AutoPRD 路径(上表)。
- 口令同时「设计完成 + 原型」时仍按步骤 4 灌需求产品说明段。
## 查重
只认任务编号。已有分析单不得因「快轨」被删除。
## 回报必含
- 需求 / 交付 / 设计编号
- 「快轨:未建分析;设计已同步需求描述并当日收口」
- 交付描述来源:手工同步 / AutoPRD / 占位(若占位则首行标红)
- 需求预计工时=2、实际工时=2
- 设计关联项含需求编号;交付子项含设计编号
## 与标准 / 编号直推对比
```text
标准:分析中→交付+分析 → 设计中→设计+收口分析 → 设计完成→收口设计 → 待开发交棒
快轨(无既有阶段单):→ 待开发:新建交付+设计+交棒何斐(无分析;设计当日收口;需求工时 2+2
编号直推:已有分析/设计编号 → 收口空计划完成 → 待开发+交付交棒(不新建冗余单)
```

View File

@@ -0,0 +1,242 @@
# 云效实写 APIYunxiaoPMapp 已验证)
`verified_at`: 2026-07-25 · **项目须门禁 PJ 点选**(见 [project-selection.md](project-selection.md));历史验证样本项目为 `01_ONEOS` / 原「统一运营管理平台」(`last_selected.spaceIdentifier``assets/runtime-ids.json`,禁止未点选即使用)。
本文件只记**已跑通**的写法;禁止再盲试 `updateStatus` / 错误 `updateFieldValue` POST。
## 认证
- CookieChrome 域 `.aliyun.com` / `devops.aliyun.com``browser_cookie3` 或 Playwright storage
- Header`x-xsrf-token` = cookie `XSRF-TOKEN`URL 解码后)
- `Origin` / `Referer``https://devops.aliyun.com`
## 建单
`POST|PUT /projex/api/workitem/workitem?_input_charset=utf-8`
创建响应 `result.identifier` / `serialNumber` 即编号真相;**禁止按标题查重**。
## 改负责人(已通)
```http
PATCH /projex/api/workitem/workitem/{id}?_input_charset=utf-8
{"propertyKey":"assignedTo","propertyValue":"<userId>","operateType":"COVER"}
```
交棒:【交付】`propertyValue` = 何斐 ID。
## 打标签(已通)
```http
PATCH /projex/api/workitem/workitem/{id}?_input_charset=utf-8
{"workitemIdentifier":"{id}","propertyKey":"tag","propertyValue":"<tagId>[,<tagId>]","operateType":"COVER"}
```
## 改状态(已通 · 唯一推荐)
```http
POST /projex/api/workitem/workitem/{id}/status/transit?_input_charset=utf-8
{"fromStatus":"<status.identifier>","toStatus":"<status.identifier>"}
```
成功:`code=200``result=true`。失败时 `errorMsg` 含「不能流转」。
### 需求状态 ID本项目
| 显示名 | identifier |
|---|---|
| 待处理 | `100005` |
| 已确认 | `32` |
| 分析中 | `154395` |
| 设计中 | `156603` |
| 设计完成 | `307012` |
| 待开发 | `1582fc929d429111b925309493` |
### 任务状态 ID
| 显示名 | identifier |
|---|---|
| 待处理 | `100005` |
| 已完成 | `100014` |
### 极速交棒跳转(工作流允许)
从「待处理」菜单可见直达「设计完成」;推荐最少跳:
```text
待处理 → 设计完成 → 待开发
```
标准路径若需看板留痕,可走完整链:已确认→分析中→设计中→设计完成→待开发(仍用本 API勿开 UI
### 禁止(已证伪)
| 写法 | 结果 |
|---|---|
| `PATCH …/updateStatus` + `statusIdentifier` | `400 不能为空` |
| `PATCH …/{id}` + `propertyKey=status` | `property not found` |
| Playwright 点左侧/列表上的状态色块(`x<1100` | 假成功、状态不落库 |
仅当 `status/transit` 不可用时,才用 UI右侧详情状态钮`getBoundingClientRect().x > 1100`+ `.next-menu-item`
## 计划开始/完成 · 提交部门/人 · 预计工时2026-07-27 修订)
**通用字段写入(已通):**
```http
POST /projex/api/workitem/workitem/field/value/{workitemId}?_input_charset=utf-8
Content-Type: application/x-www-form-urlencoded
fieldValueList=[{"fieldIdentifier":"79","value":"2026-07-27 12:00:00"},{"fieldIdentifier":"3132597a9718d1c282b7ba5a0c","value":""},{"fieldIdentifier":"9e01269e96f91fbb97d36bf5b3","value":""}]
```
| 字段 | fieldIdentifier | value |
|---|---|---|
| 计划开始 | `79` | `YYYY-MM-DD HH:mm:ss`(推荐正午)或 epoch ms 字符串 |
| 计划完成 | `80` | 同上 |
| 提交部门 | `3132597a9718d1c282b7ba5a0c` | 纯文本 |
| 提交人 | `9e01269e96f91fbb97d36bf5b3` | 纯文本 |
**预计工时 `101586`:禁止直接改字段**(报「不可直接修改」)。须登记:
```http
POST /projex/api/workitem/workitem/time/estimate?_input_charset=utf-8
{"workitemIdentifier":"<id>","spentTime":8,"type":"develop","description":"","recordUserIdentifier":"<userId>","forCreate":false,"containsRestDay":false}
```
删除多余预估:`DELETE /projex/api/workitem/workitem/time/estimate/{workitemId}/{estimateId}`
列表:`GET …/time/estimate/list?workitemIdentifier=`
旧写法 `PATCH …/updateWorkitemFieldValue` 对上述自定义字段常 `400 不能为空`,勿再优先使用。
## 父子 / 子项 / 关联项(已通 · 2026-07-23 修订 · 子项优先)
### 关联项(【交付】强制 · ASSOCIATED
任务详情「关联项」只认 `ASSOCIATED`。**仅【交付】**建单时 `createWorkitemRelationInfo` 必须指向**需求**
```json
{
"createWorkitemRelationInfo": {
"relatedWorkitemIdentifier": "<需求id>",
"relatedToRelationIdentifier": "ASSOCIATED"
}
}
```
校验:
```http
GET /projex/api/workitem/v2/workitem/{id}/relation/workitem/list/by-relation-category?category=ASSOCIATED&isForward=true
```
`result` 含该需求即通过。
### 禁止(关联项)
| 写法 | 结果 |
|---|---|
| `relatedToRelationIdentifier=PARENT` 把交付挂需求 | 详情可能有 parent**关联项仍为空** |
| 分析/设计只用 `ASSOCIATED→需求` + `parentIdentifier` | 关联项可能有,**交付子项仍为空**ONEOS-246/247 |
| 建后再 `POST …/relation/record` 补关系 | Cookie 路径下常报「不能关联相同的工作项」 |
| `createWorkitemRelationList` | 不落 ASSOCIATED |
### 子项(【分析】/【设计】强制 · TASK_SUB
「子项」页读 `PARENT_SUB` / `TASK_SUB`,分析/设计**必须**
```json
{
"parent": "<交付id>",
"parentIdentifier": "<交付id>",
"createWorkitemRelationInfo": {
"relatedWorkitemIdentifier": "<交付id>",
"relatedToRelationIdentifier": "TASK_SUB"
}
}
```
同一 create 只能带一条 `createWorkitemRelationInfo`
`ASSOCIATED→需求``TASK_SUB→交付` **不能同时写**
**产品优先级交付「子项」tab > 阶段任务「关联项」。**
交付本身仍必须 `ASSOCIATED→需求`。标准路径下分析/设计的「关联项」允许为空。
**无单快轨例外(设计双挂):** create 用 `TASK_SUB→交付` 后,须再补 **ASSOCIATED→原始需求**,使设计详情「关联项」可见需求。
```http
POST /projex/api/workitem/workitem/{id}/relation/record?_input_charset=utf-8
{"relationIdentifier":"ASSOCIATED","toWorkitemIdentifier":"<id>"}
```
**已证伪Cookie · 2026-07-27** 凡工作项**已创建**后再 `relation/record` 补挂(含 ASSOCIATED / TASK_SUB常报「不能关联相同的工作项」与是否已有父项无关。`createWorkitemRelationList` 亦不落 ASSOCIATED。
**可行路径:**
| 目标 | 做法 |
|---|---|
| 交付「子项」可见设计(优先) | create 带 `TASK_SUB→交付` |
| 设计「关联项」可见需求 | create 带 `ASSOCIATED→需求`(与上互斥,同 create 只能一条) |
| 双挂 | 需个人 `x-yunxiao-token` OpenAPICookie 路径**不得**声称成功 |
产品默认:**子项优先**;关联项失败须在回报中标红并列出缺项。
校验子项:
```http
GET /projex/api/workitem/v2/workitem/{id}/relation/workitem/list/by-relation-category?category=PARENT_SUB&isForward=true
```
结果须含对应分析/设计 identifier。
校验设计关联项:
```http
GET /projex/api/workitem/v2/workitem/{id}/relation/workitem/list/by-relation-category?category=ASSOCIATED&isForward=true
```
`result` 须含原始需求 identifier。
### 无单快轨字段默认2026-07-27
| 对象 | 规则 |
|---|---|
| 【设计】描述 | 复制需求 document HTML |
| 【设计】`79`/`80` | 当日 `12:00:00` / `23:59:59`create 后 `field/value`(勿 create 同时带 79+80 |
| 【交付】描述 | 手工同步需求正文或原型→AutoPRD禁止无故占位 |
| 【交付】`79` | 创建当日;不写 `80` |
| 【交付】/【设计】标签 | 与需求相同,`PATCH propertyKey=tag` |
| 需求预计工时 | `time/estimate` **spentTime=2**(先删多余预估) |
| 需求实际工时 | `POST …/workitem/time`body 用 **`actualTime`**(非 spentTime+ `gmtStart`/`gmtEnd` epoch ms 字符串;见 `runtime-ids.json` `fields.actual_hours` |
| 描述更新 | `PATCH …/workitem/{id}/document``{"content":"<html>","formatType":"RICHTEXT"}` |
## 迭代挂接(已通 · 2026-07-27 · 只挂交付)
创建迭代:`POST /projex/api/workspace/sprint`(必填 `staffIds`;可写 `capacityHours`)。
挂【交付】到迭代:
```http
PATCH /projex/api/workitem/workitem/{id}?_input_charset=utf-8
{"workitemIdentifier":"{id}","propertyKey":"sprint","propertyValue":"{sprintId}","operateType":"COVER"}
```
清空误挂(如需求):`propertyValue:""` + `operateType:"COVER"`
**校验**必须读 `/extra`(详情主接口常不含 sprint 字段,禁止据此判失败):
```http
GET /projex/api/workitem/workitem/{id}/extra?_input_charset=utf-8
result.sprint[].identifier / name
```
产品规则:**只挂【交付】**;需求 / 分析 / 设计默认不挂(除非口令显式)。
### 极速建单注意
1. Cookie 只刷一次;全程纯 HTTP默认**不开浏览器**。
2. 交付建完后,【分析】与【设计】**并行**创建(均 TASK_SUB→交付标准/快轨两树可并行。
3. 状态用 `transit` + **本地追踪 fromStatus**(禁止每次 GET负责人在交棒场景下**创建时即何斐**。
4. 建单 `fieldValueList` 可带计划开始 `79`**不要**在 create 同时写 `79+80`(同日会 400
5. 标签必须 PATCHcreate 带 tag 不落库);可与建子任务重叠;快轨交付/设计须与需求同标签。
6. `requests.Session` keep-alive**禁止**对共享 opener 加全局锁。
7. 脚本入口:`scripts/live_create_fast.py`v5快轨描述/计划/标签/工时 2+2/设计 ASSOCIATED 补挂)。

View File

@@ -0,0 +1,660 @@
#!/usr/bin/env python3
"""YunxiaoPM 极速真实建单 v5快轨描述/计划/标签/工时 2+2/设计 ASSOCIATED 补挂。"""
from __future__ import annotations
import json
import time
import urllib.parse
from concurrent.futures import ThreadPoolExecutor, as_completed
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Any
try:
import browser_cookie3
except ImportError: # pragma: no cover
browser_cookie3 = None
import requests
ROOT = Path(__file__).resolve().parents[1]
RUNTIME = json.loads((ROOT / "assets" / "runtime-ids.json").read_text())
STATUS = RUNTIME["status"]["req"]
TASK_STATUS = RUNTIME["status"]["task"]
FAST = RUNTIME.get("fields", {}).get("fast_track") or {}
SPACE = (
RUNTIME.get("project", {}).get("spaceIdentifier")
or (RUNTIME.get("project", {}).get("last_selected") or {}).get("spaceIdentifier")
)
if not SPACE:
raise RuntimeError(
"未选定项目 spaceIdentifier须先走门禁 PJ 点选,或设置 runtime project.last_selected"
)
REQ_TYPE = RUNTIME["workitem_types"]["product_req"]["identifier"]
TASK_TYPE = RUNTIME["workitem_types"]["task"]["identifier"]
HEFEI = RUNTIME["people"]["hefei"]["identifier"]
WANG = RUNTIME["people"].get("wangmian", {}).get("identifier", "6811df000601d2fea60144a9")
PRI = RUNTIME["priority"][""]
TAG_FAULT = RUNTIME.get("tags", {}).get("故障管理", "ceb526a7343995577645317e9a")
PLACEHOLDER = RUNTIME["delivery_placeholder"]
PROTO = "https://prototype.lnoneos.com/vehicle-fault-handling/index.html"
TZ = timezone(timedelta(hours=8))
TODAY = datetime.now(TZ).strftime("%Y-%m-%d")
NOON = f"{TODAY} 12:00:00"
EOD = f"{TODAY} 23:59:59"
NOON_MS = str(
int(datetime.now(TZ).replace(hour=12, minute=0, second=0, microsecond=0).timestamp() * 1000)
)
START_MS = str(
int(datetime.now(TZ).replace(hour=9, minute=0, second=0, microsecond=0).timestamp() * 1000)
)
END_MS = str(
int(datetime.now(TZ).replace(hour=11, minute=0, second=0, microsecond=0).timestamp() * 1000)
)
FAST_EST = int(FAST.get("req_estimated_hours", 2))
FAST_ACT = int(FAST.get("req_actual_hours", 2))
PENDING = STATUS["待处理"]
DESIGN_DONE = STATUS["设计完成"]
PENDING_DEV = STATUS["待开发"]
TASK_DONE = TASK_STATUS["已完成"]
_COOKIE = ""
_XSRF = ""
def load_auth() -> None:
global _COOKIE, _XSRF
jar: dict[str, str] = {}
if browser_cookie3:
for domain in (".aliyun.com", "devops.aliyun.com", ".devops.aliyun.com"):
try:
for c in browser_cookie3.chrome(domain_name=domain):
jar[c.name] = c.value
except Exception:
pass
if not jar:
p = Path("/tmp/yunxiao_cookies.json")
if p.exists():
raw = json.loads(p.read_text())
jar = (
raw
if isinstance(raw, dict) and "XSRF-TOKEN" in raw
else {c["name"]: c["value"] for c in raw.get("cookies", [])}
)
_COOKIE = "; ".join(f"{k}={v}" for k, v in jar.items())
x = jar.get("XSRF-TOKEN", "")
_XSRF = urllib.parse.unquote(x) if "%" in x else x
if not _XSRF:
raise RuntimeError("缺少 XSRF-TOKEN请先在 Chrome 登录 devops.aliyun.com")
def session() -> requests.Session:
s = requests.Session()
s.headers.update(
{
"Content-Type": "application/json",
"Cookie": _COOKIE,
"x-xsrf-token": _XSRF,
"X-XSRF-TOKEN": _XSRF,
"Origin": "https://devops.aliyun.com",
"Referer": f"https://devops.aliyun.com/projex/project/{SPACE}/req",
"accept": "application/json",
"User-Agent": "YunxiaoPM-live_create_fast/5.0",
"Connection": "keep-alive",
}
)
return s
def api(s: requests.Session, method: str, url: str, body: Any = None) -> dict:
r = s.request(method, url, json=body, timeout=60)
try:
return r.json()
except Exception:
r.raise_for_status()
raise
def create(s: requests.Session, payload: dict) -> dict:
url = "https://devops.aliyun.com/projex/api/workitem/workitem?_input_charset=utf-8"
j = api(s, "POST", url, payload)
r = j.get("result") or {}
if j.get("code") == 200 and isinstance(r, dict) and r.get("identifier"):
return r
j = api(s, "PUT", url, payload)
r = j.get("result") or {}
if j.get("code") == 200 and isinstance(r, dict) and r.get("identifier"):
return r
raise RuntimeError(f"create failed: {j}")
def get(s: requests.Session, wid: str) -> dict:
return api(
s,
"GET",
f"https://devops.aliyun.com/projex/api/workitem/workitem/{wid}?_input_charset=utf-8",
)["result"]
def apply_tag(s: requests.Session, wid: str, tag_id: str = TAG_FAULT) -> None:
j = api(
s,
"PATCH",
f"https://devops.aliyun.com/projex/api/workitem/workitem/{wid}?_input_charset=utf-8",
{
"workitemIdentifier": wid,
"propertyKey": "tag",
"propertyValue": tag_id,
"operateType": "COVER",
},
)
if j.get("code") != 200:
raise RuntimeError(f"tag failed {wid}: {j}")
def set_document(s: requests.Session, wid: str, html: str) -> None:
j = api(
s,
"PATCH",
f"https://devops.aliyun.com/projex/api/workitem/workitem/{wid}/document?_input_charset=utf-8",
{"content": html, "formatType": "RICHTEXT"},
)
if j.get("code") != 200 or j.get("errorMsg"):
raise RuntimeError(f"document failed {wid}: {j}")
def set_fields(s: requests.Session, wid: str, pairs: list[tuple[str, str]]) -> None:
data = urllib.parse.urlencode(
{
"fieldValueList": json.dumps(
[{"fieldIdentifier": k, "value": v} for k, v in pairs], ensure_ascii=False
)
}
)
r = s.post(
f"https://devops.aliyun.com/projex/api/workitem/workitem/field/value/{wid}?_input_charset=utf-8",
data=data,
headers={"Content-Type": "application/x-www-form-urlencoded"},
timeout=60,
)
j = r.json()
if j.get("code") != 200:
raise RuntimeError(f"field/value failed {wid}: {j}")
def set_estimate_hours(s: requests.Session, wid: str, hours: int, user: str = WANG) -> None:
est = api(
s,
"GET",
f"https://devops.aliyun.com/projex/api/workitem/workitem/time/estimate/list?workitemIdentifier={wid}",
).get("result") or []
for row in est:
eid = row.get("identifier")
if eid:
api(
s,
"DELETE",
f"https://devops.aliyun.com/projex/api/workitem/workitem/time/estimate/{wid}/{eid}",
)
j = api(
s,
"POST",
"https://devops.aliyun.com/projex/api/workitem/workitem/time/estimate?_input_charset=utf-8",
{
"workitemIdentifier": wid,
"spentTime": hours,
"type": "develop",
"description": "快轨默认预计工时",
"recordUserIdentifier": user,
"forCreate": False,
"containsRestDay": False,
},
)
if j.get("code") != 200:
raise RuntimeError(f"estimate failed {wid}: {j}")
def set_actual_hours(s: requests.Session, wid: str, hours: int, user: str = WANG) -> None:
j = api(
s,
"POST",
"https://devops.aliyun.com/projex/api/workitem/workitem/time?_input_charset=utf-8",
{
"workitemIdentifier": wid,
"actualTime": hours,
"type": "develop",
"description": "快轨默认实际工时",
"recordUserIdentifier": user,
"gmtStart": START_MS,
"gmtEnd": END_MS,
},
)
if j.get("code") != 200 or not j.get("result"):
raise RuntimeError(f"actual time failed {wid}: {j}")
def try_associate_to_req(s: requests.Session, stage_id: str, req_id: str) -> bool:
"""建后补 ASSOCIATED→需求。Cookie 下常失败,成功返回 True。"""
bodies = [
{"relationIdentifier": "ASSOCIATED", "toWorkitemIdentifier": req_id},
{
"relationIdentifier": "ASSOCIATED",
"fromWorkitemIdentifier": stage_id,
"toWorkitemIdentifier": req_id,
},
]
for body in bodies:
for url in (
f"https://devops.aliyun.com/projex/api/workitem/workitem/{stage_id}/relation/record?_input_charset=utf-8",
f"https://devops.aliyun.com/projex/api/workitem/v2/workitem/{stage_id}/relation/record?_input_charset=utf-8",
):
j = api(s, "POST", url, body)
if j.get("code") == 200 and j.get("result") not in (None, False):
if not (isinstance(j.get("result"), dict) and j["result"].get("status") in (404, 405)):
rows = list_associated(s, stage_id)
if req_id in {r.get("identifier") for r in rows}:
return True
return False
def transit(s: requests.Session, wid: str, from_status: str, to_status: str) -> None:
if from_status == to_status:
return
j = api(
s,
"POST",
f"https://devops.aliyun.com/projex/api/workitem/workitem/{wid}/status/transit?_input_charset=utf-8",
{"fromStatus": from_status, "toStatus": to_status},
)
if not (j.get("code") == 200 and j.get("result") is True):
raise RuntimeError(f"transit {wid} {from_status}->{to_status}: {j}")
def md_to_html(md: str) -> str:
parts = []
for line in md.splitlines():
if line.startswith("## "):
parts.append(f"<h2>{line[3:]}</h2>")
elif line.startswith("### "):
parts.append(f"<h3>{line[4:]}</h3>")
elif line.startswith("- "):
parts.append(f"<p>• {line[2:]}</p>")
elif line.strip():
parts.append(f"<p>{line}</p>")
return "".join(parts)
def req_document_html(s: requests.Session, rid: str) -> str:
w = get(s, rid)
return ((w.get("document") or {}).get("content") or w.get("description") or "").strip()
def req_payload(subject: str, html: str) -> dict:
return {
"subject": subject,
"description": html,
"formatType": "RICHTEXT",
"document": {"content": html, "formatType": "RICHTEXT"},
"spaceIdentifier": SPACE,
"space": SPACE,
"spaceType": "Project",
"workitemTypeIdentifier": REQ_TYPE,
"workitemType": REQ_TYPE,
"categoryIdentifier": "Req",
"category": "Req",
"assignedTo": WANG,
"fieldValueList": [
{"fieldIdentifier": "priority", "value": PRI},
{"fieldIdentifier": "assignedTo", "value": WANG},
],
"attachmentIdList": [],
"cloneFrom": None,
"createWorkitemRelationList": [],
}
def task_payload(
subject: str,
html: str,
assignee: str,
*,
plan_start: bool = True,
associated_req: str | None = None,
parent_delivery: str | None = None,
) -> dict:
fvl = [
{"fieldIdentifier": "priority", "value": PRI},
{"fieldIdentifier": "assignedTo", "value": assignee},
]
if plan_start:
fvl.append({"fieldIdentifier": "79", "value": NOON_MS})
payload: dict[str, Any] = {
"subject": subject,
"description": html,
"formatType": "RICHTEXT",
"spaceIdentifier": SPACE,
"space": SPACE,
"spaceType": "Project",
"workitemTypeIdentifier": TASK_TYPE,
"workitemType": TASK_TYPE,
"categoryIdentifier": "Task",
"category": "Task",
"assignedTo": assignee,
"fieldValueList": fvl,
"attachmentIdList": [],
"cloneFrom": None,
}
if parent_delivery:
payload["parent"] = parent_delivery
payload["parentIdentifier"] = parent_delivery
payload["createWorkitemRelationInfo"] = {
"relatedWorkitemIdentifier": parent_delivery,
"relatedToRelationIdentifier": "TASK_SUB",
}
else:
if not associated_req:
raise ValueError("associated_req required for delivery: ASSOCIATED→需求")
payload["createWorkitemRelationInfo"] = {
"relatedWorkitemIdentifier": associated_req,
"relatedToRelationIdentifier": "ASSOCIATED",
}
return payload
def list_associated(s: requests.Session, wid: str) -> list[dict]:
j = api(
s,
"GET",
f"https://devops.aliyun.com/projex/api/workitem/v2/workitem/{wid}/relation/workitem/list/by-relation-category?category=ASSOCIATED&isForward=true",
)
return j.get("result") or []
def assert_associated_to_req(s: requests.Session, wid: str, req_id: str, label: str) -> None:
rows = list_associated(s, wid)
ids = {r.get("identifier") for r in rows}
if req_id not in ids:
raise RuntimeError(
f"{label} 关联项未挂需求:期望 {req_id},实际 {[r.get('serialNumber') for r in rows]}"
)
AUTO_RDO = """## 原始诉求AutoRDO
运维需在故障处置页承接机器人上报的故障,完成处置、挂起与归档,并保留证据链;工作台相关统计口径需与处置页一致
待确认:
- 本期是否含真实短信/邮件通道(现口径一般为演示模板)
## 工作项编号(系统)
- 交付:待建
- 分析:待建
- 设计:待建
"""
def summarize_from_create(w: dict, *, status: str, assignee_name: str) -> dict:
return {
"serial": w.get("serialNumber"),
"id": w.get("identifier"),
"subject": w.get("subject"),
"status": status,
"assignee": assignee_name,
"parent": w.get("parentIdentifier"),
}
def build_normal() -> dict:
t0 = time.perf_counter()
s = session()
title = "【新增】故障处置YunxiaoPMapp标准·极速v2"
req = create(s, req_payload(title, md_to_html(AUTO_RDO + f"\n原型:{PROTO}\n")))
rid = req["identifier"]
with ThreadPoolExecutor(max_workers=2) as pool:
f_tag_r = pool.submit(apply_tag, session(), rid)
f_deliv = pool.submit(
create,
session(),
task_payload(
f"【交付】{title}",
f"<p>{PLACEHOLDER}</p>",
HEFEI,
associated_req=rid,
),
)
deliv = f_deliv.result()
f_tag_r.result()
did = deliv["identifier"]
with ThreadPoolExecutor(max_workers=3) as pool:
f_tag_d = pool.submit(apply_tag, session(), did)
f_ana = pool.submit(
create,
session(),
task_payload(
f"【分析】{title}",
"<p>分析阶段:故障处置台账、挂起归档与证据链。</p>",
WANG,
associated_req=rid,
parent_delivery=did,
),
)
f_des = pool.submit(
create,
session(),
task_payload(
f"【设计】{title}",
f"<p>设计阶段:对齐原型 {PROTO}</p>",
WANG,
associated_req=rid,
parent_delivery=did,
),
)
ana = f_ana.result()
des = f_des.result()
f_tag_d.result()
with ThreadPoolExecutor(max_workers=3) as pool:
list(
as_completed(
[
pool.submit(transit, session(), rid, PENDING, DESIGN_DONE),
pool.submit(transit, session(), ana["identifier"], PENDING, TASK_DONE),
pool.submit(transit, session(), des["identifier"], PENDING, TASK_DONE),
]
)
)
transit(s, rid, DESIGN_DONE, PENDING_DEV)
return {
"path": "normal",
"elapsed_s": round(time.perf_counter() - t0, 3),
"req": summarize_from_create(req, status="待开发", assignee_name="王冕"),
"delivery": summarize_from_create(deliv, status="待处理", assignee_name="何斐"),
"analysis": summarize_from_create(ana, status="已完成", assignee_name="王冕"),
"design": summarize_from_create(des, status="已完成", assignee_name="王冕"),
}
def build_fast(
*,
tag_id: str = TAG_FAULT,
has_prototype: bool = True,
delivery_html: str | None = None,
) -> dict:
"""无单快轨。
- 设计描述 = 需求 document
- 交付描述 = 手工同步需求正文(无原型)或传入 AutoPRD HTML禁止无故占位
- 设计 79/80=当日;交付 79=当日
- 需求/交付/设计同标签
- 需求预计/实际工时各 2
- 设计 TASK_SUB→交付后尝试 ASSOCIATED→需求
"""
t0 = time.perf_counter()
s = session()
title = "【新增】故障处置YunxiaoPM快轨·极速v5"
req_html = md_to_html(AUTO_RDO + (f"\n原型:{PROTO}\n" if has_prototype else "\n"))
req = create(s, req_payload(title, req_html))
rid = req["identifier"]
# 以落库 document 为准(与手动建需后读需求一致)
req_html = req_document_html(s, rid) or req_html
if delivery_html:
deliv_html = delivery_html
desc_source = "autoprd"
elif req_html.strip():
deliv_html = req_html
desc_source = "manual_sync"
else:
deliv_html = f"<p>{PLACEHOLDER}</p>"
desc_source = "placeholder"
with ThreadPoolExecutor(max_workers=2) as pool:
f_tag_r = pool.submit(apply_tag, session(), rid, tag_id)
f_deliv = pool.submit(
create,
session(),
task_payload(
f"【交付】{title}",
deliv_html,
HEFEI,
associated_req=rid,
),
)
deliv = f_deliv.result()
f_tag_r.result()
did = deliv["identifier"]
with ThreadPoolExecutor(max_workers=2) as pool:
f_tag_d = pool.submit(apply_tag, session(), did, tag_id)
f_des = pool.submit(
create,
session(),
task_payload(
f"【设计】{title}",
req_html,
WANG,
parent_delivery=did,
),
)
des = f_des.result()
f_tag_d.result()
des_id = des["identifier"]
apply_tag(s, des_id, tag_id)
# 计划时间设计起止当日交付开始当日create 已带 79再 field/value 加固)
set_fields(s, des_id, [("79", NOON), ("80", EOD)])
set_fields(s, did, [("79", NOON)])
# 设计关联项补挂需求(可能失败,回报 risk
design_assoc_ok = try_associate_to_req(s, des_id, rid)
with ThreadPoolExecutor(max_workers=2) as pool:
list(
as_completed(
[
pool.submit(transit, session(), rid, PENDING, DESIGN_DONE),
pool.submit(transit, session(), des_id, PENDING, TASK_DONE),
]
)
)
transit(s, rid, DESIGN_DONE, PENDING_DEV)
set_estimate_hours(s, rid, FAST_EST)
set_actual_hours(s, rid, FAST_ACT)
risk = None
if desc_source == "placeholder":
risk = "交付描述仍为占位"
if not design_assoc_ok:
risk = (risk + "" if risk else "") + "设计 ASSOCIATED→需求补挂失败Cookie须 UI/OpenAPI 兜底"
return {
"path": "fast",
"elapsed_s": round(time.perf_counter() - t0, 3),
"req": summarize_from_create(req, status="待开发", assignee_name="王冕"),
"delivery": summarize_from_create(deliv, status="待处理", assignee_name="何斐"),
"design": summarize_from_create(des, status="已完成", assignee_name="王冕"),
"analysis": None,
"delivery_desc_source": desc_source,
"design_associated_ok": design_assoc_ok,
"risk": risk,
}
def main() -> None:
auth0 = time.perf_counter()
load_auth()
auth_s = round(time.perf_counter() - auth0, 3)
wall0 = time.perf_counter()
with ThreadPoolExecutor(max_workers=2) as pool:
f_fast = pool.submit(build_fast)
f_normal = pool.submit(build_normal)
fast = f_fast.result()
normal = f_normal.result()
build_s = round(time.perf_counter() - wall0, 3)
s = session()
assert_associated_to_req(s, normal["delivery"]["id"], normal["req"]["id"], "normal.delivery")
assert_associated_to_req(s, fast["delivery"]["id"], fast["req"]["id"], "fast.delivery")
def assert_sub(delivery_id: str, child_id: str, label: str) -> None:
rows = api(
s,
"GET",
f"https://devops.aliyun.com/projex/api/workitem/v2/workitem/{delivery_id}/relation/workitem/list/by-relation-category?category=PARENT_SUB&isForward=true",
).get("result") or []
ids = {r.get("identifier") for r in rows}
if child_id not in ids:
raise RuntimeError(
f"{label} 未出现在交付子项:期望 {child_id},实际 {[r.get('serialNumber') for r in rows]}"
)
assert_sub(normal["delivery"]["id"], normal["analysis"]["id"], "normal.analysis")
assert_sub(normal["delivery"]["id"], normal["design"]["id"], "normal.design")
assert_sub(fast["delivery"]["id"], fast["design"]["id"], "fast.design")
verify = {
"normal_req": get(s, normal["req"]["id"])["status"]["displayName"],
"fast_req": get(s, fast["req"]["id"])["status"]["displayName"],
"normal_delivery_assignee": (
get(s, normal["delivery"]["id"]).get("assignedTo") or {}
).get("displayName"),
"fast_delivery_assignee": (get(s, fast["delivery"]["id"]).get("assignedTo") or {}).get(
"displayName"
),
"delivery_associated_ok": True,
"stage_tasks_as_sub_ok": True,
"fast_design_associated_ok": fast.get("design_associated_ok"),
}
out = {
"normal": normal,
"fast": fast,
"verify": verify,
"auth_elapsed_s": auth_s,
"wall_elapsed_s": build_s,
"created_at": datetime.now(TZ).isoformat(),
"mode": "live_create_fast_v5_fast_track_rules",
"opts": {
"create_includes_plan_start": True,
"skip_plan_end_on_create": True,
"tracked_transit_no_get": True,
"delivery_assignee_hefei_at_create": True,
"overlap_tag_with_create": True,
"fast_req_hours": f"{FAST_EST}+{FAST_ACT}",
"relation": "delivery ASSOCIATED→req; analysis/design TASK_SUB→delivery; design post ASSOCIATED→req",
"http": "requests.Session keep-alive",
},
}
Path("/tmp/yunxiao_pmapp_fast_v2_result.json").write_text(
json.dumps(out, ensure_ascii=False, indent=2)
)
print(json.dumps(out, ensure_ascii=False, indent=2))
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,60 @@
# 交付树模型与关联约定
## 真相源
```text
需求状态 = 阶段看板唯一真相(分析中/设计中/待开发…)
【交付】任务 = 该需求的交付容器(每需求最多 1 条)
【分析】/【设计】 = YunxiaoPMapp 在交付下建的阶段子项
【开发】/【测试】 = 另属开发 Skill / 测试 Skill不进本包
ASSOCIATED = 横向挂钩(【交付】 ↔ 需求)
SUB / TASK_SUB = 纵向拆解(交付 → 分析/设计)
```
## 关系验收
| 关系 | 用在哪里 | 验收 | 优先级 |
|---|---|---|---|
| ASSOCIATED | **仅【交付】** ↔ 需求 | 交付详情「关联项」能看到需求(**强制** | 交付必过 |
| TASK_SUB | 【分析】/【设计】 → 【交付】 | 交付详情「子项」能看到阶段任务(**强制** | 阶段任务必过 |
建单规则Cookie 路径 · 同一 create 只能一条 `createWorkitemRelationInfo`
| 对象 | `createWorkitemRelationInfo` | 另写字段 |
|---|---|---|
| 【交付】 | `ASSOCIATED` → 需求 | — |
| 【分析】/【设计】 | `TASK_SUB` → 交付 | `parent` + `parentIdentifier` = 交付 |
**禁止**对分析/设计只写 `parentIdentifier` + `ASSOCIATED→需求`关联项可能有但交付「子项」仍为空ONEOS-246/247 已复现)。
勿用 `PARENT` 冒充关联项。细则见 [live-api.md](live-api.md)。
## 禁止
| 禁止 | 说明 |
|---|---|
| 创建或描述【开发】/【测试】 | 口令与回报均不出现 |
| 分析/设计未挂成交付子项(无 TASK_SUB | 交付「子项」为 0交棒验收失败 |
| 用任务名称/标题做唯一性或查重 | 不得 `subject` 匹配复用 |
| 同一需求认定多个交付任务编号 | 列出编号请人合并后再继续 |
| 功能模块标签用「分析/设计/交付」 | 模块标签打在需求(可选交付)上 |
## 任务标题(仅展示)
- 【交付】+ 需求标题
- 【分析】+ 需求标题
- 【设计】+ 需求标题
标题可改,**不参与查重**。
## 任务编号唯一性
**唯一允许的查重/复用渠道:云效任务编号**(如 `ONEOS-99` / `serialNumber`)。
| 场景 | 正确 | 错误 |
|---|---|---|
| 首次创建【交付】 | 建单成功后回报并写入「工作项编号(系统)」 | 下次用标题搜 |
| 复用【交付】 | 口令或编号区块带 `交付任务=ONEOS-xx` | list 后按 subject 相等 |
| 判断是否已有交付 | 编号区块或交付 ASSOCIATED 编号集合 | 数【交付】开头标题 |
| 分析/设计幂等 | 仅已登记编号 | 按【分析】+需求标题 |
按编号命中则复用;**计划开始已有值禁止改写**。

View File

@@ -0,0 +1,49 @@
# 验收清单与回报
## apply 后必须自检
| # | 项 | 通过标准 |
|---|---|---|
| 1 | 需求编号 | 回报含 ONEOS-xx |
| 2 | 任务编号 | 交付/分析/设计凡新建或操作均回报编号;禁止只报标题 |
| 3 | 编号区块 | 需求「工作项编号(系统)」与实际一致 |
| 4 | ASSOCIATED | **仅交付**详情关联项可见需求(`createWorkitemRelationInfo=ASSOCIATED`;禁止 PARENT 冒充) |
| 5 | SUB | **必过**:分析/设计 create 用 `TASK_SUB→交付`(含 `parent`+`parentIdentifier`交付「子项」tab 须可见。与 ASSOCIATED 同 create 互斥,阶段任务关联项可空(见 live-api.md |
| 6 | 计划开始 | 未误覆盖已有值 |
| 7 | 阶段日历工时 | 有计划完成时已写入;脚注存在;回报用语正确 |
| 8 | 交棒 | 需求=待开发;交付负责人=何斐(交棒场景) |
| 9 | 占位风险 | 交付仍占位时首行标红 |
| 10 | 负向 | 本轮**无**【开发】/【测试】任务;未按标题查重 |
设计完成额外AutoPRD 段已写交付非占位除非失败停下ZIP+截图已挂或已列出缺项。
迭代额外:只挂【交付】(需求不挂);版本号符合递增规则。
## 回报模板(精简)
```text
【YunxiaoPM】
风险:(若有占位交棒则首行标红)
需求ONEOS-xx | 状态=…
交付ONEOS-a | 负责人=…
分析ONEOS-b | …(无则写无)
设计ONEOS-c | …(无则写无)
阶段日历工时:分析 Hh / 设计 Hh若本轮写入
附件:…(若本轮)
迭代:…(若本轮)
下一步:请技术经理使用开发 Skill交棒后
```
## 适合全自动 vs 人工门禁
| 适合全自动 | 建议半自动/人工门禁 |
|---|---|
| 建单、打标签、挂迭代、写描述、建交付树、改状态、交棒负责人、幂等查重 | **PJ 云效项目点选**、受理(已确认)、是否快轨、设计完成是否真可开发、跨需求优先级与迭代容量、回退与取消 |
## 实写性能2026-07-23 复盘)
| 项 | 要求 |
|---|---|
| 改状态 | 只用 `status/transit`(见 [live-api.md](live-api.md) |
| 改【交付】负责人 | 只用 `PATCH …/{id}` + `propertyKey=assignedTo` |
| 极速复测 | `scripts/live_create_fast.py`;默认不开浏览器 |

View File

@@ -0,0 +1,22 @@
# 口令面
```text
记录需求:…;项目=必选·Plan 点选);优先级=紧急|高|中|低;标签=…;提交部门=…;提交人=…;推进至=暂不推进|已确认|分析中|设计中|设计完成|待开发|待开发(快轨)
受理确认ONEOS-xx
开始分析ONEOS-xx → 【交付】+【分析】并回报编号
开始设计ONEOS-xx交付任务=…;分析任务=… → 【设计】+收口分析
设计完成ONEOS-xx设计任务=…;原型=…
交棒开发ONEOS-xx交付任务=… → 待开发 + 该编号负责人=何斐
快轨待开发ONEOS-xx → 待开发 +【交付】+【设计】(无【分析】)+ 交付负责人=何斐
编号直推:分析任务=ONEOS-b / 设计任务=ONEOS-c → 收口未完成计划完成 + 需求待开发 + 交付交棒何斐
创建迭代:版本类型=主|副|子;交付任务=ONEOS-a,ONEOS-b,…;名称前缀=…
AutoRDO粘贴聊天/附录音)→ 再记录需求
```
版本自动规则:取同前缀下最大 `Vx.y.z`(旧 `Vx.y` 视为 `Vx.y.0`)再按主/副/子递增;迭代名=`{前缀}{新版本}`
**PJ 项目**:新建需求/迭代前须点选云效项目(实时列表);禁止默认直指。见 [project-selection.md](project-selection.md)。
后续推进口令**优先显式带任务编号**;未带则读「工作项编号(系统)」;仍无则询问;**禁止按标题补全**。
YunxiaoPM 回报止于交棒;可一句「请技术经理使用开发 Skill」。

View File

@@ -0,0 +1,95 @@
# 压缩点选(`1a2b3a4d`
记录需求 Plan **默认**用编号题 + 字母选项;用户可用一行压缩答复确认。
## Plan 展示模板
```text
请回复压缩点选1a2b3a4d
(数字=题号,字母=选项;大小写不敏感;可写 1A2B3A4D
1. 类型
A. 新增
B. 优化
2. 项目(云效实时列表;建议项可标★)
A. 01_ONEOSONEOS
B. 02_小羚羚APPXLLAPP
C. …
3. 优先级
A. 紧急
B. 高
C. 中
D. 低
4. 标签(云效候选;建议项可标★)
A. 故障管理★
B. 还车应结款
C. …
```
可选续题(口令已齐则可写入清单、压缩串可不含):
```text
5. 推进至 …
6. 迭代 …
```
## 解析规则
| 规则 | 说明 |
|---|---|
| 形态 | `(题号)(字母)` 连续拼接,如 `1a2b3a4d` |
| 题号 | `1`=类型 `2`=项目 `3`=优先级 `4`=标签;可扩展 `5` `6` |
| 字母 | `a`→第 1 项 … `z`→第 26 项;超出选项数 → 非法,停 |
| 缺题 | 该题若口令已唯一预填且列表唯一命中,可用预填;否则停并追问缺题 |
| 多答同题 | 后写覆盖先写 |
| 非法字符 | 停,重贴模板 |
解析成功后 Plan 回显人话确认一行,例如:
```text
已解析 1a2b3a4d → 类型=新增;项目=02_小羚羚APP优先级=紧急;标签=D 项名)
确认后回复「执行」
```
用户再回「执行」才 apply仍守 Plan 门禁)。
## 与口令预填
口令已写 `类型新增项目01_ONEOS优先级标签故障管理` 时:
- 对应选项标 ★,并给出**建议压缩串**(如 `1a2a3b4a`),用户可直接改字母或整段重答。
- **不得**因有预填而跳过展示字母表;压缩确认(或逐题点选)仍是门禁。
## 标签未命中 → 自动重拉一次候选并重生选项
「标签无法对应」:口令标签名在**当前标签候选**中 0 命中(或多命中无法唯一)。
| 步骤 | 动作 |
|---|---|
| 1 | **自动重拉一次**标签候选(见下「标签候选来源」;强制刷新,不用旧缓存) |
| 2 | 用新列表**重新生成 4.A/B/C…** 选择项 |
| 3 | 回报:`已自动重拉标签列表(因无法对应)`;请用户重答 `4x` 或整串 |
| 4 | 仍无法对应 → 停;**禁止**第 3 次空转;**禁止**猜 tagId |
> 说明:此处重拉的是**标签候选列表**,不是项目列表。项目无法对应仍走 [project-selection.md](project-selection.md) 的「自动重拉一次」。
### 标签候选来源(当前已验证路径)
1. `runtime-ids.json``tags`
2. 目标项目(或预填项目)下近期工作项 `tag` 字段聚合去重
3. 重拉 = 再请求工作项列表聚合 + 合并 runtime命中后可回写 `tags` 缓存
(专用 `tag/list` Cookie API 尚未稳定;有稳定端点后改写入 `live-api.md` 并切换。)
## 项目列表顺序
生成 2. 选项时:口令预填/建议项目置 **A** 并标 ★,其余按云效返回顺序接 B/C/…。
## Agent 义务
1. 记录需求进 Plan 时必须输出本模板(至少 14 题)。
2. 收到压缩串先解析回显,再等「执行」。
3. 标签/项目无法对应:各自动重拉**一次**并刷新对应题选项。

View File

@@ -0,0 +1,69 @@
# 需求描述 vs 交付描述
两类描述职责不同;禁止混写;禁止建【交付】时把 AutoPRD 六大块提前塞进交付描述。
## A. 需求描述 · AutoRDO 清洗
| 项 | 规则 |
|---|---|
| 触发 | 对话建需求 / 碎片材料入库 |
| 调用 | **必须**使用独立 Skill「**`$AutoRDO`**」(`AutoRDO/SKILL.md`;本 Skill 不内嵌清洗细则) |
| 输入 | 聊天记录、录音、口述材料 |
| 处理 | 保留原意;书面化;去口头禅;**去除结尾句号**(细则在 AutoRDO `references/rules.md` |
| 输出 | 写入 `## 原始诉求AutoRDO` |
| 不做 | 本阶段不写 AutoPRD 六大块;不要求已有原型;不覆盖已有「产品说明」 |
口令:`AutoRDO…` → 确认后 `记录需求:【新增】标题;描述=整理稿;推进至=…`
## B. 交付描述
### B1. 标准路径(分析中起建交付)
| 时机 | 【交付】描述 |
|---|---|
| 首次创建起至设计完成前 | 固定文案:`等待设计任务完成后自动填入` |
| 设计完成时 | 用 AutoPRD「产品说明」正文替换占位 |
### B2. 无单快轨建交付(覆盖 B1
| 口令/材料 | 【交付】描述 |
|---|---|
| 手工描述(无指定原型) | **同步需求**当前手工/AutoRDO 正文;禁止占位 |
| 指定原型页面 | `$oneos-autoprd` 从原型生成写入;禁止占位 |
| 既无正文又无原型 | 才允许占位并标红风险 |
快轨【设计】描述始终复制需求当前描述正文(见 [fast-track.md](fast-track.md))。
## C. 需求描述双段模板(不可互相覆盖)
```markdown
## 原始诉求AutoRDO
(清洗稿;设计完成也不删除)
## 产品说明AutoPRD
(六大块+对象存储链接;未设计完成前可无此节或写「待设计完成后填入」)
## 工作项编号(系统)
- 交付:…
- 分析:…
- 设计:…
```
## D. 设计完成 · AutoPRD + 附件
前提:设计任务完成且已关联对应原型页。
1. 调用 **`$oneos-autoprd`AutoPRD**,产出并落盘 `.spec/requirements-prd.md` + 标注同步:
- 对象存储预览链接:`{baseUrl}/{prototype-id}/index.html`(禁止加 `prototypes/` 前缀、禁止去掉 `index.html`
- 产品说明 Markdown总览/角色/流程/状态/风险/交付等,见 AutoPRD 模板)
2. 写入需求 `## 产品说明AutoPRD`**禁止覆盖** `## 原始诉求AutoRDO` / `## 工作项编号(系统)`
3. 【交付】描述:按**交付任务编号**用产品说明正文**替换**占位(细则见 AutoPRD `references/yunxiao-delivery-sync.md`);可附「原始诉求见需求描述」。**创建【交付】时不得提前灌 MD。**
4. 附件(需求 +【交付】均挂;失败则不得声称成功):
- Make「导出 HTML含源码」ZIP → [make-export-attach.md](make-export-attach.md)
- Make「复制截图」全交互页 → 同上
缺原型 / AutoPRD 失败 / 导出或截图失败 → **不得**报到设计完成并宣称附件齐全;停下并列出缺项。
执行顺序:先 AutoPRD 落盘与附件就绪 → 再改需求/交付描述与设计计划完成 → 最后改需求状态。
**禁止**加载 `yunxiao-requirement-lifecycle`;阶段任务树只由本 SkillYunxiaoPMapp创建。

View File

@@ -0,0 +1,47 @@
# 无单快轨到待开发
适用:口令明确「快轨」或「推进至待开发」且当前需求尚无标准分析路径任务(或用户确认跳过分析)。
## 动作表
| 对象 | 动作 |
|---|---|
| 需求 | 状态 → **待开发****预计工时=2**、**实际工时=2**(覆盖同日 8h 日历工时默认);标签按口令;更新编号区块 |
| 【交付】 | 无则新建ASSOCIATED→需求勿用 PARENT负责人→何斐**计划开始=创建当日**`79`**不写**计划完成;**描述双路径**(见下);**标签与需求相同**;更新编号区块 |
| 【设计】 | **必须新建****TASK_SUB→交付**(交付「子项」须可见);**描述=复制需求当前描述正文**;计划开始/完成均=当日create 后 `field/value``79`+`80`);任务→完成态;**标签与需求相同**;建后再尝试 **ASSOCIATED→原始需求**Cookie 常失败,见 live-api失败须标红**子项优先于关联项**);更新编号区块 |
| 【分析】 | **禁止创建** |
## 交付描述双路径A1
| 口令/材料 | 【交付】描述 |
|---|---|
| **手工描述**(无指定原型) | 同步需求当前手工/AutoRDO 正文(与设计一致可复制 document |
| **指定原型页面** | 调用 `$oneos-autoprd`,从原型生成 AutoPRD「产品说明」写入【交付】 |
| 既无手工可同步正文、又无原型 | 才允许占位 `等待设计任务完成后自动填入`Plan 勾选交棒占位风险,回报首行标红 |
有手工或原型时**禁止**交棒占位。
## AutoPRD
- 快轨默认可不跑 AutoPRD**例外**:口令指定原型 → 交付走 AutoPRD 路径(上表)。
- 口令同时「设计完成 + 原型」时仍按步骤 4 灌需求产品说明段。
## 查重
只认任务编号。已有分析单不得因「快轨」被删除。
## 回报必含
- 需求 / 交付 / 设计编号
- 「快轨:未建分析;设计已同步需求描述并当日收口」
- 交付描述来源:手工同步 / AutoPRD / 占位(若占位则首行标红)
- 需求预计工时=2、实际工时=2
- 设计关联项含需求编号;交付子项含设计编号
## 与标准 / 编号直推对比
```text
标准:分析中→交付+分析 → 设计中→设计+收口分析 → 设计完成→收口设计 → 待开发交棒
快轨(无既有阶段单):→ 待开发:新建交付+设计+交棒何斐(无分析;设计当日收口;需求工时 2+2
编号直推:已有分析/设计编号 → 收口空计划完成 → 待开发+交付交棒(不新建冗余单)
```

View File

@@ -0,0 +1,20 @@
# 交棒门禁与回退最小集
## 交棒门禁(待开发)
| 情形 | 规则 |
|---|---|
| 【交付】描述已是 AutoPRD 正式说明(非占位) | 允许交棒Plan 正常列交付任务编号 + 负责人→何斐 |
| 【交付】描述仍为 `等待设计任务完成后自动填入` | **仍允许交棒**,但 Plan **必须**勾选风险项「交付描述仍为占位,技术侧仅可凭需求 AutoRDO 稿理解」;回报**首行标红**该风险;**禁止**静默交棒假装材料齐全 |
| 口令同时带原型且要求设计完成 | 先走步骤 4AutoPRD+附件)成功,再交棒,不再勾占位风险 |
## 回退 / 变更(最小集 · 兼容计划开始不篡改)
| 场景 | 规则 |
|---|---|
| 待开发 → 退回设计中 | 需求状态回退;【交付】负责人可改回创建人/产品;**交付计划开始不改**;若需重做设计 → **新开**设计任务编号(旧设计保持已收口,不改其计划开始);更新「工作项编号(系统)」中的设计编号为新号 |
| 设计完成后需求大变 | 不自动改状态Plan 询问是否回退设计中并新开设计编号;更新 AutoPRD 段AutoRDO 段保留并追加「变更纪要」 |
| 取消需求 | 关联任务标取消/废止;不删编号区块;不改已写计划开始 |
| 度量含义 | 交付计划开始保留 = 全周期仍从首次开工起算;回退重做会拉长日历工时——回报注明「含回退重做」 |
凡写云效的回退仍须走 Plan 门禁。

View File

@@ -0,0 +1,14 @@
# 交接契约(开发 Skill 入口)
YunxiaoPMapp 与开发 Skill **不要**互相 include 全文;仅认下列契约。
```text
PM 完成交棒 → 需求=待开发;【交付】任务编号=ONEOS-xx负责人=何斐ASSOCIATED 需求
若交付描述仍为占位 → 回报已标红风险
开发 Skill 入口 → 认「需求编号 + 交付任务编号」
占位时只可信需求「原始诉求AutoRDO」并有权要求产品补设计完成
```
共享常量(项目 ID、何斐 ID、节假日日历可引用本 Skill 的 `assets/` 短路径,勿加载整份对方规则。
测试 Skill 另开;本契约不覆盖提测/缺陷。

View File

@@ -0,0 +1,242 @@
# 云效实写 APIYunxiaoPMapp 已验证)
`verified_at`: 2026-07-25 · **项目须门禁 PJ 点选**(见 [project-selection.md](project-selection.md));历史验证样本项目为 `01_ONEOS` / 原「统一运营管理平台」(`last_selected.spaceIdentifier``assets/runtime-ids.json`,禁止未点选即使用)。
本文件只记**已跑通**的写法;禁止再盲试 `updateStatus` / 错误 `updateFieldValue` POST。
## 认证
- CookieChrome 域 `.aliyun.com` / `devops.aliyun.com``browser_cookie3` 或 Playwright storage
- Header`x-xsrf-token` = cookie `XSRF-TOKEN`URL 解码后)
- `Origin` / `Referer``https://devops.aliyun.com`
## 建单
`POST|PUT /projex/api/workitem/workitem?_input_charset=utf-8`
创建响应 `result.identifier` / `serialNumber` 即编号真相;**禁止按标题查重**。
## 改负责人(已通)
```http
PATCH /projex/api/workitem/workitem/{id}?_input_charset=utf-8
{"propertyKey":"assignedTo","propertyValue":"<userId>","operateType":"COVER"}
```
交棒:【交付】`propertyValue` = 何斐 ID。
## 打标签(已通)
```http
PATCH /projex/api/workitem/workitem/{id}?_input_charset=utf-8
{"workitemIdentifier":"{id}","propertyKey":"tag","propertyValue":"<tagId>[,<tagId>]","operateType":"COVER"}
```
## 改状态(已通 · 唯一推荐)
```http
POST /projex/api/workitem/workitem/{id}/status/transit?_input_charset=utf-8
{"fromStatus":"<status.identifier>","toStatus":"<status.identifier>"}
```
成功:`code=200``result=true`。失败时 `errorMsg` 含「不能流转」。
### 需求状态 ID本项目
| 显示名 | identifier |
|---|---|
| 待处理 | `100005` |
| 已确认 | `32` |
| 分析中 | `154395` |
| 设计中 | `156603` |
| 设计完成 | `307012` |
| 待开发 | `1582fc929d429111b925309493` |
### 任务状态 ID
| 显示名 | identifier |
|---|---|
| 待处理 | `100005` |
| 已完成 | `100014` |
### 极速交棒跳转(工作流允许)
从「待处理」菜单可见直达「设计完成」;推荐最少跳:
```text
待处理 → 设计完成 → 待开发
```
标准路径若需看板留痕,可走完整链:已确认→分析中→设计中→设计完成→待开发(仍用本 API勿开 UI
### 禁止(已证伪)
| 写法 | 结果 |
|---|---|
| `PATCH …/updateStatus` + `statusIdentifier` | `400 不能为空` |
| `PATCH …/{id}` + `propertyKey=status` | `property not found` |
| Playwright 点左侧/列表上的状态色块(`x<1100` | 假成功、状态不落库 |
仅当 `status/transit` 不可用时,才用 UI右侧详情状态钮`getBoundingClientRect().x > 1100`+ `.next-menu-item`
## 计划开始/完成 · 提交部门/人 · 预计工时2026-07-27 修订)
**通用字段写入(已通):**
```http
POST /projex/api/workitem/workitem/field/value/{workitemId}?_input_charset=utf-8
Content-Type: application/x-www-form-urlencoded
fieldValueList=[{"fieldIdentifier":"79","value":"2026-07-27 12:00:00"},{"fieldIdentifier":"3132597a9718d1c282b7ba5a0c","value":""},{"fieldIdentifier":"9e01269e96f91fbb97d36bf5b3","value":""}]
```
| 字段 | fieldIdentifier | value |
|---|---|---|
| 计划开始 | `79` | `YYYY-MM-DD HH:mm:ss`(推荐正午)或 epoch ms 字符串 |
| 计划完成 | `80` | 同上 |
| 提交部门 | `3132597a9718d1c282b7ba5a0c` | 纯文本 |
| 提交人 | `9e01269e96f91fbb97d36bf5b3` | 纯文本 |
**预计工时 `101586`:禁止直接改字段**(报「不可直接修改」)。须登记:
```http
POST /projex/api/workitem/workitem/time/estimate?_input_charset=utf-8
{"workitemIdentifier":"<id>","spentTime":8,"type":"develop","description":"","recordUserIdentifier":"<userId>","forCreate":false,"containsRestDay":false}
```
删除多余预估:`DELETE /projex/api/workitem/workitem/time/estimate/{workitemId}/{estimateId}`
列表:`GET …/time/estimate/list?workitemIdentifier=`
旧写法 `PATCH …/updateWorkitemFieldValue` 对上述自定义字段常 `400 不能为空`,勿再优先使用。
## 父子 / 子项 / 关联项(已通 · 2026-07-23 修订 · 子项优先)
### 关联项(【交付】强制 · ASSOCIATED
任务详情「关联项」只认 `ASSOCIATED`。**仅【交付】**建单时 `createWorkitemRelationInfo` 必须指向**需求**
```json
{
"createWorkitemRelationInfo": {
"relatedWorkitemIdentifier": "<需求id>",
"relatedToRelationIdentifier": "ASSOCIATED"
}
}
```
校验:
```http
GET /projex/api/workitem/v2/workitem/{id}/relation/workitem/list/by-relation-category?category=ASSOCIATED&isForward=true
```
`result` 含该需求即通过。
### 禁止(关联项)
| 写法 | 结果 |
|---|---|
| `relatedToRelationIdentifier=PARENT` 把交付挂需求 | 详情可能有 parent**关联项仍为空** |
| 分析/设计只用 `ASSOCIATED→需求` + `parentIdentifier` | 关联项可能有,**交付子项仍为空**ONEOS-246/247 |
| 建后再 `POST …/relation/record` 补关系 | Cookie 路径下常报「不能关联相同的工作项」 |
| `createWorkitemRelationList` | 不落 ASSOCIATED |
### 子项(【分析】/【设计】强制 · TASK_SUB
「子项」页读 `PARENT_SUB` / `TASK_SUB`,分析/设计**必须**
```json
{
"parent": "<交付id>",
"parentIdentifier": "<交付id>",
"createWorkitemRelationInfo": {
"relatedWorkitemIdentifier": "<交付id>",
"relatedToRelationIdentifier": "TASK_SUB"
}
}
```
同一 create 只能带一条 `createWorkitemRelationInfo`
`ASSOCIATED→需求``TASK_SUB→交付` **不能同时写**
**产品优先级交付「子项」tab > 阶段任务「关联项」。**
交付本身仍必须 `ASSOCIATED→需求`。标准路径下分析/设计的「关联项」允许为空。
**无单快轨例外(设计双挂):** create 用 `TASK_SUB→交付` 后,须再补 **ASSOCIATED→原始需求**,使设计详情「关联项」可见需求。
```http
POST /projex/api/workitem/workitem/{id}/relation/record?_input_charset=utf-8
{"relationIdentifier":"ASSOCIATED","toWorkitemIdentifier":"<id>"}
```
**已证伪Cookie · 2026-07-27** 凡工作项**已创建**后再 `relation/record` 补挂(含 ASSOCIATED / TASK_SUB常报「不能关联相同的工作项」与是否已有父项无关。`createWorkitemRelationList` 亦不落 ASSOCIATED。
**可行路径:**
| 目标 | 做法 |
|---|---|
| 交付「子项」可见设计(优先) | create 带 `TASK_SUB→交付` |
| 设计「关联项」可见需求 | create 带 `ASSOCIATED→需求`(与上互斥,同 create 只能一条) |
| 双挂 | 需个人 `x-yunxiao-token` OpenAPICookie 路径**不得**声称成功 |
产品默认:**子项优先**;关联项失败须在回报中标红并列出缺项。
校验子项:
```http
GET /projex/api/workitem/v2/workitem/{id}/relation/workitem/list/by-relation-category?category=PARENT_SUB&isForward=true
```
结果须含对应分析/设计 identifier。
校验设计关联项:
```http
GET /projex/api/workitem/v2/workitem/{id}/relation/workitem/list/by-relation-category?category=ASSOCIATED&isForward=true
```
`result` 须含原始需求 identifier。
### 无单快轨字段默认2026-07-27
| 对象 | 规则 |
|---|---|
| 【设计】描述 | 复制需求 document HTML |
| 【设计】`79`/`80` | 当日 `12:00:00` / `23:59:59`create 后 `field/value`(勿 create 同时带 79+80 |
| 【交付】描述 | 手工同步需求正文或原型→AutoPRD禁止无故占位 |
| 【交付】`79` | 创建当日;不写 `80` |
| 【交付】/【设计】标签 | 与需求相同,`PATCH propertyKey=tag` |
| 需求预计工时 | `time/estimate` **spentTime=2**(先删多余预估) |
| 需求实际工时 | `POST …/workitem/time`body 用 **`actualTime`**(非 spentTime+ `gmtStart`/`gmtEnd` epoch ms 字符串;见 `runtime-ids.json` `fields.actual_hours` |
| 描述更新 | `PATCH …/workitem/{id}/document``{"content":"<html>","formatType":"RICHTEXT"}` |
## 迭代挂接(已通 · 2026-07-27 · 只挂交付)
创建迭代:`POST /projex/api/workspace/sprint`(必填 `staffIds`;可写 `capacityHours`)。
挂【交付】到迭代:
```http
PATCH /projex/api/workitem/workitem/{id}?_input_charset=utf-8
{"workitemIdentifier":"{id}","propertyKey":"sprint","propertyValue":"{sprintId}","operateType":"COVER"}
```
清空误挂(如需求):`propertyValue:""` + `operateType:"COVER"`
**校验**必须读 `/extra`(详情主接口常不含 sprint 字段,禁止据此判失败):
```http
GET /projex/api/workitem/workitem/{id}/extra?_input_charset=utf-8
result.sprint[].identifier / name
```
产品规则:**只挂【交付】**;需求 / 分析 / 设计默认不挂(除非口令显式)。
### 极速建单注意
1. Cookie 只刷一次;全程纯 HTTP默认**不开浏览器**。
2. 交付建完后,【分析】与【设计】**并行**创建(均 TASK_SUB→交付标准/快轨两树可并行。
3. 状态用 `transit` + **本地追踪 fromStatus**(禁止每次 GET负责人在交棒场景下**创建时即何斐**。
4. 建单 `fieldValueList` 可带计划开始 `79`**不要**在 create 同时写 `79+80`(同日会 400
5. 标签必须 PATCHcreate 带 tag 不落库);可与建子任务重叠;快轨交付/设计须与需求同标签。
6. `requests.Session` keep-alive**禁止**对共享 opener 加全局锁。
7. 脚本入口:`scripts/live_create_fast.py`v5快轨描述/计划/标签/工时 2+2/设计 ASSOCIATED 补挂)。

View File

@@ -0,0 +1,59 @@
# 2026-07-23 真实建单复盘与极速优化
## 测试结论
标准 + 快轨均可建到「待开发」交棒;交付树、标签「故障管理」、快轨无【分析】均正确。
| 轮次 | 编号 |
|---|---|
| 第一轮(探测+UI | ONEOS-141147 |
| 极速 v1 | ONEOS-148154 |
| 极速 v2 | ONEOS-164177含中间探针 |
## 过程问题(已修)
| # | 问题 | 根因 | 修复 |
|---|---|---|---|
| 1 | 状态改不动 / 假成功 | 误用 `updateStatus`UI 点列表区 | `POST …/status/transit` |
| 2 | 负责人改不成 | `updateFieldValue` 错 | `PATCH …/{id}` + `assignedTo` |
| 3 | 状态 ID 不全 | 未抓网络 | 写入 `runtime-ids.json` |
| 4 | 极慢 | Playwright + 串行探测 | 纯 HTTP + 并行 |
| 5 | v1 仍偏慢 | 多余 GET、串行 PATCH 计划、交棒再改负责人 | 见下节 v2 |
## 性能对比
| 口径 | 优化前(第一轮) | 极速 v1 | 极速 v2本轮 |
|---|---|---|---|
| 会话墙钟 | ≈ **17.9 分钟** | — | — |
| 两路径并行建单墙钟 | ≈4.1 分钟自动化 | **4.4 s** | **2.2 s** |
| 标准单路径 | 失败反复 | 3.7 s | **2.2 s** |
| 快轨单路径 | 失败反复 | 3.7 s | **2.1 s** |
| 浏览器 | 多次 | 无 | 无 |
相对第一轮会话 ≈ **490×**;相对 v1 再快约 **2×**
## v2 压榨点(已落地)
1. `status/transit` **本地追踪** `fromStatus`,跳过每次 GET。
2. 建单 `fieldValueList` 带**计划开始(79)**;计划完成不在 create 写(同日会 400
3. 【交付】创建时负责人直接 **何斐**(省 PATCH
4. `requests.Session` keep-alive**去掉全局锁**(否则并行失效)。
5. 打标签与建子任务 **重叠**;两路径并行。
6. 交棒后汇总用创建响应,校验 GET 移出主路径计时。
## 探针结论(未采用)
| 尝试 | 结果 |
|---|---|
| create `fieldValueList` 带 tag | 建单成功但标签不落库 → 仍须 PATCH |
| create 同时写 79+80 | `400 计划…转化异常` |
| urllib 全局 lock + 单 opener | 并行被串行化,单路径 ≈4 s |
## 仍可再压(收益变小)
1. 标签 API 若将来支持 create 落库,可再少 24 次 PATCH。
2. HTTP/2 或连接预热DNS/TLS 复用到进程级)。
3. 业务允许「建单即待开发」且平台支持初始状态 → 少 2 次 transit。
4. 计划完成改为交棒后异步补写(当前故意跳过)。
脚本:`scripts/live_create_fast.py`mode=`live_create_fast_v2`)。

View File

@@ -0,0 +1,53 @@
# Make 导出与截图附件
设计完成(步骤 4且已关联原型页时需求与【交付】均挂附件。任一侧失败 → 不得声称设计完成附件齐全。
## 1. 导出 HTML含源码ZIP
与 Make「发布 → 导出 HTML含源码」对齐。
优先本地 Make Admin
```http
GET {adminOrigin}/api/export-html?path={prototypePath}&projectId={projectId}&includeSource=true
```
| 参数 | 要求 |
|---|---|
| `path` | 原型路径(如 `prototypes/oneos-h5-vehicle-assets` |
| `includeSource` | **必须** `true` |
| 响应 | ZIP`PK` 头);文件名建议 `{prototype-id}-html-source.zip` |
失败时:提示用户在 Make 客户端对该原型执行「发布 → 导出 HTML含源码把 ZIP 路径发回。
**禁止**用「仅对象存储链接」冒充已附带源码包。
## 2. 复制截图(全交互页)
1. Make「发布 → **复制截图**」(或等价:导出该原型主界面及所有交互页截图)。
2. 上传到需求附件与【交付】附件。
3. 缺页/失败 → 列出缺项,不得报成功。
## 3. 挂载范围
同一 ZIP / 同一批截图:
1. 上传到需求 identifier
2. 上传到【交付】任务 identifier
优先 API未知 upload 端点时用已登录浏览器在详情页「附件」上传。
## 4. 与对象存储的关系
| 产物 | 用途 |
|---|---|
| `{baseUrl}/{id}/index.html` | AutoPRD 描述内可点预览链接 |
| 导出 ZIP含源码 | 附件,供开发离线打开 |
| 交互页截图 | 附件,供评审/开发对照 |
三者职责不同,不可互相替代。
## 负向
- 不得导出错误原型页(须 Plan 确认原型路径/名称)。
- 不得把别的需求的旧 ZIP 复用到新需求。
- 快轨交棒默认不跑本附件流程(除非口令同时设计完成+原型)。

View File

@@ -0,0 +1,60 @@
# 交付树模型与关联约定
## 真相源
```text
需求状态 = 阶段看板唯一真相(分析中/设计中/待开发…)
【交付】任务 = 该需求的交付容器(每需求最多 1 条)
【分析】/【设计】 = YunxiaoPMapp 在交付下建的阶段子项
【开发】/【测试】 = 另属开发 Skill / 测试 Skill不进本包
ASSOCIATED = 横向挂钩(【交付】 ↔ 需求)
SUB / TASK_SUB = 纵向拆解(交付 → 分析/设计)
```
## 关系验收
| 关系 | 用在哪里 | 验收 | 优先级 |
|---|---|---|---|
| ASSOCIATED | **仅【交付】** ↔ 需求 | 交付详情「关联项」能看到需求(**强制** | 交付必过 |
| TASK_SUB | 【分析】/【设计】 → 【交付】 | 交付详情「子项」能看到阶段任务(**强制** | 阶段任务必过 |
建单规则Cookie 路径 · 同一 create 只能一条 `createWorkitemRelationInfo`
| 对象 | `createWorkitemRelationInfo` | 另写字段 |
|---|---|---|
| 【交付】 | `ASSOCIATED` → 需求 | — |
| 【分析】/【设计】 | `TASK_SUB` → 交付 | `parent` + `parentIdentifier` = 交付 |
**禁止**对分析/设计只写 `parentIdentifier` + `ASSOCIATED→需求`关联项可能有但交付「子项」仍为空ONEOS-246/247 已复现)。
勿用 `PARENT` 冒充关联项。细则见 [live-api.md](live-api.md)。
## 禁止
| 禁止 | 说明 |
|---|---|
| 创建或描述【开发】/【测试】 | 口令与回报均不出现 |
| 分析/设计未挂成交付子项(无 TASK_SUB | 交付「子项」为 0交棒验收失败 |
| 用任务名称/标题做唯一性或查重 | 不得 `subject` 匹配复用 |
| 同一需求认定多个交付任务编号 | 列出编号请人合并后再继续 |
| 功能模块标签用「分析/设计/交付」 | 模块标签打在需求(可选交付)上 |
## 任务标题(仅展示)
- 【交付】+ 需求标题
- 【分析】+ 需求标题
- 【设计】+ 需求标题
标题可改,**不参与查重**。
## 任务编号唯一性
**唯一允许的查重/复用渠道:云效任务编号**(如 `ONEOS-99` / `serialNumber`)。
| 场景 | 正确 | 错误 |
|---|---|---|
| 首次创建【交付】 | 建单成功后回报并写入「工作项编号(系统)」 | 下次用标题搜 |
| 复用【交付】 | 口令或编号区块带 `交付任务=ONEOS-xx` | list 后按 subject 相等 |
| 判断是否已有交付 | 编号区块或交付 ASSOCIATED 编号集合 | 数【交付】开头标题 |
| 分析/设计幂等 | 仅已登记编号 | 按【分析】+需求标题 |
按编号命中则复用;**计划开始已有值禁止改写**。

View File

@@ -0,0 +1,35 @@
# 编号直推到待开发
适用:标准路径已建过【分析】和/或【设计】,用**任务编号**一口气推到待开发交棒。
## 入口(只认编号)
```text
交棒开发:需求=ONEOS-xx交付任务=ONEOS-a分析任务=ONEOS-b设计任务=ONEOS-c
交棒开发:分析任务=ONEOS-b → 由分析 ASSOCIATED/SUB 反查需求与交付
交棒开发:设计任务=ONEOS-c → 同上反查
```
禁止用标题猜。编号对不上关联树 → 停下列出关联,不瞎改。
## 动作表
| 对象 | 动作 |
|---|---|
| 需求 | 状态 → **待开发**(按云效连跳) |
| 【交付】 | **必须**用交付任务编号定位;负责人→何斐;不改计划开始;不写计划完成;描述仍占位则保持(除非同时设计完成+原型+AutoPRD |
| 【分析】 | 若有编号:计划完成若为空 → 写当日并推工时;**不新建**第二条 |
| 【设计】 | 若有编号:计划完成若为空 → 写当日并推工时;**不新建**第二条 |
| 仅有分析、尚无设计 | **不强制补建【设计】**(与无单快轨区分);回报注明「无设计任务编号」 |
| 仅有设计、无分析 | 收口设计 + 交棒;**不补建分析** |
## 与无单快轨区别
| | 无单快轨 | 编号直推 |
|---|---|---|
| 前提 | 尚无分析/设计阶段单(或明确跳过分析) | 已有分析和/或设计**任务编号** |
| 【分析】 | 禁止创建 | 有编号则收口,无则不建 |
| 【设计】 | 必须新建且当日收口 | 有编号则收口;仅分析无设计时不强制新建 |
| 定位 | 新建后登记编号 | **仅任务编号**定位/反查 |
仍不创建【开发】/【测试】。交棒占位风险见 [handoff-and-rollback.md](handoff-and-rollback.md)。

View File

@@ -0,0 +1,73 @@
# 门禁 PJ · 云效项目选择(强制点选)
**新建需求 / 新建任务树 / 创建迭代 / 其它写入依赖 `spaceIdentifier`** 的操作,项目必须由用户从云效实时列表**点选**。禁止静默使用 `runtime-ids.json` 里的默认 `project.spaceIdentifier`
## 何时触发
| 场景 | 是否必须选项目 |
|---|---|
| 记录需求 / 无单快轨新建 | **必须** |
| 创建迭代(新挂项目空间) | **必须**(与需求同项目时沿用已锁定项,仍须在 Plan 写出项目名+ID |
| 仅推进已有编号(受理确认、开始分析…) | **不必重选**以该编号所在项目为准Plan 写出项目名 |
| 只读查询 | 不强制 |
## 执行顺序(建单前)
1. **实时拉取**云效项目列表Cookie + XSRF
```http
GET /projex/api/workspace/project/search/list
?category=Project&scope=all&toPage=1&pageSize=100
&conditions={"conditionGroups":[[]]}
&extraConditions= + public
&orderBy={"fieldIdentifier":"gmtCreate","format":"input","order":"desc","className":"date"}
&_input_charset=utf-8
```
2. 将结果整理为单选列表:`{name}{customCode}`;选项 id 用 `identifier`spaceId
3. **AskQuestion / Plan 单选**「PJ. 云效项目」;未点选 → **禁止 create**
4. 「批准 Plan」≠ 已选项目Plan 里仍是空选项或写「默认 01_ONEOS」而未点选 → 停。
5. 用户点选后:本轮 apply 全程使用该 `spaceIdentifier`;回报写清项目名 + customCode + spaceId。
6. 拉取成功后可回写 `assets/runtime-ids.json``projects_catalog`(缓存);**缓存不得当作已选项**。
## 无法对应 → 自动重拉一次
「无法对应」任一成立即触发:
| # | 情形 |
|---|---|
| 1 | 口令/预填的项目名、customCode、别名在**当前列表**中 0 命中 |
| 2 | 口令给出的 spaceId / identifier 不在当前列表 |
| 3 | 用户点选的选项 id 在 apply 前校验时已不在列表(列表过期) |
| 4 | 仅命中 `projects_catalog` 缓存、与本次实时列表不一致 |
| 5 | 首次拉取失败后改用了缓存,用户按缓存点选后 create 报项目/空间无效 |
**动作(固定一次):**
1. **立即再调一次**同一 `project/search/list`(强制网络,不用缓存)。
2. 用新列表重新做匹配 / 刷新 Plan 单选选项;可回写 `projects_catalog`
3. 回报注明:`已自动重拉项目列表(因无法对应)`
4. **仍无法对应** → 停,展示最新列表请用户重选;**禁止**再自动拉第 3 次;**禁止**猜一个 spaceId 继续建单。
匹配规则(名/码):忽略大小写;`name` 全等或包含;`customCode` 全等;`name_aliases` 全等。多命中视为无法唯一对应 → 重拉后仍多命中则请用户点选,不自动选定。
## 禁止
- 未询问就写入 `project.spaceIdentifier`(即便 catalog 标了 `suggested`
- 按口令里的「统一运营管理平台」字符串静默映射而不展示列表点选(口令仅作**预填建议**,仍须用户确认点选)
- API 失败时擅自沿用上次默认;应展示 `projects_catalog` 缓存并标明「离线缓存,请确认」,仍须点选;用户确认后若仍无法对应 → 走上一节「自动重拉一次」
- 多项目并行建单却共用一个未确认的 spaceId
- 「无法对应」时循环重拉超过 1 次,或跳过点选直接建单
## 口令预填
```text
记录需求:…;项目=01_ONEOS
```
若口令已含项目名/编号前缀且在实时列表中**唯一命中**Plan 可预勾该选项但仍须用户确认0 命中或多命中 → **先自动重拉一次**再匹配;仍 0/多 → 不预勾,只展示最新列表。
## 脚本
`scripts/list_projects.py`stdout JSON `projects[]`
带查询时:`python3 scripts/list_projects.py --match '01_ONEOS'` —— 0 命中/多命中则自动重拉一次再匹配(`refetched: true`)。

View File

@@ -0,0 +1,58 @@
# 记录需求 · 元字段(优先级 / 标签 / 提交部门 / 提交人)
建单前消费网页 / AutoRDO / 口令中的四类元信息。细则与 `assets/runtime-ids.json` 对齐;**禁止臆造未验证的 fieldIdentifier**。
## 口令形态
```text
记录需求:…;优先级=紧急|高|中|低;标签=…;提交部门=…;提交人=…;推进至=…
```
四字段均可选出现;网页或 AutoRDO 提示里已带的值与口令等价。
## Plan 是否追问
记录需求 **一律**走 [compact-select.md](compact-select.md) 字母表(类型/项目/优先级/标签),即使用户口令已写齐;给出建议压缩串,等用户回 `1a2b3a4d`(或改字母)并「执行」。
| 条件 | 行为 |
|---|---|
| 口令已含类型/项目/优先级/标签 | 对应选项标 ★ + 建议压缩串;**仍须**压缩确认或显式点选 |
| 标签名 0 命中 / 多命中 | **自动重拉一次**标签候选并重生 4.A/B/C…仍失败则停 |
| 仅缺提交部门/提交人 | 压缩 14 确认后,缺则追问或写入描述页脚 |
| 仅缺「推进至」等 | 按既有口令规则;可作 5. 题字母表 |
## 写入策略
### 优先级(已验证)
- 映射:`runtime-ids.json``priority`(紧急 / 高 / 中 / 低)。
- create 时写入 `fieldIdentifier: "priority"`(与 [live-api.md](live-api.md) / `live_create_fast.py` 一致)。
- 未给优先级时Plan 追问;脚本默认「中」仅作既有兜底,口令/网页有值时以用户值为准。
### 标签(已验证)
- 映射:`runtime-ids.json``tags`(按显示名取 tagId
- 标签须 **PATCH** `propertyKey: "tag"`create 带 tag 不落库)。
- 口令/网页给出的标签名若不在候选:按 [compact-select.md](compact-select.md) **自动重拉一次**标签列表并重生选项;仍无则停在 Plan勿猜 ID。
### 提交部门 / 提交人(已验证 · 2026-07-27 · ONEOS-293
| 字段 | fieldIdentifier |
|---|---|
| 提交部门 | `3132597a9718d1c282b7ba5a0c` |
| 提交人 | `9e01269e96f91fbb97d36bf5b3` |
| 规则 | 说明 |
|---|---|
| **写入** | `POST /projex/api/workitem/workitem/field/value/{workitemId}``Content-Type: application/x-www-form-urlencoded`,参数 `fieldValueList` = JSON 数组字符串 `[{"fieldIdentifier","value"}]` |
| **形态** | 均为普通文本 input非人员选择器口令值原样写入 |
| **页脚** | 仍可在描述页脚重复一份,便于检索;**不能替代**字段写入 |
| **计划开始** | 字段 `79`,同一 `field/value` API推荐 `YYYY-MM-DD 12:00:00`。快轨:【交付】/【设计】创建当日写入;【设计】另写计划完成 `80`=`当日 23:59:59` |
| **预计工时** | 字段 `101586` **禁止**直接 PATCH`POST …/time/estimate``spentTime`)登记;删多余用 `DELETE …/time/estimate/{workitemId}/{estimateId}` |
| **实际工时** | `POST …/workitem/time`body **`actualTime`**(非 spentTime+ `gmtStart`/`gmtEnd`epoch ms 字符串);快轨待开发需求默认 **2** |
| **描述更新** | `PATCH …/workitem/{id}/document``{"content","formatType":"RICHTEXT"}` |
| **快轨标签** | 【交付】【设计】建单后 `PATCH propertyKey=tag``propertyValue` 与需求 tagId 一致(多标签逗号拼接) |
## 与描述双段的关系
页脚元信息写在「原始诉求」段末或整篇描述末尾均可,**不得覆盖** `## 产品说明AutoPRD` / `## 工作项编号(系统)` 区块(见 [description-split.md](description-split.md))。

View File

@@ -0,0 +1,63 @@
# 创建迭代并关联交付
产品经理可将已交棒(或已有编号)的多条【交付】任务打进同一云效迭代。
## 口令
```text
创建迭代:版本类型=副;交付任务=ONEOS-a,ONEOS-b,ONEOS-c名称前缀=统一运营管理平台PC端
创建迭代:版本类型=子;交付任务=ONEOS-99名称前缀=统一运营管理平台PC端
```
| 参数 | 规则 |
|---|---|
| 交付任务 | **1..N 个任务编号**(逗号分隔);禁止用标题凑数 |
| 版本类型 | 主 / 副 / 子;未点选则停下询问,禁止默认猜 |
| 名称前缀 | 可选;缺省 `统一运营管理平台PC端`。最终名=`{前缀}{版本号}` |
## 版本号 `V{主}.{副}.{子}`
| 版本类型 | 含义 | 递增 |
|---|---|---|
| **主** | 功能重制 | 主+1副→0子→0V1.3.2→V2.0.0 |
| **副** | 新功能上线 | 副+1子→0V1.3.2→V1.4.0 |
| **子** | bug/优化 | 子+1V1.3.2→V1.3.3 |
### 取基线再递增
1. 拉取当前项目云效迭代列表。
2. 从迭代**名称**解析 `V数字.数字.数字`;旧名 `V数字.数字` 视为 `.0`
3. 同名称前缀内取**最大**版本为基线(主→副→子比较);避免 PC 与小程序串号。
4. 按用户点选类型递增,写入新迭代名称。
5. 无一可解析版本:基线 `V0.0.0` 再递增主→V1.0.0副→V0.1.0子→V0.0.1);或口令显式给起始版本。
禁止:手填与规则冲突的版本号却声称自动生成;禁止用交付标题推断版本类型。
## 创建与关联
| 步骤 | 动作 |
|---|---|
| 1 | 算出新版本 → 拼迭代全名 |
| 2 | 创建迭代(起止日期口令未给则询问或用项目默认,禁止瞎填) |
| 3 | **只挂【交付】**N 个交付任务挂迭代;交付失败不得报完成 |
| 4 | 幂等:同名迭代已存在 → 不新建,补挂尚未关联的交付,回报「复用迭代」 |
| 5 | 回报迭代名、版本号、identifier、已关联交付编号、失败编号 |
**禁止**把需求挂进迭代(需求侧「迭代」字段保持空)。不挂【分析】/【设计】除非口令显式点名。
**不**在本步创建【开发】/【测试】。仍须 Plan 门禁。
### 挂接 API已通 · 校验走 `/extra`
```http
PATCH /projex/api/workitem/workitem/{id}?_input_charset=utf-8
{"workitemIdentifier":"{id}","propertyKey":"sprint","propertyValue":"{sprintId}","operateType":"COVER"}
```
校验(详情主接口**不**含 sprint勿用其判空
```http
GET /projex/api/workitem/workitem/{id}/extra?_input_charset=utf-8
result.sprint[].identifier
```
清空误挂的需求迭代:同上 PATCH`propertyValue:""` + `operateType:"COVER"`(或 `CLEAR`)。

View File

@@ -0,0 +1,63 @@
# 标准路径:待处理 → 待开发交棒
人员/状态等常量见 [../assets/runtime-ids.json](../assets/runtime-ids.json)。**项目空间**须按 [project-selection.md](project-selection.md) 点选,禁止默认直指。查重只用任务编号。
## 步骤 0创建需求
| 云效动作 | 落地 |
|---|---|
| 新建产品类需求 | POST 建单;标题 `【新增】`/`【优化】` |
| 需求描述 | **先** AutoRDO 清洗再写入 `## 原始诉求AutoRDO`;本步不写 AutoPRD |
| 默认状态 | **待处理**;不建任务、不改负责人 |
| 可选推进 | 口令点选目标状态;未选则停在待处理 |
## 步骤 1受理 → 已确认
| 云效动作 | 落地 |
|---|---|
| 状态 | 待处理 → **已确认** |
| 任务 | **仍不建**交付/分析/设计 |
若用户只「创建」未受理:只提示「受理后请推进至已确认」,不自动跳。
## 步骤 2分析中
| 对象 | 动作 |
|---|---|
| 【交付】 | 无则新建;标题 `【交付】`+需求标题;**ASSOCIATED→需求**(勿用 PARENT负责人=创建人/产品;**计划开始仅空时写当日**;不写计划完成;描述=`等待设计任务完成后自动填入`;更新编号区块 |
| 【分析】 | 新建;**TASK_SUB→交付**`parent`+`parentIdentifier`+`createWorkitemRelationInfo=TASK_SUB`);交付「子项」须可见;计划开始=当日(仅空时);负责人默认可=创建人;更新编号区块 |
| 需求 | 状态=`分析中` |
## 步骤 3设计中
| 对象 | 动作 |
|---|---|
| 【交付】 | 已存在则按编号复用;没有则补建;**不改交付计划开始**;不写交付计划完成 |
| 【设计】 | 新建;**TASK_SUB→交付**(同分析);计划开始=当日(仅空时);更新编号区块 |
| 【分析】 | **计划完成**=状态更新日;推算阶段日历工时(见 work-hours |
| 需求 | 状态=`设计中` |
## 步骤 4设计完成
| 对象 | 动作 |
|---|---|
| 【设计】 | 计划完成=当日;推算工时;任务→完成态 |
| 需求 | AutoPRD 写入 `## 产品说明`;挂 ZIP+截图;状态=`设计完成` |
| 【交付】 | 不换负责人;不改计划开始;不写计划完成;描述改为 AutoPRD 正文;同样挂附件 |
顺序与失败门禁见 [description-split.md](description-split.md)。
## 步骤 5待开发交棒本 Skill 终点 · 标准路径)
| 对象 | 动作 |
|---|---|
| 需求 | 状态=`待开发` |
| 【交付】 | 按**任务编号**定位;**负责人→何斐**;不改计划开始;不写计划完成 |
| 【分析】/【设计】 | 不新建;不改已有计划开始;前序未收口按步骤 3/4 处理 |
执行 [handoff-and-rollback.md](handoff-and-rollback.md) §交棒门禁。
**不做:** 【开发】/【测试】、仓库、分支、提测。
快轨 / 编号直推见专文。创建迭代见 [sprint.md](sprint.md)。

View File

@@ -0,0 +1,73 @@
# 计划时间与阶段日历工时
适用于【交付】/【分析】/【设计】统一口径。
## 用途
| 对象 | 计划开始→计划完成 |
|---|---|
| 【交付】 | 需求开工→上线全周期(本 Skill **不**写交付计划完成;上线由后续段) |
| 【分析】 | 分析阶段时长 |
| 【设计】 | 设计阶段时长 |
## 计划开始(不可篡改)
| 对象 | 首次写入 | 之后 |
|---|---|---|
| 【交付】 | 首次进入分析中且字段为空 → 当日 | **禁止覆盖** |
| 【分析】 | 首次创建且为空 → 当日 | **禁止覆盖** |
| 【设计】 | 首次创建且为空 → 当日 | **禁止覆盖** |
日期写入形态:中国时区正午 epoch ms 字符串,见 [../assets/runtime-ids.json](../assets/runtime-ids.json) `fields.plan_start`
## 计划完成
| 环节 | 写计划完成的对象 |
|---|---|
| 推进到设计中 | 【分析】= 状态更新日 |
| 推进到设计完成 | 【设计】= 状态更新日 |
| 无单快轨建设计 | 【设计】= 当日(同轮收口) |
| 编号直推收口 | 口令涉及的分析/设计若计划完成为空 → 当日 |
| 上线/关闭 | 【交付】计划完成(**本 Skill 暂不写** |
## 预计工时 = 阶段日历工时Lead Time
有计划完成且已有计划开始时,写入该对象云效「预计工时」:
```text
workdays = 0
从计划开始日到计划完成日(含首尾)逐日:
周六或周日 → 跳过(除非该日是调休补班)
法定放假日 → 跳过
调休补班日(含周末上班)→ 计入
其余周一~周五 → 计入
预计工时(小时) = workdays × 8
```
**禁止**用「(结束日 开始日 + 1× 8」日历天数算法。
### 语义与脚注(强制)
- 正式名称:**阶段日历工时****不是**投入人天/排期负荷。
- 任务描述末尾固定脚注:
`【系统】预计工时=阶段日历工时工作日×8非人力投入预估`
- 回报写「阶段日历工时 Hh」**禁止**写「需投入 Hh」。
- 本 Skill **不自动写**「人力投入预估」。
### 日历数据源
- 使用 [../assets/cn-workday-calendar.json](../assets/cn-workday-calendar.json)(按自然年;跨年须覆盖起止两侧年份)。
- 缺当年日历 → **停下**提示补日历;**禁止**静默按「仅去周末」算完并报成功。
- 计算脚本:[../scripts/workday_hours.py](../scripts/workday_hours.py)
```bash
python3 scripts/workday_hours.py 2026-03-06 2026-03-09
```
缺计划开始则只写结束、不推工时,回报提示。
## 示例
- 开始=周五、结束=下周一(无节假日)→ 五+一 → 16h
- 区间全在法定放假内 → 0h
- 某周日为调休补班且落在区间内 → 该日计入 8h

View File

@@ -0,0 +1,22 @@
# 工作项编号(系统)
## 权威源
需求描述固定区块(机器可解析;人工只读即可):
```markdown
## 工作项编号(系统)
- 交付ONEOS-xx
- 分析ONEOS-yy无则写无
- 设计ONEOS-zz无则写无
```
## 规则
1. **禁止**仅靠本地会话映射当唯一真相。
2. 每次新建/登记交付·分析·设计编号后,**立即 PATCH 更新该区块**(只改本区块,不动 AutoRDO / AutoPRD 正文)。
3. 操作顺序:口令显式编号 > 读本区块 > ASSOCIATED/SUB 反查校验。
4. 三者冲突 → 停下人工;**仍禁止按标题猜**。
5. 本地缓存仅加速,启动以云效该区块为准。
6. 区块出现两个交付编号 → 停止并列号请人合并。
7. 取消需求:关联任务标取消/废止;**不删**本区块(留痕)。

View File

@@ -0,0 +1,221 @@
{
"schema_version": 1,
"skill": "YunxiaoPM",
"verified_at": "2026-07-25",
"note": "YunxiaoPM constants. Project space MUST be user-selected (PJ gate); project.spaceIdentifier is last-known cache only — never auto-apply. See references/project-selection.md.",
"project": {
"selection_mode": "user_pick_required",
"name": null,
"name_aliases": [
"01_ONEOS",
"ONEOS",
"统一运营管理平台",
"统一运营管理平台PC端",
"统一运营管理平台 PC 端"
],
"spaceIdentifier": null,
"customCode": null,
"spaceType": "Project",
"organizationIdentifier": "697c54a19df7fdfa65466405",
"default_sprint_name_prefix": "统一运营管理平台PC端",
"list_api": "GET /projex/api/workspace/project/search/list",
"last_selected": {
"name": "01_ONEOS",
"spaceIdentifier": "1280be963a5a2cc126a4118dca",
"customCode": "ONEOS",
"note": "历史常用项;仅作预填建议,禁止未点选即使用"
},
"refreshed_at": "2026-07-25"
},
"projects_catalog": [
{
"name": "05_羚牛碳资产平台",
"identifier": "ff104a3bce09463da136a97999",
"customCode": "CARBON"
},
{
"name": "06_对外客户项目",
"identifier": "baca8b4d676c5af67e475caec0",
"customCode": "CUST"
},
{
"name": "07_LNBOX",
"identifier": "35e1e915a052379bbdfb993aac",
"customCode": "LNBOX"
},
{
"name": "04_AI应用",
"identifier": "d9002ea72c6c3a1a97b02be750",
"customCode": "AIAPP"
},
{
"name": "03_数据中台",
"identifier": "a801cef5c9a68fa051c07432c7",
"customCode": "DATA"
},
{
"name": "02_小羚羚APP",
"identifier": "db771a2cca07bed43b369af077",
"customCode": "XLLAPP"
},
{
"name": "01_ONEOS",
"identifier": "1280be963a5a2cc126a4118dca",
"customCode": "ONEOS"
},
{
"name": "敏捷研发示例项目",
"identifier": "65eca0c2e16a23939081e19e14",
"customCode": "DEMO"
}
],
"people": {
"wangmian": {
"displayName": "王冕",
"identifier": "6811df000601d2fea60144a9",
"role": "产品创建人/默认负责人"
},
"hefei": {
"displayName": "何斐",
"identifier": "695f0400562f09713f9c3a93",
"role": "待开发交棒【交付】负责人"
}
},
"tags": {
"故障管理": "ceb526a7343995577645317e9a",
"还车应结款": "4204960ce658c94b17abb7c5f6",
"工作台": "b62d21beac55c0b43389915eab",
"交车管理": "b6947b5aca82a8c759612ba039",
"合同管理": "23873be81931cb0dc1bf87a456",
"安全培训": "76988b5f73ef515de5930d59b9",
"证照管理": "11f4c2ec65901a8f3199c81706",
"还车管理": "1e0fce2d6929ff4ac13b310e97"
},
"status": {
"req": {
"待处理": "100005",
"已确认": "32",
"分析中": "154395",
"设计中": "156603",
"设计完成": "307012",
"待开发": "1582fc929d429111b925309493"
},
"task": {
"待处理": "100005",
"已完成": "100014"
},
"transit_api": "POST /projex/api/workitem/workitem/{id}/status/transit",
"fast_handoff_hops": [
"设计完成",
"待开发"
],
"note": "见 references/live-api.md禁止再用 updateStatus"
},
"workitem_types": {
"product_req": {
"name": "产品类需求",
"category": "Req",
"identifier": "9uy29901re573f561d69jn40"
},
"task": {
"name": "任务",
"category": "Task",
"identifier": "ba102e46bc6a8483d9b7f25c"
}
},
"priority": {
"紧急": "646004e97f54bb77fec7b455df",
"高": "95b89e0a524d9693e1f335ffe5",
"中": "fa155d1214f9f8db222d39db3b",
"低": "92924feff9c1085891e7511872"
},
"fields": {
"plan_start": {
"fieldIdentifier": "79",
"name": "计划开始时间",
"value_shape": "YYYY-MM-DD HH:mm:ss China wall time preferred; epoch ms string also accepted",
"example": "2026-07-27 12:00:00",
"update_api": "POST /projex/api/workitem/workitem/field/value/{workitemId} form fieldValueList=JSON"
},
"plan_end": {
"fieldIdentifier": "80",
"name": "计划完成时间",
"value_shape": "YYYY-MM-DD HH:mm:ss or epoch ms string",
"update_api": "POST /projex/api/workitem/workitem/field/value/{workitemId} form fieldValueList=JSON"
},
"estimated_hours": {
"fieldIdentifier": "101586",
"name": "预计工时",
"note": "不可直接改字段;须工时预估登记",
"create_api": "POST /projex/api/workitem/workitem/time/estimate body spentTime,type,recordUserIdentifier,workitemIdentifier",
"delete_api": "DELETE /projex/api/workitem/workitem/time/estimate/{workitemId}/{estimateId}",
"list_api": "GET /projex/api/workitem/workitem/time/estimate/list?workitemIdentifier="
},
"actual_hours": {
"name": "实际工时",
"note": "快轨待开发默认 2",
"create_api": "POST /projex/api/workitem/workitem/time body actualTime,type,recordUserIdentifier,workitemIdentifier,gmtStart,gmtEnd (epoch ms string)",
"list_api": "GET /projex/api/workitem/workitem/time/list?workitemIdentifier=",
"fast_track_default": 2,
"verified_at": "2026-07-27",
"verified_on": "ONEOS-293"
},
"fast_track": {
"req_estimated_hours": 2,
"req_actual_hours": 2,
"design_plan_start_end_same_day": true,
"design_description": "copy_req_document",
"delivery_description": "manual_sync_or_autoprd",
"delivery_design_same_tags_as_req": true,
"design_associated_to_req_after_task_sub": true,
"document_update_api": "PATCH /projex/api/workitem/workitem/{id}/document {content,formatType:RICHTEXT}"
},
"submit_department": {
"fieldIdentifier": "3132597a9718d1c282b7ba5a0c",
"name": "提交部门",
"format": "string input",
"update_api": "POST /projex/api/workitem/workitem/field/value/{workitemId} form fieldValueList=JSON",
"verified_at": "2026-07-27",
"verified_on": "ONEOS-293"
},
"submitter": {
"fieldIdentifier": "9e01269e96f91fbb97d36bf5b3",
"name": "提交人",
"format": "string input",
"update_api": "POST /projex/api/workitem/workitem/field/value/{workitemId} form fieldValueList=JSON",
"verified_at": "2026-07-27",
"verified_on": "ONEOS-293"
},
"tag": {
"fieldIdentifier": "tag",
"name": "标签",
"propertyKey": "tag"
}
},
"assignee_rules": {
"待开发_交付任务": "hefei",
"分析中_交付与分析": "creator",
"设计中_设计": "creator"
},
"relation": {
"delivery_to_req": "ASSOCIATED",
"stage_to_delivery": "TASK_SUB",
"create_field": "createWorkitemRelationInfo",
"forbid": [
"PARENT_as_关联项",
"ASSOCIATED_only_for_stage_tasks_without_TASK_SUB"
],
"note": "交付必须 ASSOCIATED→需求。分析/设计默认 TASK_SUB→交付子项 tab。二者同 create 互斥。见 references/live-api.md"
},
"delivery_placeholder": "等待设计任务完成后自动填入",
"task_title_prefixes": {
"delivery": "【交付】",
"analysis": "【分析】",
"design": "【设计】"
},
"publish_url": {
"shape": "{baseUrl}/{prototype-id}/index.html",
"forbid_prototypes_prefix": true,
"require_index_html": true
}
}

View File

@@ -0,0 +1,227 @@
#!/usr/bin/env python3
"""拉取云效项目列表(供 YunxiaoPMapp 门禁 PJ 点选。stdout = JSON。
无法对应时自动重拉一次:
python3 scripts/list_projects.py --match '01_ONEOS'
python3 scripts/list_projects.py --match-id 1280be963a5a2cc126a4118dca
"""
from __future__ import annotations
import argparse
import json
import urllib.parse
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Any
import requests
ROOT = Path(__file__).resolve().parents[1]
RUNTIME = json.loads((ROOT / "assets" / "runtime-ids.json").read_text())
ORG = RUNTIME.get("project", {}).get("organizationIdentifier", "697c54a19df7fdfa65466405")
WANG = RUNTIME.get("people", {}).get("wangmian", {}).get("identifier", "6811df000601d2fea60144a9")
ALIASES = [a.lower() for a in (RUNTIME.get("project", {}).get("name_aliases") or [])]
TZ = timezone(timedelta(hours=8))
def load_jar() -> dict[str, str]:
jar: dict[str, str] = {}
try:
import browser_cookie3
for domain in (".aliyun.com", "devops.aliyun.com", ".devops.aliyun.com"):
try:
for c in browser_cookie3.chrome(domain_name=domain):
jar[c.name] = c.value
except Exception:
pass
except Exception:
pass
if not jar.get("XSRF-TOKEN"):
p = Path("/tmp/yunxiao_cookies.json")
if p.exists():
raw = json.loads(p.read_text())
jar = (
raw
if isinstance(raw, dict) and "XSRF-TOKEN" in raw
else {c["name"]: c["value"] for c in raw.get("cookies", [])}
)
if not jar.get("XSRF-TOKEN"):
raise RuntimeError("缺少 XSRF-TOKEN请先在 Chrome 登录 devops.aliyun.com")
return jar
def fetch_projects() -> list[dict[str, Any]]:
jar = load_jar()
x = jar.get("XSRF-TOKEN", "")
xsrf = urllib.parse.unquote(x) if "%" in x else x
cookie = "; ".join(f"{k}={v}" for k, v in jar.items())
headers = {
"Cookie": cookie,
"x-xsrf-token": xsrf,
"X-XSRF-TOKEN": xsrf,
"Origin": "https://devops.aliyun.com",
"Referer": "https://devops.aliyun.com/projex",
"accept": "application/json",
}
extra = json.dumps(
{
"conditionGroups": [
[
{
"className": "user",
"fieldIdentifier": "users",
"format": "multiList",
"operator": "CONTAINS",
"value": [WANG],
}
],
[
{
"className": "string",
"fieldIdentifier": "scope",
"format": "list",
"operator": "CONTAINS",
"value": ["public"],
}
],
]
},
separators=(",", ":"),
)
params = {
"extraConditions": extra,
"conditions": json.dumps({"conditionGroups": [[]]}, separators=(",", ":")),
"orderBy": json.dumps(
{
"fieldIdentifier": "gmtCreate",
"format": "input",
"order": "desc",
"className": "date",
},
separators=(",", ":"),
),
"scope": "all",
"category": "Project",
"toPage": 1,
"pageSize": 100,
"_input_charset": "utf-8",
}
r = requests.get(
"https://devops.aliyun.com/projex/api/workspace/project/search/list",
headers=headers,
params=params,
timeout=30,
)
r.raise_for_status()
rows = r.json().get("result") or []
return [
{
"name": p.get("name"),
"identifier": p.get("identifier"),
"customCode": p.get("customCode"),
"logicalStatus": p.get("logicalStatus"),
"status": (p.get("status") or {}).get("displayName"),
"scope": p.get("scope"),
}
for p in rows
]
def match_projects(
projects: list[dict[str, Any]],
*,
query: str | None = None,
space_id: str | None = None,
) -> list[dict[str, Any]]:
if space_id:
sid = space_id.strip()
return [p for p in projects if p.get("identifier") == sid]
if not query:
return []
q = query.strip().lower()
hits: list[dict[str, Any]] = []
for p in projects:
name = (p.get("name") or "").lower()
code = (p.get("customCode") or "").lower()
if q == name or q == code or q in name or name in q:
hits.append(p)
continue
if q in ALIASES and (code == "oneos" or "oneos" in name or "运营" in name):
hits.append(p)
# de-dupe by identifier
seen: set[str] = set()
out: list[dict[str, Any]] = []
for p in hits:
i = p.get("identifier") or ""
if i in seen:
continue
seen.add(i)
out.append(p)
return out
def list_projects(
*,
match: str | None = None,
match_id: str | None = None,
) -> dict:
projects = fetch_projects()
payload: dict[str, Any] = {
"fetched_at": datetime.now(TZ).isoformat(),
"organizationIdentifier": ORG,
"count": len(projects),
"projects": projects,
"selection_required": True,
"refetched": False,
"note": "禁止默认直指;须 AskQuestion/Plan 点选后再写入 spaceIdentifier",
}
if not match and not match_id:
return payload
hits = match_projects(projects, query=match, space_id=match_id)
if len(hits) == 1:
payload["matches"] = hits
payload["match_status"] = "unique"
return payload
# 无法对应0 或多)→ 自动重拉一次
projects2 = fetch_projects()
hits2 = match_projects(projects2, query=match, space_id=match_id)
payload["projects"] = projects2
payload["count"] = len(projects2)
payload["refetched"] = True
payload["refetch_reason"] = "无法对应" if len(hits) != 1 else "unexpected"
if len(hits) == 0:
payload["refetch_reason"] = "首次0命中"
elif len(hits) > 1:
payload["refetch_reason"] = "首次多命中"
payload["matches"] = hits2
if len(hits2) == 1:
payload["match_status"] = "unique_after_refetch"
elif len(hits2) == 0:
payload["match_status"] = "none_after_refetch"
payload["note"] = "已自动重拉一次仍无法对应请用户从最新列表点选禁止再拉第3次"
else:
payload["match_status"] = "ambiguous_after_refetch"
payload["note"] = "已自动重拉一次仍多命中;请用户点选;禁止自动选定"
payload["fetched_at"] = datetime.now(TZ).isoformat()
return payload
def main() -> None:
ap = argparse.ArgumentParser(description="YunxiaoPMapp 项目列表 / 匹配(无法对应则重拉一次)")
ap.add_argument("--match", help="按项目名或 customCode 匹配")
ap.add_argument("--match-id", help="按 spaceIdentifier 匹配")
args = ap.parse_args()
print(
json.dumps(
list_projects(match=args.match, match_id=args.match_id),
ensure_ascii=False,
indent=2,
)
)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,190 @@
#!/usr/bin/env python3
"""标签候选列表(聚合工作项 tag + runtime未命中可 --match 后自动重拉一次。"""
from __future__ import annotations
import argparse
import json
import urllib.parse
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Any
import requests
ROOT = Path(__file__).resolve().parents[1]
RUNTIME = json.loads((ROOT / "assets" / "runtime-ids.json").read_text())
TZ = timezone(timedelta(hours=8))
def load_jar() -> dict[str, str]:
jar: dict[str, str] = {}
try:
import browser_cookie3
for domain in (".aliyun.com", "devops.aliyun.com", ".devops.aliyun.com"):
try:
for c in browser_cookie3.chrome(domain_name=domain):
jar[c.name] = c.value
except Exception:
pass
except Exception:
pass
if not jar.get("XSRF-TOKEN"):
p = Path("/tmp/yunxiao_cookies.json")
if p.exists():
raw = json.loads(p.read_text())
jar = (
raw
if isinstance(raw, dict) and "XSRF-TOKEN" in raw
else {c["name"]: c["value"] for c in raw.get("cookies", [])}
)
if not jar.get("XSRF-TOKEN"):
raise RuntimeError("缺少 XSRF-TOKEN")
return jar
def session() -> requests.Session:
jar = load_jar()
x = jar.get("XSRF-TOKEN", "")
xsrf = urllib.parse.unquote(x) if "%" in x else x
s = requests.Session()
s.headers.update(
{
"Cookie": "; ".join(f"{k}={v}" for k, v in jar.items()),
"x-xsrf-token": xsrf,
"X-XSRF-TOKEN": xsrf,
"Origin": "https://devops.aliyun.com",
"Referer": "https://devops.aliyun.com/projex",
"accept": "application/json",
"Content-Type": "application/json",
}
)
return s
def fetch_tags(space_id: str) -> list[dict[str, str]]:
s = session()
by_id: dict[str, str] = {}
for name, tid in (RUNTIME.get("tags") or {}).items():
by_id[tid] = name
body = {
"spaceIdentifier": space_id,
"spaceType": "Project",
"category": "Req",
"toPage": 1,
"pageSize": 100,
"conditions": json.dumps({"conditionGroups": [[]]}),
}
rows = (
s.post(
"https://devops.aliyun.com/projex/api/workitem/workitem/list?_input_charset=utf-8",
json=body,
timeout=30,
)
.json()
.get("result")
or []
)
for row in rows:
for t in row.get("tag") or []:
tid = t.get("identifier")
name = t.get("name") or t.get("displayName")
if tid and name:
by_id[tid] = name
# Task 再扫一页,补标签
body["category"] = "Task"
rows = (
s.post(
"https://devops.aliyun.com/projex/api/workitem/workitem/list?_input_charset=utf-8",
json=body,
timeout=30,
)
.json()
.get("result")
or []
)
for row in rows:
for t in row.get("tag") or []:
tid = t.get("identifier")
name = t.get("name") or t.get("displayName")
if tid and name:
by_id[tid] = name
return [{"name": n, "identifier": i} for i, n in sorted(by_id.items(), key=lambda x: x[1])]
def match_tags(tags: list[dict[str, str]], query: str) -> list[dict[str, str]]:
q = query.strip().lower()
hits = []
for t in tags:
name = (t.get("name") or "").lower()
if q == name or q in name or name in q:
hits.append(t)
return hits
def list_tags(*, space_id: str, match: str | None = None, prefer: str | None = None) -> dict[str, Any]:
tags = fetch_tags(space_id)
# prefer 置顶
if prefer:
prefer_l = prefer.strip().lower()
tags = sorted(
tags,
key=lambda t: (0 if (t.get("name") or "").lower() == prefer_l else 1, t.get("name") or ""),
)
out: dict[str, Any] = {
"fetched_at": datetime.now(TZ).isoformat(),
"spaceIdentifier": space_id,
"count": len(tags),
"tags": tags,
"refetched": False,
"note": "标签未命中须自动重拉一次并重生 4.A/B/C 选项;见 compact-select.md",
}
if not match:
return out
hits = match_tags(tags, match)
if len(hits) == 1:
out["matches"] = hits
out["match_status"] = "unique"
return out
# 无法对应 → 重拉一次
tags2 = fetch_tags(space_id)
if prefer:
prefer_l = prefer.strip().lower()
tags2 = sorted(
tags2,
key=lambda t: (0 if (t.get("name") or "").lower() == prefer_l else 1, t.get("name") or ""),
)
hits2 = match_tags(tags2, match)
out["tags"] = tags2
out["count"] = len(tags2)
out["refetched"] = True
out["refetch_reason"] = "首次0命中" if len(hits) == 0 else "首次多命中"
out["matches"] = hits2
if len(hits2) == 1:
out["match_status"] = "unique_after_refetch"
elif len(hits2) == 0:
out["match_status"] = "none_after_refetch"
out["note"] = "已自动重拉标签列表仍无法对应;请用户点选 4.x禁止再拉第3次"
else:
out["match_status"] = "ambiguous_after_refetch"
out["fetched_at"] = datetime.now(TZ).isoformat()
return out
def main() -> None:
ap = argparse.ArgumentParser()
ap.add_argument("--space", required=True, help="spaceIdentifier")
ap.add_argument("--match", help="标签名")
ap.add_argument("--prefer", help="置顶标签名")
args = ap.parse_args()
print(
json.dumps(
list_tags(space_id=args.space, match=args.match, prefer=args.prefer),
ensure_ascii=False,
indent=2,
)
)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,660 @@
#!/usr/bin/env python3
"""YunxiaoPM 极速真实建单 v5快轨描述/计划/标签/工时 2+2/设计 ASSOCIATED 补挂。"""
from __future__ import annotations
import json
import time
import urllib.parse
from concurrent.futures import ThreadPoolExecutor, as_completed
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Any
try:
import browser_cookie3
except ImportError: # pragma: no cover
browser_cookie3 = None
import requests
ROOT = Path(__file__).resolve().parents[1]
RUNTIME = json.loads((ROOT / "assets" / "runtime-ids.json").read_text())
STATUS = RUNTIME["status"]["req"]
TASK_STATUS = RUNTIME["status"]["task"]
FAST = RUNTIME.get("fields", {}).get("fast_track") or {}
SPACE = (
RUNTIME.get("project", {}).get("spaceIdentifier")
or (RUNTIME.get("project", {}).get("last_selected") or {}).get("spaceIdentifier")
)
if not SPACE:
raise RuntimeError(
"未选定项目 spaceIdentifier须先走门禁 PJ 点选,或设置 runtime project.last_selected"
)
REQ_TYPE = RUNTIME["workitem_types"]["product_req"]["identifier"]
TASK_TYPE = RUNTIME["workitem_types"]["task"]["identifier"]
HEFEI = RUNTIME["people"]["hefei"]["identifier"]
WANG = RUNTIME["people"].get("wangmian", {}).get("identifier", "6811df000601d2fea60144a9")
PRI = RUNTIME["priority"][""]
TAG_FAULT = RUNTIME.get("tags", {}).get("故障管理", "ceb526a7343995577645317e9a")
PLACEHOLDER = RUNTIME["delivery_placeholder"]
PROTO = "https://prototype.lnoneos.com/vehicle-fault-handling/index.html"
TZ = timezone(timedelta(hours=8))
TODAY = datetime.now(TZ).strftime("%Y-%m-%d")
NOON = f"{TODAY} 12:00:00"
EOD = f"{TODAY} 23:59:59"
NOON_MS = str(
int(datetime.now(TZ).replace(hour=12, minute=0, second=0, microsecond=0).timestamp() * 1000)
)
START_MS = str(
int(datetime.now(TZ).replace(hour=9, minute=0, second=0, microsecond=0).timestamp() * 1000)
)
END_MS = str(
int(datetime.now(TZ).replace(hour=11, minute=0, second=0, microsecond=0).timestamp() * 1000)
)
FAST_EST = int(FAST.get("req_estimated_hours", 2))
FAST_ACT = int(FAST.get("req_actual_hours", 2))
PENDING = STATUS["待处理"]
DESIGN_DONE = STATUS["设计完成"]
PENDING_DEV = STATUS["待开发"]
TASK_DONE = TASK_STATUS["已完成"]
_COOKIE = ""
_XSRF = ""
def load_auth() -> None:
global _COOKIE, _XSRF
jar: dict[str, str] = {}
if browser_cookie3:
for domain in (".aliyun.com", "devops.aliyun.com", ".devops.aliyun.com"):
try:
for c in browser_cookie3.chrome(domain_name=domain):
jar[c.name] = c.value
except Exception:
pass
if not jar:
p = Path("/tmp/yunxiao_cookies.json")
if p.exists():
raw = json.loads(p.read_text())
jar = (
raw
if isinstance(raw, dict) and "XSRF-TOKEN" in raw
else {c["name"]: c["value"] for c in raw.get("cookies", [])}
)
_COOKIE = "; ".join(f"{k}={v}" for k, v in jar.items())
x = jar.get("XSRF-TOKEN", "")
_XSRF = urllib.parse.unquote(x) if "%" in x else x
if not _XSRF:
raise RuntimeError("缺少 XSRF-TOKEN请先在 Chrome 登录 devops.aliyun.com")
def session() -> requests.Session:
s = requests.Session()
s.headers.update(
{
"Content-Type": "application/json",
"Cookie": _COOKIE,
"x-xsrf-token": _XSRF,
"X-XSRF-TOKEN": _XSRF,
"Origin": "https://devops.aliyun.com",
"Referer": f"https://devops.aliyun.com/projex/project/{SPACE}/req",
"accept": "application/json",
"User-Agent": "YunxiaoPM-live_create_fast/5.0",
"Connection": "keep-alive",
}
)
return s
def api(s: requests.Session, method: str, url: str, body: Any = None) -> dict:
r = s.request(method, url, json=body, timeout=60)
try:
return r.json()
except Exception:
r.raise_for_status()
raise
def create(s: requests.Session, payload: dict) -> dict:
url = "https://devops.aliyun.com/projex/api/workitem/workitem?_input_charset=utf-8"
j = api(s, "POST", url, payload)
r = j.get("result") or {}
if j.get("code") == 200 and isinstance(r, dict) and r.get("identifier"):
return r
j = api(s, "PUT", url, payload)
r = j.get("result") or {}
if j.get("code") == 200 and isinstance(r, dict) and r.get("identifier"):
return r
raise RuntimeError(f"create failed: {j}")
def get(s: requests.Session, wid: str) -> dict:
return api(
s,
"GET",
f"https://devops.aliyun.com/projex/api/workitem/workitem/{wid}?_input_charset=utf-8",
)["result"]
def apply_tag(s: requests.Session, wid: str, tag_id: str = TAG_FAULT) -> None:
j = api(
s,
"PATCH",
f"https://devops.aliyun.com/projex/api/workitem/workitem/{wid}?_input_charset=utf-8",
{
"workitemIdentifier": wid,
"propertyKey": "tag",
"propertyValue": tag_id,
"operateType": "COVER",
},
)
if j.get("code") != 200:
raise RuntimeError(f"tag failed {wid}: {j}")
def set_document(s: requests.Session, wid: str, html: str) -> None:
j = api(
s,
"PATCH",
f"https://devops.aliyun.com/projex/api/workitem/workitem/{wid}/document?_input_charset=utf-8",
{"content": html, "formatType": "RICHTEXT"},
)
if j.get("code") != 200 or j.get("errorMsg"):
raise RuntimeError(f"document failed {wid}: {j}")
def set_fields(s: requests.Session, wid: str, pairs: list[tuple[str, str]]) -> None:
data = urllib.parse.urlencode(
{
"fieldValueList": json.dumps(
[{"fieldIdentifier": k, "value": v} for k, v in pairs], ensure_ascii=False
)
}
)
r = s.post(
f"https://devops.aliyun.com/projex/api/workitem/workitem/field/value/{wid}?_input_charset=utf-8",
data=data,
headers={"Content-Type": "application/x-www-form-urlencoded"},
timeout=60,
)
j = r.json()
if j.get("code") != 200:
raise RuntimeError(f"field/value failed {wid}: {j}")
def set_estimate_hours(s: requests.Session, wid: str, hours: int, user: str = WANG) -> None:
est = api(
s,
"GET",
f"https://devops.aliyun.com/projex/api/workitem/workitem/time/estimate/list?workitemIdentifier={wid}",
).get("result") or []
for row in est:
eid = row.get("identifier")
if eid:
api(
s,
"DELETE",
f"https://devops.aliyun.com/projex/api/workitem/workitem/time/estimate/{wid}/{eid}",
)
j = api(
s,
"POST",
"https://devops.aliyun.com/projex/api/workitem/workitem/time/estimate?_input_charset=utf-8",
{
"workitemIdentifier": wid,
"spentTime": hours,
"type": "develop",
"description": "快轨默认预计工时",
"recordUserIdentifier": user,
"forCreate": False,
"containsRestDay": False,
},
)
if j.get("code") != 200:
raise RuntimeError(f"estimate failed {wid}: {j}")
def set_actual_hours(s: requests.Session, wid: str, hours: int, user: str = WANG) -> None:
j = api(
s,
"POST",
"https://devops.aliyun.com/projex/api/workitem/workitem/time?_input_charset=utf-8",
{
"workitemIdentifier": wid,
"actualTime": hours,
"type": "develop",
"description": "快轨默认实际工时",
"recordUserIdentifier": user,
"gmtStart": START_MS,
"gmtEnd": END_MS,
},
)
if j.get("code") != 200 or not j.get("result"):
raise RuntimeError(f"actual time failed {wid}: {j}")
def try_associate_to_req(s: requests.Session, stage_id: str, req_id: str) -> bool:
"""建后补 ASSOCIATED→需求。Cookie 下常失败,成功返回 True。"""
bodies = [
{"relationIdentifier": "ASSOCIATED", "toWorkitemIdentifier": req_id},
{
"relationIdentifier": "ASSOCIATED",
"fromWorkitemIdentifier": stage_id,
"toWorkitemIdentifier": req_id,
},
]
for body in bodies:
for url in (
f"https://devops.aliyun.com/projex/api/workitem/workitem/{stage_id}/relation/record?_input_charset=utf-8",
f"https://devops.aliyun.com/projex/api/workitem/v2/workitem/{stage_id}/relation/record?_input_charset=utf-8",
):
j = api(s, "POST", url, body)
if j.get("code") == 200 and j.get("result") not in (None, False):
if not (isinstance(j.get("result"), dict) and j["result"].get("status") in (404, 405)):
rows = list_associated(s, stage_id)
if req_id in {r.get("identifier") for r in rows}:
return True
return False
def transit(s: requests.Session, wid: str, from_status: str, to_status: str) -> None:
if from_status == to_status:
return
j = api(
s,
"POST",
f"https://devops.aliyun.com/projex/api/workitem/workitem/{wid}/status/transit?_input_charset=utf-8",
{"fromStatus": from_status, "toStatus": to_status},
)
if not (j.get("code") == 200 and j.get("result") is True):
raise RuntimeError(f"transit {wid} {from_status}->{to_status}: {j}")
def md_to_html(md: str) -> str:
parts = []
for line in md.splitlines():
if line.startswith("## "):
parts.append(f"<h2>{line[3:]}</h2>")
elif line.startswith("### "):
parts.append(f"<h3>{line[4:]}</h3>")
elif line.startswith("- "):
parts.append(f"<p>• {line[2:]}</p>")
elif line.strip():
parts.append(f"<p>{line}</p>")
return "".join(parts)
def req_document_html(s: requests.Session, rid: str) -> str:
w = get(s, rid)
return ((w.get("document") or {}).get("content") or w.get("description") or "").strip()
def req_payload(subject: str, html: str) -> dict:
return {
"subject": subject,
"description": html,
"formatType": "RICHTEXT",
"document": {"content": html, "formatType": "RICHTEXT"},
"spaceIdentifier": SPACE,
"space": SPACE,
"spaceType": "Project",
"workitemTypeIdentifier": REQ_TYPE,
"workitemType": REQ_TYPE,
"categoryIdentifier": "Req",
"category": "Req",
"assignedTo": WANG,
"fieldValueList": [
{"fieldIdentifier": "priority", "value": PRI},
{"fieldIdentifier": "assignedTo", "value": WANG},
],
"attachmentIdList": [],
"cloneFrom": None,
"createWorkitemRelationList": [],
}
def task_payload(
subject: str,
html: str,
assignee: str,
*,
plan_start: bool = True,
associated_req: str | None = None,
parent_delivery: str | None = None,
) -> dict:
fvl = [
{"fieldIdentifier": "priority", "value": PRI},
{"fieldIdentifier": "assignedTo", "value": assignee},
]
if plan_start:
fvl.append({"fieldIdentifier": "79", "value": NOON_MS})
payload: dict[str, Any] = {
"subject": subject,
"description": html,
"formatType": "RICHTEXT",
"spaceIdentifier": SPACE,
"space": SPACE,
"spaceType": "Project",
"workitemTypeIdentifier": TASK_TYPE,
"workitemType": TASK_TYPE,
"categoryIdentifier": "Task",
"category": "Task",
"assignedTo": assignee,
"fieldValueList": fvl,
"attachmentIdList": [],
"cloneFrom": None,
}
if parent_delivery:
payload["parent"] = parent_delivery
payload["parentIdentifier"] = parent_delivery
payload["createWorkitemRelationInfo"] = {
"relatedWorkitemIdentifier": parent_delivery,
"relatedToRelationIdentifier": "TASK_SUB",
}
else:
if not associated_req:
raise ValueError("associated_req required for delivery: ASSOCIATED→需求")
payload["createWorkitemRelationInfo"] = {
"relatedWorkitemIdentifier": associated_req,
"relatedToRelationIdentifier": "ASSOCIATED",
}
return payload
def list_associated(s: requests.Session, wid: str) -> list[dict]:
j = api(
s,
"GET",
f"https://devops.aliyun.com/projex/api/workitem/v2/workitem/{wid}/relation/workitem/list/by-relation-category?category=ASSOCIATED&isForward=true",
)
return j.get("result") or []
def assert_associated_to_req(s: requests.Session, wid: str, req_id: str, label: str) -> None:
rows = list_associated(s, wid)
ids = {r.get("identifier") for r in rows}
if req_id not in ids:
raise RuntimeError(
f"{label} 关联项未挂需求:期望 {req_id},实际 {[r.get('serialNumber') for r in rows]}"
)
AUTO_RDO = """## 原始诉求AutoRDO
运维需在故障处置页承接机器人上报的故障,完成处置、挂起与归档,并保留证据链;工作台相关统计口径需与处置页一致
待确认:
- 本期是否含真实短信/邮件通道(现口径一般为演示模板)
## 工作项编号(系统)
- 交付:待建
- 分析:待建
- 设计:待建
"""
def summarize_from_create(w: dict, *, status: str, assignee_name: str) -> dict:
return {
"serial": w.get("serialNumber"),
"id": w.get("identifier"),
"subject": w.get("subject"),
"status": status,
"assignee": assignee_name,
"parent": w.get("parentIdentifier"),
}
def build_normal() -> dict:
t0 = time.perf_counter()
s = session()
title = "【新增】故障处置YunxiaoPMapp标准·极速v2"
req = create(s, req_payload(title, md_to_html(AUTO_RDO + f"\n原型:{PROTO}\n")))
rid = req["identifier"]
with ThreadPoolExecutor(max_workers=2) as pool:
f_tag_r = pool.submit(apply_tag, session(), rid)
f_deliv = pool.submit(
create,
session(),
task_payload(
f"【交付】{title}",
f"<p>{PLACEHOLDER}</p>",
HEFEI,
associated_req=rid,
),
)
deliv = f_deliv.result()
f_tag_r.result()
did = deliv["identifier"]
with ThreadPoolExecutor(max_workers=3) as pool:
f_tag_d = pool.submit(apply_tag, session(), did)
f_ana = pool.submit(
create,
session(),
task_payload(
f"【分析】{title}",
"<p>分析阶段:故障处置台账、挂起归档与证据链。</p>",
WANG,
associated_req=rid,
parent_delivery=did,
),
)
f_des = pool.submit(
create,
session(),
task_payload(
f"【设计】{title}",
f"<p>设计阶段:对齐原型 {PROTO}</p>",
WANG,
associated_req=rid,
parent_delivery=did,
),
)
ana = f_ana.result()
des = f_des.result()
f_tag_d.result()
with ThreadPoolExecutor(max_workers=3) as pool:
list(
as_completed(
[
pool.submit(transit, session(), rid, PENDING, DESIGN_DONE),
pool.submit(transit, session(), ana["identifier"], PENDING, TASK_DONE),
pool.submit(transit, session(), des["identifier"], PENDING, TASK_DONE),
]
)
)
transit(s, rid, DESIGN_DONE, PENDING_DEV)
return {
"path": "normal",
"elapsed_s": round(time.perf_counter() - t0, 3),
"req": summarize_from_create(req, status="待开发", assignee_name="王冕"),
"delivery": summarize_from_create(deliv, status="待处理", assignee_name="何斐"),
"analysis": summarize_from_create(ana, status="已完成", assignee_name="王冕"),
"design": summarize_from_create(des, status="已完成", assignee_name="王冕"),
}
def build_fast(
*,
tag_id: str = TAG_FAULT,
has_prototype: bool = True,
delivery_html: str | None = None,
) -> dict:
"""无单快轨。
- 设计描述 = 需求 document
- 交付描述 = 手工同步需求正文(无原型)或传入 AutoPRD HTML禁止无故占位
- 设计 79/80=当日;交付 79=当日
- 需求/交付/设计同标签
- 需求预计/实际工时各 2
- 设计 TASK_SUB→交付后尝试 ASSOCIATED→需求
"""
t0 = time.perf_counter()
s = session()
title = "【新增】故障处置YunxiaoPM快轨·极速v5"
req_html = md_to_html(AUTO_RDO + (f"\n原型:{PROTO}\n" if has_prototype else "\n"))
req = create(s, req_payload(title, req_html))
rid = req["identifier"]
# 以落库 document 为准(与手动建需后读需求一致)
req_html = req_document_html(s, rid) or req_html
if delivery_html:
deliv_html = delivery_html
desc_source = "autoprd"
elif req_html.strip():
deliv_html = req_html
desc_source = "manual_sync"
else:
deliv_html = f"<p>{PLACEHOLDER}</p>"
desc_source = "placeholder"
with ThreadPoolExecutor(max_workers=2) as pool:
f_tag_r = pool.submit(apply_tag, session(), rid, tag_id)
f_deliv = pool.submit(
create,
session(),
task_payload(
f"【交付】{title}",
deliv_html,
HEFEI,
associated_req=rid,
),
)
deliv = f_deliv.result()
f_tag_r.result()
did = deliv["identifier"]
with ThreadPoolExecutor(max_workers=2) as pool:
f_tag_d = pool.submit(apply_tag, session(), did, tag_id)
f_des = pool.submit(
create,
session(),
task_payload(
f"【设计】{title}",
req_html,
WANG,
parent_delivery=did,
),
)
des = f_des.result()
f_tag_d.result()
des_id = des["identifier"]
apply_tag(s, des_id, tag_id)
# 计划时间设计起止当日交付开始当日create 已带 79再 field/value 加固)
set_fields(s, des_id, [("79", NOON), ("80", EOD)])
set_fields(s, did, [("79", NOON)])
# 设计关联项补挂需求(可能失败,回报 risk
design_assoc_ok = try_associate_to_req(s, des_id, rid)
with ThreadPoolExecutor(max_workers=2) as pool:
list(
as_completed(
[
pool.submit(transit, session(), rid, PENDING, DESIGN_DONE),
pool.submit(transit, session(), des_id, PENDING, TASK_DONE),
]
)
)
transit(s, rid, DESIGN_DONE, PENDING_DEV)
set_estimate_hours(s, rid, FAST_EST)
set_actual_hours(s, rid, FAST_ACT)
risk = None
if desc_source == "placeholder":
risk = "交付描述仍为占位"
if not design_assoc_ok:
risk = (risk + "" if risk else "") + "设计 ASSOCIATED→需求补挂失败Cookie须 UI/OpenAPI 兜底"
return {
"path": "fast",
"elapsed_s": round(time.perf_counter() - t0, 3),
"req": summarize_from_create(req, status="待开发", assignee_name="王冕"),
"delivery": summarize_from_create(deliv, status="待处理", assignee_name="何斐"),
"design": summarize_from_create(des, status="已完成", assignee_name="王冕"),
"analysis": None,
"delivery_desc_source": desc_source,
"design_associated_ok": design_assoc_ok,
"risk": risk,
}
def main() -> None:
auth0 = time.perf_counter()
load_auth()
auth_s = round(time.perf_counter() - auth0, 3)
wall0 = time.perf_counter()
with ThreadPoolExecutor(max_workers=2) as pool:
f_fast = pool.submit(build_fast)
f_normal = pool.submit(build_normal)
fast = f_fast.result()
normal = f_normal.result()
build_s = round(time.perf_counter() - wall0, 3)
s = session()
assert_associated_to_req(s, normal["delivery"]["id"], normal["req"]["id"], "normal.delivery")
assert_associated_to_req(s, fast["delivery"]["id"], fast["req"]["id"], "fast.delivery")
def assert_sub(delivery_id: str, child_id: str, label: str) -> None:
rows = api(
s,
"GET",
f"https://devops.aliyun.com/projex/api/workitem/v2/workitem/{delivery_id}/relation/workitem/list/by-relation-category?category=PARENT_SUB&isForward=true",
).get("result") or []
ids = {r.get("identifier") for r in rows}
if child_id not in ids:
raise RuntimeError(
f"{label} 未出现在交付子项:期望 {child_id},实际 {[r.get('serialNumber') for r in rows]}"
)
assert_sub(normal["delivery"]["id"], normal["analysis"]["id"], "normal.analysis")
assert_sub(normal["delivery"]["id"], normal["design"]["id"], "normal.design")
assert_sub(fast["delivery"]["id"], fast["design"]["id"], "fast.design")
verify = {
"normal_req": get(s, normal["req"]["id"])["status"]["displayName"],
"fast_req": get(s, fast["req"]["id"])["status"]["displayName"],
"normal_delivery_assignee": (
get(s, normal["delivery"]["id"]).get("assignedTo") or {}
).get("displayName"),
"fast_delivery_assignee": (get(s, fast["delivery"]["id"]).get("assignedTo") or {}).get(
"displayName"
),
"delivery_associated_ok": True,
"stage_tasks_as_sub_ok": True,
"fast_design_associated_ok": fast.get("design_associated_ok"),
}
out = {
"normal": normal,
"fast": fast,
"verify": verify,
"auth_elapsed_s": auth_s,
"wall_elapsed_s": build_s,
"created_at": datetime.now(TZ).isoformat(),
"mode": "live_create_fast_v5_fast_track_rules",
"opts": {
"create_includes_plan_start": True,
"skip_plan_end_on_create": True,
"tracked_transit_no_get": True,
"delivery_assignee_hefei_at_create": True,
"overlap_tag_with_create": True,
"fast_req_hours": f"{FAST_EST}+{FAST_ACT}",
"relation": "delivery ASSOCIATED→req; analysis/design TASK_SUB→delivery; design post ASSOCIATED→req",
"http": "requests.Session keep-alive",
},
}
Path("/tmp/yunxiao_pmapp_fast_v2_result.json").write_text(
json.dumps(out, ensure_ascii=False, indent=2)
)
print(json.dumps(out, ensure_ascii=False, indent=2))
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,92 @@
#!/usr/bin/env python3
"""Compute YunxiaoPMapp stage calendar hours = workdays × 8.
Usage:
python3 workday_hours.py YYYY-MM-DD YYYY-MM-DD
python3 workday_hours.py YYYY-MM-DD YYYY-MM-DD --calendar /path/to/cn-workday-calendar.json
"""
from __future__ import annotations
import argparse
import json
import sys
from datetime import date, datetime, timedelta
from pathlib import Path
def parse_day(s: str) -> date:
return datetime.strptime(s, "%Y-%m-%d").date()
def load_calendar(path: Path) -> dict:
data = json.loads(path.read_text(encoding="utf-8"))
years = data.get("years") or {}
holidays: set[str] = set()
makeup: set[str] = set()
for _y, block in years.items():
holidays.update(block.get("holidays") or [])
makeup.update(block.get("workdays_on_weekend") or [])
return {"holidays": holidays, "makeup": makeup, "years": set(years.keys())}
def ensure_years_covered(start: date, end: date, years: set[str]) -> None:
y = start.year
while y <= end.year:
if str(y) not in years:
raise SystemExit(
f"缺少 {y} 年日历:请在 assets/cn-workday-calendar.json 补全后再计算。"
"禁止仅去周末静默估算。"
)
y += 1
def is_workday(d: date, holidays: set[str], makeup: set[str]) -> bool:
key = d.isoformat()
if key in holidays:
return False
if key in makeup:
return True
return d.weekday() < 5 # Mon=0 .. Fri=4
def count_workdays(start: date, end: date, holidays: set[str], makeup: set[str]) -> int:
if end < start:
raise SystemExit("结束日早于开始日")
n = 0
cur = start
while cur <= end:
if is_workday(cur, holidays, makeup):
n += 1
cur += timedelta(days=1)
return n
def main() -> None:
parser = argparse.ArgumentParser(description="阶段日历工时 = 工作日×8")
parser.add_argument("start", help="计划开始 YYYY-MM-DD")
parser.add_argument("end", help="计划完成 YYYY-MM-DD")
parser.add_argument(
"--calendar",
default=str(Path(__file__).resolve().parent.parent / "assets" / "cn-workday-calendar.json"),
help="日历 JSON 路径",
)
args = parser.parse_args()
start = parse_day(args.start)
end = parse_day(args.end)
cal = load_calendar(Path(args.calendar))
ensure_years_covered(start, end, cal["years"])
days = count_workdays(start, end, cal["holidays"], cal["makeup"])
hours = days * 8
out = {
"start": start.isoformat(),
"end": end.isoformat(),
"workdays": days,
"stage_calendar_hours": hours,
"label": "阶段日历工时工作日×8非人力投入预估",
}
print(json.dumps(out, ensure_ascii=False, indent=2))
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,63 @@
# 标准路径:待处理 → 待开发交棒
项目常量见 [../assets/runtime-ids.json](../assets/runtime-ids.json)。查重只用任务编号。
## 步骤 0创建需求
| 云效动作 | 落地 |
|---|---|
| 新建产品类需求 | POST 建单;标题 `【新增】`/`【优化】` |
| 需求描述 | **先** AutoRDO 清洗再写入 `## 原始诉求AutoRDO`;本步不写 AutoPRD |
| 默认状态 | **待处理**;不建任务、不改负责人 |
| 可选推进 | 口令点选目标状态;未选则停在待处理 |
## 步骤 1受理 → 已确认
| 云效动作 | 落地 |
|---|---|
| 状态 | 待处理 → **已确认** |
| 任务 | **仍不建**交付/分析/设计 |
若用户只「创建」未受理:只提示「受理后请推进至已确认」,不自动跳。
## 步骤 2分析中
| 对象 | 动作 |
|---|---|
| 【交付】 | 无则新建;标题 `【交付】`+需求标题;**ASSOCIATED→需求**(勿用 PARENT负责人=创建人/产品;**计划开始仅空时写当日**;不写计划完成;描述=`等待设计任务完成后自动填入`;更新编号区块 |
| 【分析】 | 新建;**TASK_SUB→交付**`parent`+`parentIdentifier`+`createWorkitemRelationInfo=TASK_SUB`);交付「子项」须可见;计划开始=当日(仅空时);负责人默认可=创建人;更新编号区块 |
| 需求 | 状态=`分析中` |
## 步骤 3设计中
| 对象 | 动作 |
|---|---|
| 【交付】 | 已存在则按编号复用;没有则补建;**不改交付计划开始**;不写交付计划完成 |
| 【设计】 | 新建;**TASK_SUB→交付**(同分析);计划开始=当日(仅空时);更新编号区块 |
| 【分析】 | **计划完成**=状态更新日;推算阶段日历工时(见 work-hours |
| 需求 | 状态=`设计中` |
## 步骤 4设计完成
| 对象 | 动作 |
|---|---|
| 【设计】 | 计划完成=当日;推算工时;任务→完成态 |
| 需求 | AutoPRD 写入 `## 产品说明`;挂 ZIP+截图;状态=`设计完成` |
| 【交付】 | 不换负责人;不改计划开始;不写计划完成;描述改为 AutoPRD 正文;同样挂附件 |
顺序与失败门禁见 [description-split.md](description-split.md)。
## 步骤 5待开发交棒本 Skill 终点 · 标准路径)
| 对象 | 动作 |
|---|---|
| 需求 | 状态=`待开发` |
| 【交付】 | 按**任务编号**定位;**负责人→何斐**;不改计划开始;不写计划完成 |
| 【分析】/【设计】 | 不新建;不改已有计划开始;前序未收口按步骤 3/4 处理 |
执行 [handoff-and-rollback.md](handoff-and-rollback.md) §交棒门禁。
**不做:** 【开发】/【测试】、仓库、分支、提测。
快轨 / 编号直推见专文。创建迭代见 [sprint.md](sprint.md)。

View File

@@ -0,0 +1,146 @@
---
name: oneos-autoprd
description: >-
OneOS AutoPRD: generates PM-facing requirements (总览/目标/边界/角色/用户故事
起点→运作→闭环/故事点/正逆向/流程图/关键逻辑/状态/风险/交付) and syncs Axhub Make
annotation PRD. On 需求定稿/本轮定稿 appends functional changelog with auto
V主.副.子 (user 主/副/子 override wins). With YunxiaoPMapp design-complete,
writes Markdown into 【交付】 by task number (not at create; placeholder until then).
Use for AutoPRD, prototypes, 产品说明, 本轮定稿. Never create same-titled stage
tasks; never load yunxiao-requirement-lifecycle—cloud combo is YunxiaoPMapp only.
---
# AutoPRDoneos-autoprd
为 OneOS 业务模块生成**产品经理可读、可评审、可排期**的需求说明,并**自动挂到 Axhub Make 标注工具 → 原型目录**。
另支持:**本轮定稿 / 需求定稿**时汇总功能变更并**自动递增 PRD 版本号**;与 **`$YunxiaoPMapp`** 组合时,在**设计完成**(或显式同步交付)把 Markdown 写入【交付】任务描述。
**禁止加载** `yunxiao-requirement-lifecycle`。云效状态机与【交付】/【分析】/【设计】树**只**由 YunxiaoPMapp 负责;本 Skill **不**建同名无前缀阶段任务。
颗粒度:讲清做什么、谁用、故事点、正逆向、流程图与关键业务逻辑;**不写**表结构、接口、字段代码名、文件路径、实现清单。
## 何时使用(含自动触发)
**主动调用**
- AutoPRD、OneOS 需求说明、整模块 PRD、故事点 + 流程图、产品说明
**改原型时必须自动跟进**
- 修改 `src/prototypes/<id>/` 下页面、交互、文案、判定、验收相关内容
- 同一轮同步更新 PRD Markdown + 标注目录;**纯样式且无产品语义变化可跳过全量重写**
**需求定稿时(强制)**
- 关键字:`需求定稿` / `定稿` / `确认定稿` / `本次定稿` / **`本轮定稿`**
- 执行 [references/release-changelog.md](references/release-changelog.md):第 10 章 + `prdVersion` 基线
**与 YunxiaoPMapp 组合(强制 · 唯一云效组合)**
- 设计完成或完善「产品说明」:先本 Skill 落盘 MD再由 YunxiaoPMapp / 本 Skill 按 [yunxiao-description.md](references/yunxiao-description.md) 写入需求 `## 产品说明AutoPRD`**不覆盖** `## 原始诉求AutoRDO` / `## 工作项编号(系统)`
- **创建【交付】时不写 PRD 正文**(占位由 YunxiaoPMapp 写入);设计完成或口令「同步交付说明」时按 [yunxiao-delivery-sync.md](references/yunxiao-delivery-sync.md) 用任务**编号**回填【交付】
- 入库前聊天/录音清洗:先 `$AutoRDO`,再 YunxiaoPMapp 记录需求
## 工作流
### 主流程(写/同步 PRD
1. **定模块**OneOS 模块名与 `src/prototypes/<prototype-id>/`
2. **读上下文(只取产品语义)**
- 用户说明、已确认口径、原型标注、`.spec/`、业务条线说明(`lines.ts`
- 忽略实现细节;字段名/接口改写成业务语言。
3. **收敛边界**:做什么 / 不做什么、外部依赖、与其它模块关系。
4. **按模板成文**:见「输出结构」与 [references/template.md](references/template.md)。
5. **落盘 + 标注同步(强制)** — [references/annotation-sync.md](references/annotation-sync.md)。
| 顺序 | 动作 |
|------|------|
| A | 写/更新 `src/prototypes/<id>/.spec/requirements-prd.md` |
| B | 写/更新 `src/resources/prd/<id>-autoprd.md` |
| C | 更新 `annotation-source.json` **顶层** `directory.nodes`PRD 全文 + 推荐分章) |
| D | 若存在 `scripts/sync-annotation-directory.mjs`,执行之 |
6. **交付说明**:路径、标注入口、故事点合计、开放问题/假设。
### 定稿流程
见 [references/release-changelog.md](references/release-changelog.md)。含自动 `V主.副.子`**用户显式指定主/副/子时以用户为准**。
### 云效需求「产品说明」(与 YunxiaoPMapp 双段模板)
见 [references/yunxiao-description.md](references/yunxiao-description.md)。
### 云效【交付】回填(设计完成 · 非创建时)
见 [references/yunxiao-delivery-sync.md](references/yunxiao-delivery-sync.md)。
## 写作硬约束
**必须写(映射用户概要)**
| 概要能力 | 落在章节 |
|---|---|
| 总览 | §1 一句话与目标 |
| 目标 / 边界 | §12 |
| 角色 | §3 |
| 用户故事(起点→运作→闭环)+ 故事点 | §4 |
| 正逆向流程 | §5 |
| 关键逻辑 / 状态 / 风险 | §6及验收相关 |
| 流程图 | §7 |
| 交付 | §9 交付口径 |
| 定稿变更 | §10 |
另:验收清单 §8对象存储预览链接形态 `{baseUrl}/{prototype-id}/index.html`(禁止加 `prototypes/` 前缀、禁止去掉 `index.html`)。
**禁止写**
- 数据库表、字段名、接口路径、代码路径、组件名、存储 key
- 变更记录里的样式/UI/表结构优化
- 引导加载 `yunxiao-requirement-lifecycle` 或「同名阶段任务」建单
## 用户故事口径(强制 · 对齐业务条线说明)
真相源:业务条线说明(`lease-business-line-overview` / `lines.ts`)。
主叙述:**起点 → 怎么运作 → 闭环**(不要用「作为…我希望…」宽表作主叙述)。
## 输出结构
完整模板:[references/template.md](references/template.md)。
```markdown
# <模块名> · 产品需求说明(全模块)
## 1. 一句话与目标
## 2. 模块边界(最重要)
## 3. 用户与角色
## 4. 用户故事与故事点(业务条线说明口径)
## 5. 功能模块说明(正向 / 逆向)
## 6. 关键业务逻辑(必须对齐)
## 7. 总览流程图
## 8. 验收清单
## 9. 交付口径
## 10. 功能变更记录 ← 定稿维护;含 V主.副.子
```
## 质量自检
- [ ] 产品经理不看代码也能评审
- [ ] 用户故事为起点 / 怎么运作 / 闭环
- [ ] `.spec/requirements-prd.md` + 标注目录已同步
- [ ] 定稿时:第 10 章含版本号 + `autoprd-baseline.json``prdVersion`
- [ ] 与 YunxiaoPMapp 设计完成:【交付】按**编号**回填,创建时未提前灌 MD
- [ ] 全文无 `yunxiao-requirement-lifecycle` 引导;无同名阶段任务建单
- [ ] 变更记录无样式/UI/表结构废话
## 参考
- 定稿与版本:[references/release-changelog.md](references/release-changelog.md)
- 云效产品说明:[references/yunxiao-description.md](references/yunxiao-description.md)
- 【交付】回填:[references/yunxiao-delivery-sync.md](references/yunxiao-delivery-sync.md)
- 标注同步:[references/annotation-sync.md](references/annotation-sync.md)
- 模板:[references/template.md](references/template.md)
- 故事示例:[references/granularity-example.md](references/granularity-example.md)
- 业务条线:`src/prototypes/lease-business-line-overview/lines.ts`
- 云效组合(唯一):`$YunxiaoPMapp`
- 入库清洗:`$AutoRDO`

View File

@@ -0,0 +1,98 @@
# Axhub 标注目录同步(强制)
使用 OneOS AutoPRD 时,除资源库归档外,**必须**把 PRD 挂到 Axhub Make 标注工具的「原型目录」里,用户才能在右侧面板直接打开。
## 落点(三份必须一致)
| # | 路径 | 作用 |
|---|------|------|
| 1 | `src/prototypes/<prototype-id>/.spec/requirements-prd.md` | **主真相**:产品可读 PRD 全文 |
| 2 | `src/prototypes/<prototype-id>/annotation-source.json`**顶层** `directory.nodes` | **标注目录入口**:面板里可见的 Markdown/PRD |
| 3 | `src/resources/prd/<prototype-id>-autoprd.md` | 资源库归档(可选但默认写) |
可选:复杂判定另写 `.spec/<topic>.md`,目录里再挂一条,并在 PRD 里链过去(与 `business-logic-documentation` 一致)。
## ⚠️ 目录必须写在文档顶层(常见踩坑)
Wire format`prototype-annotation` 一致):
```json
{
"documentVersion": 1,
"format": "axhub-annotation-source",
"data": { "version": 2, "prototypeName": "...", "nodes": [] },
"markdownMap": {},
"assetMap": {},
"directory": { "nodes": [] }
}
```
| 正确 | 错误 |
|------|------|
| 顶层 `directory.nodes` | 只写在 `data.directory` |
| `PrototypeAnnotationHost` / Make 读的是 `source.directory` | 写在 `data` 下时右侧「原型目录」为空 |
若误写在 `data.directory`:迁移到顶层 `directory`,并删除 `data.directory`,避免双源。
## 目录节点写法(推荐)
在说明根 `folder``children` **靠前**插入或更新:
```json
{
"type": "markdown",
"id": "<prefix>-doc-prd",
"title": "产品需求说明PRD",
"markdownPath": ".spec/requirements-prd.md",
"markdown": "<与 .spec/requirements-prd.md 相同的全文>"
}
```
### 分章节 PRD推荐便于右侧目录浏览
在「产品需求说明PRD」旁增加文件夹 **「PRD 分章」**,按 PRD 的 `##` 一级标题拆成多个 `markdown` 子节点(标题用章节名,正文为该章全文)。专题规格(`.spec/<topic>.md`)放在 **「专题规格」** 文件夹。
参考结构:
```text
folder <模块>说明
markdown 产品需求说明PRD ← 全文
folder PRD 分章
markdown 1. 一句话与目标
markdown 2. 模块边界
folder 专题规格
markdown <topic 标题>
```
`scripts/sync-annotation-directory.mjs` 的原型:改 PRD / `.spec` 后**必须执行**该脚本再生目录。
定稿后第 10 章「功能变更记录」必须进入 PRD 全文节点若有「PRD 分章」,同步该章节点。详见 [release-changelog.md](release-changelog.md)。
约定:
- `id``<短前缀>-doc-prd`(如 `ipc-doc-prd``wb-doc-prd``h5-va-doc-prd`
- `title`优先「产品需求说明PRD已有「PRD」可保留不改名
- **同时写** `markdownPath` + `markdown`:构建可内联路径,运行时目录也能直接读到正文
- 若已有同 id / 同标题节点:只更新正文与 path不新建重复入口
- 遵守 `prototype-annotation-layout`:目录以 `markdown` 为主,不要用 `link`/`route` 顶替 PRD
## 增量改原型时怎么更新
1. 根据改动的文件路径确定 `<prototype-id>`
2. 读现有 `.spec/requirements-prd.md`(没有则按 AutoPRD 模板新建)。
3. 只改受影响章节(故事、正逆向、关键逻辑、验收);其余保留。
4. 回写 `.spec` + `resources/prd` + **顶层** `annotation-source.json``directory`(正文与文件一致;含分章节点)。
5. 若原型有 `scripts/sync-annotation-directory.mjs`,改完后执行它。
## 可跳过全量重写的情况
纯样式、无文案/无流程/无判定变化的微调:不必重写整份 PRD但若改了用户可见文案或交互结果仍须同步对应段落与目录节点。
## 验收
- [ ] `.spec/requirements-prd.md` 存在且为最新
- [ ] `annotation-source.json` **顶层**有 `directory.nodes`(不是只在 `data` 下)
- [ ] 标注目录能打开「产品需求说明PRD」且内容与文件一致
- [ ] 若有「PRD 分章」:各章可单独打开
- [ ] 用户故事仍为业务条线说明口径(起点 / 怎么运作 / 闭环)

View File

@@ -0,0 +1,58 @@
# 颗粒度标杆与用户故事口径
## 用户故事:对齐「业务条线说明」页面
页面:`/prototypes/lease-business-line-overview`
数据:`src/prototypes/lease-business-line-overview/lines.ts`
每个能力卡片的产品叙述结构:
```text
责任部门roles
→ 起点start
→ 怎么运作process[],有序)
→ 关键结果outcomes可选
→ 闭环closure
```
AutoPRD 第 4 章必须用同一套结构写用户故事,而不是「作为…我希望…」宽表。
### 示例(保险采购 · 交车合规,示意)
#### US · 保险有效才允许交车
- **角色**:采购部、运维部
- **起点**:采购或运营维护车辆交强险与商业险台账,作为交车前置合规数据。
- **怎么运作**
1. 在保险采购维护一车一档险种台账(录入 / 识别 / 导入)。
2. 交车时系统校验交强 + 商业是否均为正常或临期。
3. 不合规则拦截交车并给出可理解原因。
- **关键结果**`允许交车` / `禁止交车 · 保险异常`
- **闭环**:交车合规与台账一致、可追溯;异常车辆不能进入履约运营。
- **排期(可选)**US-17 · 规模 M · 作为采购/运维,我想维护交强+商业险并在交车时校验,以便不合规车辆无法交车。
### 反例(不要作为主叙述)
| 编号 | 用户故事 | SP |
|------|----------|----|
| B1 | 作为运营,我能看到失败原因 | 2 |
↑ 信息太扁,缺少起点、协作步骤与闭环结果。
---
## AutoPRD 其余层次(仍要对齐)
1. 一句话 + 目标/非目标
2. 模块边界(独立业务线写清「不自动同步」)
3. 角色表(命名对齐业务条线)
4. **用户故事:起点 / 怎么运作 / 闭环** + SP/规模
5. 分模块正逆向
6. 关键业务逻辑
7. mermaid 流程图
8. 验收清单
9. 交付口径
## 刻意不写
- 表结构、接口、代码路径
- 用实现指令代替业务闭环描述

View File

@@ -0,0 +1,95 @@
# 功能变更记录(定稿触发)+ PRD 版本号
用户回复**定稿关键字**后,必须生成「自上次定稿以来」的功能变更日志,追加到 PRD **最下方**,按规则递增 **`prdVersion`V主.副.子)**,并更新定稿基线。
## 触发关键字(命中任一)
`需求定稿` · `定稿` · `确认定稿` · `本次定稿` · **`本轮定稿`**
(可带模块名,如「保险采购本轮定稿」。可附带 `版本类型=主|副|子`。)
## 写什么 / 不写什么
| 要写(产品发版视角) | 不写 |
|----------------------|------|
| 哪个功能做了什么修改 | 布局、页面样式、UI 设计优化 |
| 变更了什么业务逻辑 / 流程 / 验收口径 | 「优化了哪些表」「改了哪些字段/接口」 |
| 用户可感知的交互结果变化 | 纯样式、动效、无语义文案微调 |
## 版本号 `V{主}.{副}.{子}`
基线字段 `prdVersion`(无则视为 `V0.0.0`)。有功能/逻辑增量时递增;**无增量则版本号不变**。
### 判定优先级
1. **用户覆盖(优先)**
口令或对话显式指定「主 / 副 / 子」→ **以用户为准**,不再自动改判。
定稿块首行写:`判定=用户指定·主`(或副/子)。
2. **自动判定(用户未指定时)**
- **主+1**副→0子→0跨模块边界变化、主流程/状态机重做、角色权限模型大改、验收口径整体推翻等「大改动」≥1 条主导。
- **副+1**子→0能力增删改、逻辑/文案产品语义变化、故事点级功能优化(**默认多数定稿**)。
- **子+1**:仅小幅逻辑澄清;若用户明确「本轮定稿」且变更非空且未指定类型 → **至少副+1**(不用子)。
- 定稿块首行写:`判定=主:…` / `判定=副:…` / `判定=子:…`(须写依据,禁止无依据猜)。
3. **无功能增量**
版本号不变;正文写「本轮无功能/逻辑增量(仅样式或未达产品语义变更)」或「首版定稿」(无基线且首版可落到 `V1.0.0` 若视为首次发布——首版有实质内容时用主从 `V0.0.0``V1.0.0`)。
## 落点
1. **PRD 文末章节**
`src/prototypes/<id>/.spec/requirements-prd.md``## 10. 功能变更记录`
新定稿块插在该章**最上方**。
2. **定稿基线**
`src/prototypes/<id>/.spec/autoprd-baseline.json`
```json
{
"prototypeId": "insurance-procurement",
"prdVersion": "V1.2.0",
"lastConfirmedAt": "2026-07-21T12:00:00+08:00",
"lastConfirmedLabel": "定稿 · V1.2.0 · 2026-07-21",
"summaryBullets": ["…", "…"]
}
```
3. **标注目录**同步「产品需求说明PRD」全文节点。
4. **云效**(若本轮走 YunxiaoPMapp按 [yunxiao-description.md](yunxiao-description.md) 更新需求产品说明;**禁止**加载 `yunxiao-requirement-lifecycle`
## 定稿工作流
1. 确认 `<prototype-id>`
2. 读 PRD 与 `autoprd-baseline.json`(无基线 → 首版;`prdVersion` 缺省 `V0.0.0`)。
3. 收集自 `lastConfirmedAt` 以来的产品语义变更;过滤样式/表结构。
4. 判定版本类型(用户指定优先)→ 计算新 `prdVersion`
5. 追加 `### 定稿 · V{x.y.z} · YYYY-MM-DD`(首行判定理由 + 条目)。
6. 更新基线 JSONannotation-sync。
7. 回报新版本号、判定理由、条目数、PRD 路径。
## PRD 章节格式
```markdown
## 10. 功能变更记录
> 产品经理原型发版记录。仅记功能与业务逻辑变更;不含样式/UI/表结构。
### 定稿 · V1.2.0 · 2026-07-21
判定=副:新增比价失败明细可点开
- 「识别失败」:失败数可点击查看失败文件与原因
-
### 定稿 · V1.1.0 · 2026-07-10
判定=用户指定·副
-
```
## 与日常改原型的关系
- **改原型过程中**:增量更新第 19 章;**不必**每改一次写第 10 章。
- **用户说定稿时**:才汇总第 10 章并刷新版本与基线。

View File

@@ -0,0 +1,181 @@
# OneOS AutoPRD 输出模板
复制下列结构填写。方括号为占位。**第 4 章用户故事必须用业务条线说明口径。**
## 概要能力 → 章节映射
| 用户概要 | 本模板位置 |
|---|---|
| 总览 | §1 一句话与目标 |
| 目标 / 边界 | §12 |
| 角色 | §3 |
| 用户故事(起点→运作→闭环)/ 故事点 | §4 |
| 正逆向流程 | §5 |
| 状态 / 风险 / 关键逻辑 | §6可分小节写状态机与风险 |
| 流程图 | §7 |
| 交付 | §9 |
| 定稿变更与版本 | §10见 release-changelog |
状态与风险也可在 §6 下设 `### 状态` / `### 风险` 短节,避免另起大结构推翻存量 PRD。
```markdown
# <模块名> · 产品需求说明(全模块)
## 1. 一句话与目标
**一句话**
<用一句话说明模块解决什么>
**要解决的问题**
-
**本期目标**
1.
2.
**非目标(本期不做)**
-
## 2. 模块边界(最重要)
(可选 mermaid模块与外部系统关系
| 业务线 / 子域 | 做什么 | 不做什么 |
|---------------|--------|----------|
| … | … | … |
**外部依赖(产品口径)**
| 依赖方 | 交互方式 | 产品要求 |
|--------|----------|----------|
| … | … | … |
**关键约束**
-
## 3. 用户与角色
| 角色 | 主要目标 |
|------|----------|
| … | … |
> 角色名优先与「业务条线说明」一致(如业务管理组、采购部、运维部)。
## 4. 用户故事与故事点(业务条线说明口径)
> 故事点 / 规模供排期参考,可按团队基准调整。合计约 **N SP**(或 S/M/L 汇总说明)。
按 Epic 或能力单元分组。**每一条**按下面四块写(对齐业务条线说明页:责任部门 → 起点 → 怎么运作 → 闭环):
### Epic A · <名称>(约 N SP
#### A1 · <能力标题>
- **角色**:…
- **起点**:…
- **怎么运作**
1.
2.
3.
- **关键结果**(可选):`可…` / `禁止…`
- **闭环**:…
- **排期(可选)**US-xx · 规模 S/M/L · 「作为…,我想…,以便…」
#### A2 · <能力标题>
### Epic B · …
## 5. 功能模块说明(正向 / 逆向)
### 5.x <功能名>
**正向**
1.
2.
**逆向 / 边界**
| 情况 | 系统表现 |
|------|----------|
| … | … |
## 6. 关键业务逻辑(必须对齐)
### 6.x <规则名>
用编号优先级、表格或短列表写清业务规则。
## 7. 总览流程图
```mermaid
flowchart TB
home[入口] --> a[能力A]
home --> b[能力B]
```
## 8. 验收清单(产品 / 测试)
**子域 A**
- [ ]
## 9. 交付口径
> <一段可贴需求单开头的浓缩描述>
## 10. 功能变更记录
> 产品经理原型发版记录。仅记功能与业务逻辑变更;不含样式/UI/表结构。
> 由「需求定稿」关键字触发追加;日常改原型不强制每改必写。详见 [release-changelog.md](release-changelog.md)。
### 定稿 · V{x.y.z} · YYYY-MM-DD
判定=<主|副|子|用户指定·…><一行依据>
- 「<能力名>」:<做了什么 / 逻辑如何变>
-
```
成文后**必须**同步 Axhub 标注目录(见 [annotation-sync.md](annotation-sync.md)
1. `src/prototypes/<id>/.spec/requirements-prd.md`
2. `annotation-source.json` → 目录节点「产品需求说明PRD`markdownPath` + `markdown`
3. `src/resources/prd/<id>-autoprd.md`
4. 定稿时另写:`src/prototypes/<id>/.spec/autoprd-baseline.json`
## 用户故事写法(对照业务条线说明)
业务条线说明页字段 → AutoPRD 字段:
| 页面 | AutoPRD |
|------|---------|
| 责任部门标签 | **角色** |
| 起点 | **起点** |
| 怎么运作(有序列表) | **怎么运作** |
| 结果色签 | **关键结果**(可选) |
| 闭环 | **闭环** |
示例口吻(摘自业务条线风格,非照抄某模块):
- **起点**:采购部维护交强与商业险台账,作为交车合规的前置数据。
- **怎么运作**1. 运营录入或识别保单… 2. 运维交车时校验…
- **闭环**:核心险种有效则允许交车;异常则拦截并提示原因,过程可追溯。
**不要**用下面这种宽表作为第 4 章唯一形态:
| 编号 | 作为…我希望… | SP |
|------|--------------|----|
「作为…我想…以便…」只允许作为**排期可选一行**,主叙述必须是起点/怎么运作/闭环。
## 正逆向写法约定
- **正向**:用户成功完成任务的最短路径
- **逆向**:取消、关闭、禁用、冲突状态、不可操作项
- 审批类:写清「本页只读 / 在外部系统办理」
## 规模与故事点
| 规模 | 建议含义 | 约 SP |
|------|----------|-------|
| S | 轻交互 / 列表展示 | 12 |
| M | 标准流程 + 筛选详情 | 35 |
| L | 状态机 / 跨模块 / 批量识别 | 6+ |

View File

@@ -0,0 +1,47 @@
# 【交付】任务描述回填(设计完成 · 按编号)
**`$YunxiaoPMapp`** 组合。创建【交付】时描述保持占位 `等待设计任务完成后自动填入`**本文件只在设计完成(或显式同步)时**把 AutoPRD Markdown 写入【交付】。
**禁止**按任务标题查找交付;**禁止**加载 `yunxiao-requirement-lifecycle`
## 触发时机
| 时机 | 动作 |
|---|---|
| YunxiaoPMapp **设计完成**且 AutoPRD 落盘成功 | 必须回填【交付】描述 |
| 口令 `同步交付说明:交付任务=ONEOS-xx`(或需求编号可反查交付) | 按编号回填 |
| 仅创建【交付】 / 分析中 / 设计中尚未设计完成 | **不**写 PRD 正文 |
## 前置
1. 已有【交付】任务编号:口令显式 > 需求 `## 工作项编号(系统)` > ASSOCIATED 反查校验。
2. 冲突或缺少编号 → 停下询问;禁止按 `【交付】`+标题猜。
3. 本地已有 `requirements-prd.md`(或本轮刚生成)。
## 写入内容
- 用与需求「产品说明AutoPRD」一致的正文**替换**占位文案。
- 推荐:原型链接 + `requirements-prd.md` 全文(或 YunxiaoPMapp 约定的产品说明正文)。
- 可附一句:`原始诉求见需求描述「原始诉求AutoRDO」`
- 不要删除或改写需求侧 AutoRDO 段(本步骤只改**任务**描述)。
## 执行顺序(设计完成组合)
```text
1. AutoPRD 落盘 MD + 标注同步
2. 更新需求「产品说明AutoPRD
3. 按交付任务编号 PATCH 任务描述(替换占位)
4. 附件ZIP/截图)由 YunxiaoPMapp make-export 流程负责;本文件不替代附件
5. 任一步失败 → 不得声称交付说明已更新 / 设计完成材料齐全
```
## 回报
- 交付任务编号、是否已替换占位、MD 路径
- 失败时列出缺项(无编号 / 无 MD / 写入失败)
## 负向
- 创建交付当下灌入未完成的 PRD
- 按标题 list 复用「像交付的任务」
- 引导旧 lifecycle 建同名任务

View File

@@ -0,0 +1,60 @@
# 云效需求描述:产品说明(对接 YunxiaoPMapp
发云效 / 完善需求描述时,与 **`$YunxiaoPMapp`** 双段模板对齐。
**禁止加载** `yunxiao-requirement-lifecycle`
## 需求描述固定结构(不可互相覆盖)
```markdown
## 原始诉求AutoRDO
(由 AutoRDO 清洗;设计完成也不删除;本 Skill 不覆盖本段)
## 产品说明AutoPRD
(本 Skill 写入:原型链接 + requirements-prd 正文或等价产品说明)
## 工作项编号(系统)
(由 YunxiaoPMapp 维护;本 Skill 不改本段)
```
## 产品说明段推荐拼装
```markdown
## 产品说明AutoPRD
### 原型链接
<{baseUrl}/{prototype-id}/index.html禁止加 prototypes/ 前缀;禁止去掉 index.html>
无则写「待发布」
### 需求说明
<src/prototypes/<id>/.spec/requirements-prd.md 全文原样粘贴;禁止摘要顶替>
### 更新内容
<第 10 章最新定稿块;无则「首版定稿」或「本轮无功能/逻辑增量」>
### 更新内容·历史
<旧更新内容倒序;勿删>
```
若 YunxiaoPMapp 本轮只要求「产品说明」短写:至少包含原型链接 + MD 全文或与交付回填一致的正文;**仍禁止**覆盖 AutoRDO / 工作项编号段。
## 真相源文件
1. `src/prototypes/<prototype-id>/.spec/requirements-prd.md`(主)
2. 否则 `src/resources/prd/<prototype-id>-autoprd.md`
先 Read 文件再写入;不要凭记忆重写。
## 执行步骤
1. 确认 prototype-id 与需求编号(若写云效)。
2. 读 MD 全文。
3. PATCH/更新需求描述时**只改**「产品说明AutoPRD」相关内容保留原始诉求与工作项编号。
4. 若同时设计完成:按 [yunxiao-delivery-sync.md](yunxiao-delivery-sync.md) 回填【交付】。
5. 回报需求编号、MD 路径、是否全文写入、是否已回填交付编号。
## 禁止
- 只用第 9 章摘要顶替全文(除非用户只要链接)
- 二次删减章节、去掉 mermaid/表格却声称全文已写
- 创建【交付】时灌入 PRD须等设计完成见交付回填
- 引用或配合 `yunxiao-requirement-lifecycle`

View File

@@ -0,0 +1,32 @@
---
description: 改原型跟进 AutoPRD定稿写功能变更与版本号云效仅与 YunxiaoPMapp 组合;禁止旧 lifecycle 同名任务
alwaysApply: true
---
# OneOS AutoPRD 全局同步
## 改原型
修改 `src/prototypes/**` 且涉及**行为、文案、流程、判定或验收**时,同一轮必须跟进 **oneos-autoprd**AutoPRD
1. 更新 `.spec/requirements-prd.md`(用户故事:起点 → 怎么运作 → 闭环)。
2. 更新 `annotation-source.json` **顶层** `directory.nodes` 中「产品需求说明PRD」。
3. 同步 `src/resources/prd/<id>-autoprd.md`(若有)。
纯样式且无产品语义变化:可跳过全量重写。
## 需求定稿
用户回复含 `需求定稿` / `定稿` / `确认定稿` / `本次定稿` / `本轮定稿` 时:
1. 按 skill `references/release-changelog.md` 汇总**自上次定稿**的功能/逻辑变更,并递增 `prdVersion`(用户显式指定主/副/子时以用户为准)。
2. 追加到 PRD `## 10. 功能变更记录`(最新在上);更新 `.spec/autoprd-baseline.json`(含 `prdVersion`)。
3. **不要**写布局/UI/表结构类条目。
## 云效(唯一组合 · YunxiaoPMapp
产品侧写云效**只**与 `$YunxiaoPMapp` 组合;**禁止加载** `yunxiao-requirement-lifecycle`。
- 入库碎片:先 `$AutoRDO`,再 YunxiaoPMapp 记录需求(原始诉求段)。
- 设计完成 / 完善产品说明:先 `oneos-autoprd` 落盘 MD再写需求 `## 产品说明AutoPRD`;按交付**任务编号**回填【交付】描述(创建交付时保持占位,见 AutoPRD `yunxiao-delivery-sync.md`)。
- 【交付】/【分析】/【设计】树与交棒由 **YunxiaoPMapp** 负责AutoPRD **不**建同名无前缀阶段任务。

View File

@@ -0,0 +1,85 @@
---
description: OneOS V2 全局定版设计规范Stripe Violet 紫光高规 + 3视角架构 + PC/H5 移动端 100% 响应式 + 全量 UI 控件库 + 若依动态主题色 + 车牌号无点标准)
globs: src/prototypes/oneos-v2/**/*, src/prototypes/lease-contract-management/**/*, src/resources/design-system/**/*, src/prototypes/**/*
alwaysApply: true
---
# OneOS V2 全局定版设计规范Cursor Agent 强制执行规则)
> **【硬性准则】**:在 `OneOS V2` 目录下**生成新页面、修改或迁移任何原型页面**时AI Agent **必须首先 Read** 并严格遵守 `src/resources/design-system/DESIGN.md` 或 `src/prototypes/oneos-v2/DESIGN.md`
---
## 0. 新页面生成与修改工作流 (Mandatory Workflow)
1. **强前置步骤**:在创建或修改 `OneOS V2` 下的任何页面前,必须读取 `src/resources/design-system/DESIGN.md`,确认最新的 Token、UI 控件用法、3 视图模板和响应式规范。
2. **禁止使用原生 HTML 控件**:严禁直接使用原生 `<select>`、`<input type="date">` 或未经过 V2 封装的第三方组件。必须统一导入并使用 `UIComponents.tsx` 导出的封装控件:
- `V2Button`(主/次/描边/幽灵/危险/返回;详见 `DESIGN.md` §3.0
- `V2Select`
- `V2DatePicker`
- `V2DateRangePicker`
- `V2SingleInputDateRangePicker`(单输入框双日历,默认推荐)
- `V2TimePicker`
- `V2SingleInputTimeRangePicker`(单输入框双时间)
- `V2RadioGroup`
- `V2CheckboxGroup`
- `V2Switch`
- `V2Steps`
- `V2Timeline`
- `V2ApprovalProgress`(默认 `direction="vertical"` 垂直贯穿时间轴)
- `V2Pagination`(统一分页控制器)
- `V2Empty`(空状态与异常页组件)
- `V2SegmentedControl`(顶栏视图/模式分段切换控件)
- `V2StatusTabs`(分类/状态过滤页签条)
- `V2ImageUpload`(图片拖拽/新增上传 · Web Dropzone + H5 拍照/相册;详见 `DESIGN.md` §3.17
- `V2MobileHeader`
- `V2MobileBottomNav`
- `V2MobileActionBar`
3. **母版参考**
- **台账三视角**`src/prototypes/lease-contract-management/LeaseContractHub.tsx`13 项高阶筛选、3 视图、嵌套车辆子表)。
- **结构化工单/处置表单页**`src/prototypes/lease-contract-redesign/FaultDispositionForm.tsx`(左主表单三段卡 + 右 340px 指派/SLA详见 `DESIGN.md` §4.8)。
4. **筛选查询收起(强制)**:台账筛选栏 /「更多筛选」展开后,点击 **查询** 必须应用条件并**自动收起**筛选栏H5 为关闭 Bottom Sheet**重置**清空后同样收起。详见 `DESIGN.md` §2.4.3。
5. **列表操作列(强制)**:常用「编辑 / 处理(处置)」**外侧**展示(最多 2 个);低频「查看记录 / 操作记录 / 历史」及危险操作收入 **⋮ 更多**。统一使用 `OperationActions``DESIGN.md` §3.16 / `vm-shared/DESIGN.md`)。
---
## 1. 核心视觉与配色规范 (Stripe Fintech UI)
- **主色 (Primary Accent)**Stripe Violet `#533AFD`(悬停 `#6346FF`Focus 环 `#4226E8`,浅亮底 `#E0E7FF`,暗亮底 `rgba(83, 58, 253, 0.18)`
- **画布背景**:浅色 `#F6F9FC` / 深色 `#0A0B0D`
- **卡片容器**:浅色 `#FFFFFF` / 深色 `#121418`
- **边框线**:浅色 `#E3E8EE` / 深色 `#23272F`
- **主正文**:浅色 `#0A2540` / 深色 `#F7FAFC`
- **次要正文**:浅色 `#425466` / 深色 `#A0AEC0`
- **语义色**:成功 `#10B981` · 预警 `#D97706` · 危险/错误 `#EF4444` · 提示 `#3B82F6`
- **若依 (RuoYi) 框架动态主题色**:所有组件背景、边框、选中态必须消费 CSS 变量 `var(--oneos-primary, var(--ln-primary, #533AFD))`,兼容若依的主题色动态切换。
- **双色模式**:通过 `[data-ds-mode="dark"]` 或 `[data-oneos-theme="dark"]` 响应,严禁出现外壳深内容浅的失配情况。
- **车牌号规范**:车牌号严禁出现间隔点 `·`(必须形如 `浙A88888F`、`京A66666`)。
---
## 2. PC / H5 移动端 App 嵌入 100% 响应式 (Mobile H5 Standard)
- **双形态适配**:所有 V2 原型必须支持 PC 屏宽 (≥1024px) 与 H5 移动端 (≤767px) 形态。
- **触控规格**:移动端 (≤767px) 场景下,所有可点击元素与输入框触控高度必须 **`≥ 44px`**`min-height: 44px`),正文字号 **`≥ 14px`**。
- **Mobile Bottom Sheet**:移动端下 `V2Select`、`V2DatePicker` 等弹窗自动转为固定吸底 **Bottom Sheet 面板**,配有顶部抓手条与 44px 确定按钮。
- **移动端底部操作条**:提交与主操作按钮在移动端自动固定吸底(`V2MobileActionBar`)。
---
## 3. 统一的三视角页面架构 (Three Core Views)
任何台账、列表、审批与履约管理页面必须提供或集成 3 视角模板:
1. **列表模式 (List View)**:包含 Bento Grid KPI 大盘 + Pill Tabs + 13 项高阶筛选(查询/重置后自动收起)+ 展开式嵌套子表格。
2. **看板模式 (Kanban View)**:包含 4 阶段 Pipeline 管道列(卡片快速操作与流程推进)。
3. **主从表单模式 (Split / Master-Detail View)**:左侧 340px 搜索任务/单据列表 + 右侧深度工作台(包含结构化表单、关联业务 Tabs 及履约图谱)。
---
## 4. 规范参考文件路径
- 全局主规范文档:`src/resources/design-system/DESIGN.md`
- 规范展示页:`src/prototypes/oneos-v2/DesignSystemShowcase.tsx`
- 组件库文件:`src/resources/design-system/components/UIComponents.tsx`
- 全局 Token CSS`src/resources/design-system/oneos-ds-tokens.css`
- 若依预设导出:`src/resources/design-system/ruoyi-theme-preset.json` & `ruoyi-oneos-v2-theme.css`

View File

@@ -0,0 +1,17 @@
---
description: 产品侧云效写操作走 YunxiaoPMapp强制 Plan 门禁;禁止加载已删除的 yunxiao-requirement-lifecycle
globs:
alwaysApply: true
---
# 云效记录需求 · 产品侧唯一入口
产品侧凡「记录需求 / 推进至 / 交棒 / 创建迭代」等**会改云效**的操作:
0. **只使用 `$YunxiaoPMapp`**(及入库前 `$AutoRDO`、设计完成 `$oneos-autoprd`)。
**禁止加载**已删除的 `yunxiao-requirement-lifecycle`;勿按旧同名阶段任务规则建单。
1. **强制先切 Cursor Plan 模式**`SwitchMode` → `plan`):对齐需求/任务**编号**、推进目标、交付树策略等;用户确认后再一口气 apply。
2. 标题规范:`【新增】…` / `【优化】…`(详见 YunxiaoPMapp / 口令面)。
3. 查重与复用**只认任务编号**;创建【交付】描述占位,设计完成再灌 AutoPRD。
4. 项目常量见 `.cursor/skills/YunxiaoPMapp/assets/runtime-ids.json`(勿再引用旧 lifecycle 路径)。
5. 细则以 `$YunxiaoPMapp` Skill 全文为准。

View File

@@ -0,0 +1,83 @@
---
name: AutoRDO
description: >-
AutoRDO (Requirement Description Optimization): cleans fragmented chat logs,
voice transcripts, oral notes, and feedback ledgers into written title and description;
auto-detects 类型/优先级/标签/提交部门/提交人 from content; maps OneOS modules via oneos-domain.md;
splits multi-line into multiple results; if any 待确认 exists, MUST switch to Plan mode
for choice-based confirmation. Does not change Yunxiao status or create tasks.
Pair with YunxiaoPMapp for cloud write; never load yunxiao-requirement-lifecycle.
---
# AutoRDO
**Requirement Description Optimization**(需求描述优化)。
将碎片化、通俗化文字(聊天/录音/反馈台账)在**保留原意**前提下拆解为**标题、描述**,并**自动识别**类型、优先级、标签、提交部门、提交人,供入库写入云效需求。
多行/多条独立诉求 → **自动拆成多份**转译结果。
**强制**:清洗结果中**只要存在任意「待确认」**Agent **必须立刻** `SwitchMode`**plan**,逐条用选择题消解;**无需**用户再说「确认待确认」。无待确认则可直接交定稿。
## 边界(强制)
| 做 | 不做 |
|---|---|
| 提炼标题与书面描述;自动识别类型/优先级/标签/提交部门/提交人 | 改云效状态 / 建任务 / **直接**打云效标签 |
| 多行/多条 → 多份转译结果 | 写成完整 AutoPRD / 臆造业务结论 |
| 有待确认 → 强制 Plan 逐条确认 | 停在初稿等口令;把猜测写入定稿 |
| 去除描述**结尾句号** | 加载 `yunxiao-requirement-lifecycle` |
云效建单与打标由 **`$YunxiaoPMapp`** 负责;本 Skill 只出清洗稿与**推荐元数据**。
## 何时使用
- 口令含 `AutoRDO` / `清洗聊天` / `录音整理` / `原始诉求`
- 粘贴反馈台账(含部门/优先级/模块列)或口述碎片
- YunxiaoPMapp「记录需求」前必须先跑本 Skill材料为碎片/台账时)
## 输入
- 聊天、会议速记、口述、录音转写
- **多行/台账**含反馈人、所属部门、业务模块、优先级、PC或移动端等列时优先采信列值
- 确认阶段补充文字
## 处理规则
**强制前置**ONE-OS 材料先 Read [references/oneos-domain.md](references/oneos-domain.md),元数据规则见 [references/meta-fields.md](references/meta-fields.md),再按 [references/rules.md](references/rules.md) 执行。
1. **多条拆解** → 每条独立成稿
2. **OneOS 对齐** → 模块/部门标准名
3. **元数据识别** → 类型、优先级、标签、提交部门、提交人(显式列 > 正文标记 > 语义推断;不确定 → 待确认)
4. **标题 + 描述转译** → 去口语、去结尾句号
5. **有待确认 → 强制 Plan** → 见 [references/confirm-pending.md](references/confirm-pending.md)
## 输出
```markdown
## 原始诉求AutoRDO
**标题**<清晰标题>
**类型**:【新增】|【优化】
**优先级**P1-高|P2-中|P3-低
**标签**<标准模块>[, PC端|小程序]
**提交部门**<标准部门名或空>
**提交人**<姓名或空>
**描述**
<转译正文;无结尾句号>
反馈:<有则附日期/禅道/状态/端>
待确认:
-
```
多条时先写「共 N 条」,再 `### 1``### N`
交 YunxiaoPMapp 示例:`记录需求:标题=…;类型=…;优先级=…;标签=…;提交部门=…;提交人=…;描述=…`
## 口令
```text
AutoRDO<粘贴聊天或台账行>
AutoRDO录音转写如下 …
按下列补充消解待确认:
<补充说明>
```

View File

@@ -0,0 +1,4 @@
interface:
display_name: "AutoRDO"
short_description: "清洗诉求并识别类型优先级标签部门提交人"
default_prompt: "按 AutoRDO 清洗:先读 oneos-domain.md 与 meta-fields.md多行拆多条出标题+描述+类型/优先级/标签/提交部门/提交人。有待确认则同轮强制切 Plan 用选择题消解;不改云效、不直接打标、不贴词典全文。"

View File

@@ -0,0 +1,126 @@
# AutoRDO · 待确认逐条 Plan 确认
## 目标
清洗稿中的「待确认」经产品经理**逐条人工确认**后,回填进标题/描述,得到可交 YunxiaoPMapp 的定稿。
确认过程**优先选择题**;选项用 [oneos-domain.md](oneos-domain.md) 辅助生成;也支持用补充说明/需求描述文字直接消解待确认点。
## 何时进入(强制)
```text
清洗初稿产出后:
若任一需求含「待确认」→ 同轮必须 SwitchMode → plan
若全部无待确认 → 不必进 Plan初稿即定稿
```
- **触发条件只有一条**:存在待确认(单条或多条中任意一点)
- **禁止**要求用户再说「确认待确认」「开始确认」才进 Plan
- 用户在 Plan 中可用选择题作答,也可粘贴补充说明消解
**不进 Plan 的唯一情况**:清洗结果中没有任何「待确认」条目。
## Plan 门禁(强制)
1. 清洗初稿写出后(可先展示初稿摘要),**立刻** `SwitchMode`**plan**,说明:存在待确认,须逐条确认后再回填定稿;本阶段仍**不写云效**
2. Plan 列出:待确认的**需求条号**、每条下的待确认点清单、推荐确认方式(选择题 / 文字补充)
3. **用户确认 / 批准 Plan / 「执行」之前**:禁止把未确认内容写进定稿描述
4. 批准后:按条推进确认 → 回填 → 输出定稿
## 逐条确认顺序
```text
需求 1 的待确认点 1 → 点 2 → … → 需求 1 定稿片段
需求 2 的待确认点 1 → …
全部完成后输出「已确认定稿」全集
```
- **一次只推进一个待确认点**(或同一点下的一组互斥选项),避免一屏堆十几个问题
- 多条需求时Plan 清单可注明建议从第 1 条起;用户可指定跳过或改序
- 某条无「待确认」→ 跳过,保留初稿即可
## 确认方式(优先选择)
每个待确认点按下列优先级出题:
| 优先级 | 方式 | 适用 |
|---|---|---|
| 1 | **选择题**25 个互斥选项 + 可选「其他/我补充」) | 模块归属、部门名称、类型/优先级、是否/范围、枚举字段、拆条边界等 |
| 2 | **多选** | 明确可多选的范围如适用端PC+H5 |
| 3 | **文字补充** | 无法枚举、需自由描述字段清单/规则细节时 |
### 选项如何用 OneOS 词典生成
先 Read `oneos-domain.md`,再出选项:
- **模块名不清**:候选 = 词典中相关条线的标准模块名(如还车应结款 / 违章管理 / 还车管理),勿自造模块
- **部门/角色口语**:候选 = 第 1 节标准名(业管→业务管理组,安全小组→安全部 等)+「保持单据原文分区名」
- **跨条线联动**:选项写清主责模块 vs 联动对象;标题只挂主责,联动写描述
- **故事点细节**:仅当材料或用户补充已暗示时,才把词典闭环中的合理分支列为选项;**禁止**把未提及的故事点细节默认选中
每题结构建议:
```text
【需求 n · 待确认 k】<待确认原文>
依据词典,请选择:
A. …
B. …
C. …
D. 其他(请补充一句)
也可用一段需求描述直接回答本点
```
## 用需求描述补充
用户可用以下任一方式消解待确认,**不必**每题都点选:
- 粘贴一段补充说明 / 功能规则 / 字段清单
- 回复「按下列描述确认:…」
- 对某一待确认点直接写答案句
Agent 须:
1. 将补充文字**映射**到对应待确认点(可一次消解多点)
2. 写入该条**描述**(书面化、去结尾句号),从「待确认」列表**移除已消解项**
3. 补充仍含糊的部分 → 保留或新开「待确认」,继续选择题
4. **不**把补充里未说的内容脑补进去
## 回填定稿规则
确认完成后,对该条输出「已确认」版本:
```markdown
### n已确认
## 原始诉求AutoRDO
**标题**:…
**描述**
<初稿 + 已确认信息合并;无结尾句号>
待确认:
- (无则写「无」或省略本段)
```
- 标题若因模块/动作确认而需微调,可改,并在确认回合说明改了什么
- 未确认点**不得**假装已确认;可标「本条暂缓,待确认仍保留」
- 全部条完成后,给总览:已确认条数 / 仍含待确认条数
## 口令
```text
AutoRDO<材料> → 有待确认则自动进 Plan
按下列补充消解待确认:
<粘贴补充说明>
第 6 条待确认选 A第 7 条补充:字段非必填,计入应补汇总
```
(「确认待确认」等口令**不再作为**进 Plan 的前置条件;有待确认即强制进。)
## 不做
- 确认阶段仍不改云效、不建任务
- 不把 `oneos-domain.md` 全文贴进定稿
- 不跳过 Plan 直接把「猜的答案」写进描述
- 不等用户额外口令才进 Plan有待确认必须进

View File

@@ -0,0 +1,96 @@
# AutoRDO · 元数据自动识别
从粘贴内容(台账表格行、聊天、口述)自动识别下列字段,写入每条原始诉求输出;**不**直接改云效打标(打标由 YunxiaoPMapp 执行)。
## 输出字段
| 字段 | 说明 | 无依据时 |
|---|---|---|
| **类型** | `【新增】` / `【优化】`(与云效标题前缀一致) | 默认 `【优化】`,并列入待确认 |
| **优先级** | `P1-高` / `P2-中` / `P3-低` | 默认 `P2-中`,高不确定则待确认 |
| **标签** | 主模块标签(对齐 `oneos-domain.md` 标准模块名);可附端标签 `PC端` / `小程序` | 仅模块不确定则待确认 |
| **提交部门** | 映射到词典标准部门名 | 材料无部门且无法推断 → 待确认或空 |
| **提交人** | 反馈人/用户姓名 | 材料无人名 → 空(不臆造) |
## 识别优先级
```text
1. 显式列/字段反馈台账优先级、所属部门、反馈方、业务模块、PC或移动端…
2. 正文中的明确标记P1、【优化】、@某人、部门署名)
3. 语义推断(用词 + oneos-domain 模块/部门)
4. 仍不确定 → 待确认(选择题),禁止假装已确认
```
## 类型(【新增】/【优化】)
| 信号 | 类型 |
|---|---|
| 新增、增加、支持、允许、增加列/字段/入口、批量导入(首次能力) | 【新增】 |
| 优化、调整、修改、放开、更清晰、重构、移动至、改由、精确到、兼容 | 【优化】 |
| 台账/口令已写 `【新增】`/`【优化】` | 以显式为准 |
| 同时含新增与优化语义 | 以**主诉求**定类型;次要点写在描述 |
标题可带类型前缀供入库:`【优化】交车管理:…`;若用户只要裸标题,类型仍单独输出字段。
## 优先级
| 信号 | 优先级 |
|---|---|
| 列值 `P1-高` / `P1` / 紧急、阻塞、无法办理、P1 | `P1-高` |
| 列值 `P2-中` / `P2` | `P2-中` |
| 列值 `P3-低` / `P3` / 文案、置灰、体验微调 | `P3-低` |
| 无信号 | 默认 `P2-中` |
## 标签
1. **主标签** = 归属标准模块名(`oneos-domain.md`),如 `还车应结款``违章管理``交车管理`
2. 台账「业务模块」列优先;口语映射到标准名(验车管理→验车入库,调拨管理→车辆调拨)
3. **端标签**(可选,可多选):材料含 `PC端`/`小程序`/`PC及小程序` 时写入
4. 「其他」「全局优化」「小程序审批中心」等非模块名:主标签用最贴近模块或 `系统全局`;勿发明云效不存在的随意标签名
5. 输出格式:逗号分隔,如 `还车应结款, PC端`
## 提交部门
| 材料常见写法 | 标准输出 |
|---|---|
| 业务管理部、业管、业务管理 | 业务管理组 |
| 运维部、运维 | 运维部 |
| 数智中心、数智、信息化 | 数智部 |
| 安全部、安全 | 安全部 |
| 财务部、财务 | 财务部 |
| 法务部、法务 | 法务部 |
| 采购部/采购组 | 按词典区分输出 |
台账「所属部门」列优先;聊天中「我们运维…」可推断,低置信度则待确认。
## 提交人
- 台账「反馈方/用户」「反馈人」列 → 原样作为提交人
- 聊天 @姓名、署名「张三:」→ 取该名
- 多人联合反馈 → 取主反馈人(首列/首个署名);其余可写描述附注
- **禁止**用当前对话用户名冒充提交人(除非材料写明)
## 与描述附注的关系
- **结构化字段**(类型/优先级/标签/提交部门/提交人)单独成行,供 YunxiaoPMapp 建单口令复用
- 禅道编号、处理状态、反馈日期等 → 可放描述末行「反馈:…」附注,不升格为强制字段
## 输出模板(每条)
```markdown
## 原始诉求AutoRDO
**标题**<清晰标题;可选带【新增】/【优化】前缀>
**类型**:【新增】|【优化】
**优先级**P1-高|P2-中|P3-低
**标签**<模块>[, PC端|小程序]
**提交部门**<标准部门名或空>
**提交人**<姓名或空>
**描述**
<转译正文;无结尾句号>
反馈:<日期 · 原文部门 · 状态 · 禅道号 · 端 …>(有则写)
待确认:
-
```

View File

@@ -0,0 +1,399 @@
# ONE-OS 业务领域词典(供 AutoRDO 对齐)
> 来源:业务条线说明原型 `lease-business-line-overview`
> 用途:清洗标题/描述时,优先用下列**标准模块名、部门名、闭环表述**对齐,避免口语臆造模块或错挂条线。
> 系统定位1 套系统 · 5 大业务条线闭环 · 3 大数据底座 · 演进方向为业财一体
> **强制**:本文件只用于理解与用词对齐;**禁止**把本词典全文贴进云效描述或 AutoRDO 输出稿。
---
## 0. 系统总览
| 维度 | 口径 |
|---|---|
| 平台名 | ONE-OS亦写作 OneOS |
| 五大业务条线 | 租赁 · 能源 · 运维 · 安全 · 物流 |
| 三大数据底座 | 车辆资产运营情况 · 各业务条线盈亏情况 · 里程调度情况 |
| 现阶段 | 业务驱动 · 财务手工维护(收款/付款/核销多人工) |
| 演进方向 | 业财闭环一体化(打通财务 YS「收款记录」「付款记录」与业务台账双向回写 |
**标题提炼提示**:口述涉及合同/台账/交还车/氢费/证照/调度时,先归入对应条线再落模块名;跨条线联动(如还车应结款联动违章事故)在描述中写明联动对象,标题以主责模块为准。
---
## 1. 业务部门 / 角色词典(标准用词)
清洗时统一下列名称;同义口语请映射到标准名。
| 标准名称 | 常见口语/别称 | 主要出现条线 |
|---|---|---|
| 业务管理组 | 业管、业务管理 | 租赁、运维、安全、物流 |
| 业务管理组-能源部 | 能源组、业管能源、业务管理部-能源组 | 能源、租赁还车 |
| 业务服务组 | 业务服务 | 物流 |
| 业务员 | 业务 | 租赁 |
| 调度岗 | 调度 | 物流 |
| 法务部 | 法务 | 租赁、运维采购合同 |
| 财务部 | 财务 | 租赁评级、能源账户、运维付款/维保、安全违章事故、物流台账 |
| 安全部 | 安全 | 租赁评级、证照、安全条线 |
| 运维部 | 运维、区域操作员 | 运维全链路、交还车、租赁提车后交车 |
| 采购部 | 采购 | 能源加氢站、运维采购合同/验车 |
| 采购组 | 采购组 | 供应商管理(能源/运维) |
| 数智部 | 数智、信息化 | 合同模板电子化、能源扩展 |
| 董事长 | 老板、总 | 非标合同、资产出售过户报废确认 |
| 司机 | 提车司机、内部司机 | 交车培训、故障、安全培训 |
| 加氢站 / 签约加氢站 | 站点、站方 | 能源 |
**组织边界提示**
- 「采购组」侧重供应商主数据;「采购部」侧重站点管理与采购/三方租赁合同。
- 「业务管理组」与「业务管理组-能源部」勿混用;氢费、加氢对账默认能源部。
- 物流调度明确:**非 TMS**,不做配载与承运商调度。
---
## 2. 功能模块总表(按条线)
### 2.1 租赁业务条线6 模块 · 全链路闭环)
**条线闭环**:客户评级决定是否可签 → 标准模板支撑签约 → 租赁合同进入履约 → 提车应收对齐后交车 → 台账承接租期账单 → 还车应结款会签归档。
| 步 | 模块名 | 一句话定位 | 责任部门 |
|---|---|---|---|
| 1 | 客户管理 | 准入评级 · 决定能否签约、走哪条流程 | 业务管理组、法务部、财务部、安全部 |
| 2 | 标准合同管理 | 模板配置 · 支撑电子合同一键发起 | 法务部、数智部 |
| 3 | 租赁合同 | 签约发起 · 标准 / 非标 / 禁止三条路径 | 业务员、法务部 |
| 4 | 提车应收款 | 应收生成 · 实收对齐 · 触发交车 | 业务员、法务部、业务管理组、运维部 |
| 5 | 租赁业务台账 | 交车后账单 · 周期收费与实收延续 | 运维部、业务员、业务管理组 |
| 6 | 还车应结款 | 还车结算 · 多部门会签 · 归档闭环 | 业务管理组、安全部、运维部、业务管理组-能源部 |
**关键结果标签(客户管理)**:可标准签约 · 可签·走非标 · 禁止签约·高风险
---
### 2.2 能源业务条线6 模块 · 业财闭环)
**条线闭环**:供应商主数据支撑站点绑定 → 签约站账号与订单主动上报 → 非签约站氢费补录对账 → 客户对账单关联收款 → 加氢记录标记已付款 → 成熟后向采购端与司机端延伸。
| 步 | 模块名 | 一句话定位 | 责任部门 |
|---|---|---|---|
| 1 | 供应商管理 | 加氢/充电站供应商 · 站点绑定与业财直连 | 采购组、财务部 |
| 2 | 加氢站管理 | 签约站 / 非签约站 · 账号、余额与价格 | 采购部、加氢站 |
| 3 | 加氢订单 | 主动上报 · PLC 自动采集 · 预约接单 | 签约加氢站、业务管理组-能源部 |
| 4 | 车辆氢费明细 | 非签约站补录 · 对账归档 · 余额关联 | 业务管理组-能源部 |
| 5 | 氢费账户 | 客户预付款 · 对账单 · 业财收款闭环 | 业务管理组-能源部、财务部 |
| 6 | 扩展规划 | 上游采购 · 下游司机服务 | 采购部、业务管理组-能源部、数智部 |
---
### 2.3 运维管理条线15 模块)
**主线main**:验车入库 → 上牌 → 证照 → 备车 → 交车 → 还车 → 出售/过户/报废出库
**并行能力support**:供应商、采购合同、替换车、故障、年审、维保、异动、调拨(无严格先后)
**条线闭环**:供应商与采购合同入库 → 上牌证照与备车整备 → 交车/替换/还车闭环 → 故障与年审维保 → 异动调拨 → 出售/过户/报废审批出库。
| 步 | 模块名 | 轨道 | 一句话定位 | 责任部门 |
|---|---|---|---|---|
| 1 | 供应商管理 | support | 整车厂 / 三方租赁 · 付款底座 | 采购组、财务部 |
| 2 | 车辆采购 / 三方租赁合同 | support | 车型数量 · 付款关联 · 验车任务 | 采购部、法务部、财务部 |
| 3 | 验车入库 | main | 采购 / 三方来源 · 验完自动入库 | 运维部、采购部 |
| 4 | 车辆上牌 | main | 车架号入库 · 完成牌证登记 | 运维部 |
| 5 | 证照管理 | main | 一车一档 · 到期待办推送 | 运维部、安全部 |
| 6 | 备车管理 | main | 交车前整备 · 随时可交付 | 运维部 |
| 7 | 交车管理 | main | 司机培训留痕 · 区域派单 · OCR 比对 · 电子签 | 运维部、业务管理组、司机 |
| 8 | 替换车管理 | support | 临时 / 永久替换 · 费用自动核算 | 运维部、业务管理组 |
| 9 | 还车管理 | main | 区域派单 · 费用自动计算 · 电子签 | 运维部、业务管理组 |
| 10 | 故障管理 | support | AI 助手 + 人工 · 证据链归档 | 运维部、司机 |
| 11 | 年审记录 | support | 提前 3 个月 · OCR 刷新证照 | 运维部 |
| 12 | 维修与保养记录 | support | 费用汇总 · 业财一体 · 盈亏核算 | 运维部、财务部 |
| 13 | 车辆异动 | support | 出库维修 / 年审 / 保养 · 成本归集 | 运维部 |
| 14 | 车辆调拨 | support | 跨区调拨 · 运维权转移 | 运维部、业务管理组 |
| 15 | 车辆出售、过户、报废 | main | 资产变更审批 · 过程留痕 · 自动出库 | 运维部、董事长、财务部 |
---
### 2.4 安全管理条线6 模块 · 安全闭环)
**条线闭环**:司机信息与证照 → 定期培训与资料库学习 → 违规记录关联评级 → 违章/事故登记 → 联动还车应结款与代处理费用。
| 步 | 模块名 | 一句话定位 | 责任部门 |
|---|---|---|---|
| 1 | 司机管理 | 物流内部司机 · 信息证照一体 | 安全部、业务管理组 |
| 2 | 内部司机培训 | 定期安全培训 · 证据链留痕 | 安全部、司机 |
| 3 | 安全培训资料库 | 资料上传 · APP / 小程序学习 | 安全部、司机 |
| 4 | 违规记录 | 司机违规 · 关联评级 | 安全部、业务管理组 |
| 5 | 违章管理 | 分值罚款 · 还车联动 · 代处理 | 安全部、财务部、业务管理组 |
| 6 | 事故管理 | 权责划分 · 保险赔付 · 还车联动 | 安全部、财务部、业务管理组 |
---
### 2.5 物流业务条线3 模块 · 经营闭环)
**条线闭环**:物流合同生效 → 轻量调度派车(交车后可办结)→ 办结自动生成物流业务明细 → 汇总盈亏 → 汇集项目盈亏表 → 演进关联收款记录完成业财闭环。
| 步 | 模块名 | 一句话定位 | 责任部门 |
|---|---|---|---|
| 1 | 物流合同 | 关键信息录入 · 业务确认生效 · 可派车 | 业务管理组、业务服务组 |
| 2 | 调度任务 | 轻量派车 · 交还车校验 · 办结出车 | 业务服务组、调度岗、运维部 |
| 3 | 物流台账 | 任务自动生成 · 补录导入 · 盈亏核算 | 业务服务组、财务部 |
---
### 2.6 三大数据底座(管理决策层,非业务条线)
| 底座 | 看什么 | 主要数据来源条线 |
|---|---|---|
| 车辆资产运营情况 | 规模 · 结构 · 健康度 · 品牌型号出勤率下钻省市 | 运维、车辆管理、证照/保险、交车/备车 |
| 各业务条线盈亏情况 | 收入 · 成本 · 利润(条线/项目/单车) | 租赁台账、物流台账、氢费账户、收款、维保/事故/违章 |
| 里程调度情况 | 里程补贴 · 客户履约 · 智能替换与运维干预 | 车机/GPS/人工里程、客户里程约定、替换车、运维干预 |
---
## 3. 流程闭环速查(端到端一句话)
| 条线 | 闭环一句话 |
|---|---|
| 租赁 | 客户 → 模板 → 签约 → 提车应收 → 交车 → 台账账单 → 还车应结款归档 |
| 能源 | 供应商 → 加氢站 → 订单采集 → 氢费明细 → 客户账户收款 → 记录已付款 |
| 运维 | 采购/验车入库 → 牌证备车 → 交还车 → 维保故障 → 异动调拨 → 处置出库 |
| 安全 | 司机档案 → 培训资料 → 违规评级 → 违章事故 → 还车应结款费用 |
| 物流 | 合同生效 → 调度派车办结 → 台账明细/盈亏 →(演进)收款业财闭环 |
| 系统级 | 五条线业务闭环 → 三大数据底座决策 → 打通财务 YS 业财一体 |
**高频跨模块联动(写描述时勿漏)**
- 租赁签约路径依赖**客户管理**评级(标准 / 非标 / 禁止)
- **提车应收**对齐后触发运维**交车**;交车成功生成**租赁业务台账**
- **还车管理**完成后生成**还车应结款**;安全**违章/事故**费用写入应结项
- 运维**采购/三方租赁合同**自动生成**验车入库**任务
- 物流**调度办结**须车辆已**交车**;办结自动写**物流台账**
- 能源签约站**加氢订单**与非签约站**氢费明细**统一进入**氢费账户**对账收款
---
## 4. 故事点(按模块:起点 → 怎么运作 → 闭环)
> 结构对齐页面「起点 / 怎么运作 / 闭环」。标题用「模块名 + 核心动作」;描述保留谁发起、关键规则、闭环结果,不升格成完整 PRD。
> 下列为各模块业务事实摘要,用于**识别归属与用词**;材料未提及的细节**不得**脑补进描述。
### 4.1 租赁
#### 客户管理
- **起点**:业务管理组维护客户基础信息,作为后续合同与账单的统一客户主数据
- **怎么运作**:法务每 3 个月评估法律风险;财务实时维护财务风险等级;安全实时维护安全风险等级;系统综合形成签约策略
- **闭环**:未达禁止标准可签;偏离常规范式走「非标准流程」;达禁止标准禁止新签,现有合同标「高风险」并通知业务跟进或终止
#### 标准合同管理
- **起点**:法务部维护各车型试用/正式等标准模板,明确条款边界与风控要求
- **怎么运作**:数智部按模板配置电子合同;条款可设「触发车型」;「风控红线」被改进非标审批;「锁定区域」不可随意改
- **闭环**:业务员直选模板走标准流程;触碰红线或锁定区外修改转法务非标审批
#### 租赁合同
- **起点**:业务员选羚牛签约主体与乙方客户;系统按评级判标准/非标/禁止
- **怎么运作**:合同要素实时反写电子合同预览;生成电子合同/条款附件/授权委托书;越界转非标;支持续签、转正式、转三方、增值服务、授权委托书、主动终止等
- **闭环**:审批通过进入履约并串联提车应收、交车、台账;非标须法务与董事长确认后放行
#### 提车应收款
- **起点**:提交租赁合同审批时,按合同条款自动生成提车应收金额
- **怎么运作**:法务在「收款记录」导入到账(后期对接 YS/银企直联);业务/业管关联账单并分配金额;实收对齐后标记完成
- **闭环**:应收完成后按约定生成交车任务,属地运维执行交车
#### 租赁业务台账
- **起点**:运维交车成功后自动生成该车租赁账单,应付款日初始「待设置」
- **怎么运作**:设置应付款日后生成首期应收;提车实收写入首期;溢出并入第二期减免
- **闭环**:持续记录每期应收/实收/状态,支撑租期运营与还车结算
#### 还车应结款
- **起点**:运维完成还车后自动生成还车应结款任务
- **怎么运作**:业管、安全、运维、能源各自完成部门审批;汇总应退/应补;应补关联收款记录、应退关联付款记录
- **闭环**:业管发起总审批;完成后自动归档,租赁单条业务全链路闭环
---
### 4.2 能源
#### 供应商管理
- **起点**:加氢站/充电站作为供应商纳入统一体系,采购组维护基础信息与结算要素
- **怎么运作**:创建站点时绑定供应商;氢费/电费对账支持直连付款;收付款明细关联财务记录;支撑付款/收款申请审批
- **闭环**:供应商主数据与站点、对账、财务贯通,打好能源业财基础
#### 加氢站管理
- **起点**:采购部统一管理签约站/非签约站;签约站须关联供应商与系统账号
- **怎么运作**签约站账号登录加氢订单PC/移动/H5预付款余额营业状态成本价关联氢费记录能源部形成对账单并发起付款后期对接 YS
- **闭环**:站点/账号/余额/价格/营业状态集中管理,签约站可自助上报
#### 加氢订单
- **起点**签约站登录后多渠道上报订单PLC 站点可自动获取
- **怎么运作**多端快速识别记录PLC 自动获取;联动「小羚羚」预约接单,司机确认;进入加氢记录供对账
- **闭环**:主动上报或自动采集,预约在线闭环,减少手工补录
#### 车辆氢费明细
- **起点**:非签约站氢费由业务管理组-能源部手动维护
- **怎么运作**:录入并关联站点/车辆/客户对账后标「已对账」归档联动预付款余额与客户能源账户OCR 与电子围栏辅助核对
- **闭环**:签约/非签约氢费统一归集,余额变动可追溯
#### 氢费账户
- **起点**:管理客户氢费预付款余额与客户对账单
- **怎么运作**:维护余额变动;生成对账单;关联「收款记录」;收款后加氢记录标「已付款」;支持充值/开票直达财务(替代钉钉,对接 YS
- **闭环**:明细→对账→收款全链路可核对,付款状态与财务实收一致
#### 扩展规划
- **起点**:条线成熟后向上游采购与下游司机服务延伸
- **怎么运作**:上游氢气采购;下游外部氢能车司机服务;与现有供应商/站点/订单/账户衔接
- **闭环**:覆盖「采购—站点—用氢—结算—司机服务」更大范围生态
---
### 4.3 运维
#### 供应商管理
- **起点**:整车厂、三方租赁企业纳入供应商体系
- **怎么运作**:维护档案;为采购/三方租赁合同提供主数据;支撑付款底座
- **闭环**:与采购合同、付款记录贯通
#### 车辆采购 / 三方租赁合同
- **起点**:向整车厂/三方租赁厂商发起采购或三方租赁合同
- **怎么运作**:创建审批;关联付款记录;按条款自动生成验车任务
- **闭环**:合同、付款、验车联动,入库合规入口
#### 验车入库
- **起点**:对采购或三方来源氢能车执行验车
- **怎么运作**:接收验车任务;记录过程与问题;验完自动入库
- **闭环**:验车结果与合同、库存绑定,来源可审计
#### 车辆上牌
- **起点**:对仅有车架号的新车执行上牌
- **怎么运作**:筛选待上牌车;录入/同步牌照;更新库存状态
- **闭环**:牌证完整,为证照与交车提供前置条件
#### 证照管理
- **起点**:行驶证、道路运输证、登记证、特种设备证/标识、加氢卡、安全阀、压力表等一车一档
- **怎么运作**:维护档案与有效期;临近到期生成年审/等评/换证待办;推送运维/安全
- **闭环**:证照全生命周期管理,降低漏办与违规风险
#### 备车管理
- **起点**:日常提前整备,确保交车任务可随时交付
- **怎么运作**:按计划/库存策略发起检查;记录整备项与责任人
- **闭环**:交车前置完成,提升交付效率与质量一致性
#### 交车管理
- **起点**:承接租赁/物流交车任务,按区域派属地运维;司机先完成在线培训并留痕
- **怎么运作**:司机上传身份证/驾驶证/从业资格证、签名与现场拍照;交付证照及保险有效车辆;记录里程/氢量/电量/位置OCR 胎纹还车时比对算磨损等费用E 签宝电子签归档
- **闭环**:培训与交车数据完整可查,为还车费用与争议提供依据
#### 替换车管理
- **起点**:因客户或车辆原因发起临时/永久替换
- **怎么运作**:选类型与新旧车;完成替换交还;客户原因自动算费用差
- **闭环**:过程可追踪、费用可核算,履约不中断
#### 还车管理
- **起点**:处理业务/业管还车任务,按区域派属地运维
- **怎么运作**:记录还车时间/里程/氢电量/位置OCR 胎纹对比算磨损费按里程与氢电差算费用E 签宝确认归档
- **闭环**:费用依据交还对比自动出具
#### 故障管理
- **起点**:微信 AI 故障助手或人工记录故障关键信息
- **怎么运作**:记时间地点车型紧急程度;留存图文视频聊天证据;运维处理至关闭;形成待办统计;沉淀品牌故障类型统计支撑采购论证
- **闭环**:全过程留痕,证据链完整
#### 年审记录
- **起点**:按行驶证审验有效期提前 3 个月生成年审任务
- **怎么运作**:按车按月归集;完成后 OCR 新行驶证刷新证照;按月量化完成率
- **闭环**:任务不遗漏,证照与办理结果同步
#### 维修与保养记录
- **起点**:运维手动维护负责车辆维保记录(首期)
- **怎么运作**:配件费/人工费汇总;按承担方(客户/我司)生成客户账单或计入运维成本;计入车辆盈亏
- **闭环**:维保成本可追溯可分摊,支撑单车盈亏与对客户计费
#### 车辆异动
- **起点**:因当地维修/年审/保养出库异动,须提前审批
- **怎么运作**:记异动前后氢电量里程;异动期间加氢记录归集为异动成本
- **闭环**:可审批可计量,避免成本漏记
#### 车辆调拨
- **起点**:车辆从 A 地调至 B 地运营,须提前审批
- **怎么运作**:记发起方/费用/运输;接收方确认;运维操作权由 A 转 B
- **闭环**:跨区调拨透明,责任属地随车切换
#### 车辆出售、过户、报废
- **起点**:达出售/过户/报废条件发起资产变更,录入交易方价格过户残值等
- **怎么运作**:提交申请;董事长确认;运维记录全过程归档;完成后退出运营并出库
- **闭环**:处置审批留痕,生命周期闭环至出库归档
---
### 4.4 安全
#### 司机管理
- **起点**:管理物流内部司机,支撑快速选取与档案维护
- **怎么运作**:维护基础信息与在职状态;管理驾驶证/从业资格证;与交车、台账联动
- **闭环**:主数据统一、证照可查,支撑调度与合规
#### 内部司机培训
- **起点**:定期开展安全培训并形成可追溯记录
- **怎么运作**:制定计划组织参训;记录时间内容参训人;形成证据链供交管查询
- **闭环**:培训电子归档,随时可调阅
#### 安全培训资料库
- **起点**:安全部上传培训与安全运营资料供司机学习
- **怎么运作**:维护课件制度指引;分类发布版本检索;司机经 APP/小程序学习
- **闭环**:资料集中更新,移动端可学可查
#### 违规记录
- **起点**:记录内部司机运营违规
- **怎么运作**:登记事件类型时间结果;关联司机档案;联动客户安全评级
- **闭环**:违规可追踪汇总,支撑选用与评级
#### 违章管理
- **起点**:记录交通违章并与还车应结款联动
- **怎么运作**:登记时间地点分值罚款及是否缴纳;未处理纳入还车结算;逾期未缴自动生成代处理费用
- **闭环**:违章可查,代处理费用与还车/财务口径一致
#### 事故管理
- **起点**:记录事故信息,支撑定责理赔与还车结算
- **怎么运作**:登记权责划分;记保险介入/赔付/上浮;联动还车应结款写入安全费用
- **闭环**:登记→赔付→上浮→应结款贯通,费用不遗漏
---
### 4.5 物流
#### 物流合同
- **起点**:创建物流运力服务合同,录客户/车型/车辆数/交车时间地点,上传附件
- **怎么运作**:录入项目与合同要素;业务确认生效后可创建轻量调度并提示运维交车
- **闭环**:合同成为调度派车与交车的上游凭证
#### 调度任务
- **起点**:在生效合同下创建出车任务,派车派司机;非 TMS
- **怎么运作**:选合同、计划出车日、线路、是否多趟与计价口径;未交车须先交车;办结确认实际出车后自动生成物流业务明细一行
- **闭环**:出车事实追溯到合同与车牌,驱动台账落账
#### 物流台账
- **起点**:承接调度办结自动生成的出车明细,导入/行编辑补录异常与历史
- **怎么运作**:办结写入营收侧并算金额/总成本/盈亏;氢费/ETC 等成本可手工补录;汇集项目盈亏表;演进关联「收款记录」
- **闭环**:收入与司机/车辆成本同台账可核对,盈亏可对接财务实收
---
## 5. AutoRDO 应用约定
1. **标题**:优先 `模块标准名:核心动作/结果`1030 字),模块名以本词典为准(例:`验车入库:采购与三方租赁合同自动生成验车记录及入库`
2. **条线归属**:一句需求只挂一个主模块;跨条线联动写在描述里,不硬塞进标题
3. **部门用词**:口语「业管/能源组/运维」等映射到第 1 节标准名
4. **闭环口径**:若材料只讲做到一半,闭环写实际说到的结果,缺的标「待确认」
5. **不做**:不把本词典全文贴进云效描述或输出稿;不脑补材料未出现的故事点细节
6. **业财关键词**:收款记录、付款记录、对账单、应收/实收、YS、银企直联、E 签宝、小羚羚、PLC——保留原文业务对象名勿随意改写
---
## 6. 条线演进(辅助理解,非强制写入描述)
| 条线 | 现阶段 | 演进方向 |
|---|---|---|
| 租赁 | 合同电子化 · 业务闭环化 | 移动端商城直连发起合同,后续自动打通 |
| 能源 | 手工维护氢费明细 | 签约站主动上报,能源部转为核对确认 |
| 运维 | 车辆使用环节闭环 | 入库→运作→出库全链路 |
| 安全 | 司机安全全链条 | 与客户安全评级挂钩、事前预判 |
| 物流 | 合同 + 调度办结落账 | 成本自动回填、司机在线、关联收款;不做完整 TMS |
| 系统 | 业务驱动 · 财务手工 | 打通 YS · 业财一体 |

View File

@@ -0,0 +1,67 @@
# AutoRDO 清洗与拆解细则
## 目标
碎片 → 可入库的书面「标题」与「描述」。保留原意;不写成产品 PRD。
多行/多条独立输入 → **多份**转译结果(一份需求一份稿)。
## 必做与精炼规则
| 规则 | 说明 |
|---|---|
| **多条拆解** | 输入为多条独立诉求时,**先拆后洗**<br>• **拆分信号**(满足任一即可):换行且每行一句独立诉求;`1. 2. 3.` / `-` / `*` 列表;表格多行;空行分段;「另外」「还有」「第二条」等显式分条<br>• **每条**各自输出一份标题+描述+待确认,**禁止**合并成一条大需求<br>• **不拆**:同一条需求内部的续写、补充说明、功能规则子点(属于描述细节,挂在该条下)<br>• **边界不清**:无法判断是一条还是多条时,在文首标「待确认:拆条边界」,并按最可能的分条给出结果,请用户校对 |
| **OneOS 领域对齐** | 涉及 ONE-OS / 羚牛业务时,**先读** [oneos-domain.md](oneos-domain.md)<br>• 部门口语映射到标准名(业管→业务管理组,能源组→业务管理组-能源部 等)<br>• 标题模块名优先用词典标准名(如「验车入库」而非口语「验车管理」——若材料确指该模块)<br>• 跨条线联动写在描述,标题只挂主责模块<br>• **禁止**把词典全文或未在材料中出现的故事点细节写入输出 |
| **标题提炼** | 根据材料内容理解,自动概括简炼、清晰的标准需求标题:<br>• **内容理解**:准确识别归属的业务模块与核心动作/诉求(如:`验车入库:采购与三方租赁合同自动生成验车记录及入库`)。<br>• **自然流畅**:表达自然书面化,无需死板强求拼接固定句式;彻底剔除“我们要做一个”、“主要是用于”、“完成之后才能”等口语废话。<br>• **字数适中**:控制在 10-30 字内,能让读者一眼看懂需求核心。 |
| **元数据识别** | 详见 [meta-fields.md](meta-fields.md)。从台账列或正文自动识别并输出:<br>• **类型**`【新增】`/`【优化】`<br>• **优先级**`P1-高`/`P2-中`/`P3-低`<br>• **标签**:标准模块名(+ 可选 PC端/小程序)<br>• **提交部门**:映射词典标准名(业务管理部→业务管理组,数智中心→数智部 等)<br>• **提交人**:反馈方/用户列或署名<br>• 显式列优先;推断不确定则待确认;**不**直接写云效打标 |
| **描述转译** | 原文的转译结果,将口述/碎片材料转译为规范书面表达保留原意不改变谁要求什么、约束与例外不替换成「更优方案」业财对象名收款记录、付款记录、YS、E 签宝、小羚羚、PLC 等)按词典保留 |
| 书面化 | 口语改成完整句子或清晰短条目;主谓齐全 |
| 去口头禅 | 删除:嗯、啊、那个、就是说、然后呢、对对对、你懂吧 等 |
| 自我修正 | 以最后一次明确口径为准;若前后矛盾且未决,列入「待确认」 |
| 去重复 | 同一意思多轮确认只保留一处;多条拆解时,各条之间不要互相抄写无关内容 |
| 轻度格式 | 可用短标题/条目;禁止展开成总览/角色/流程图/故事点等 PRD 结构 |
| 去结尾句号 | 描述中每个句子或条目末尾去掉 `。`;保留 `` `` 若确为疑问/感叹 |
| 待确认 | 材料含糊处写 `待确认:…`,不臆造;**只要存在待确认,同轮强制**进入 [confirm-pending.md](confirm-pending.md) 的 Plan 逐条确认(无需用户再说「确认待确认」) |
| **待确认 Plan 确认** | 详见 [confirm-pending.md](confirm-pending.md)<br>• 清洗结果含待确认 → **立刻** `SwitchMode` → plan<br>• 按需求条号**逐点**确认;**优先选择题**25 项 +「其他/我补充」),选项用 `oneos-domain.md` 辅助<br>• 也支持用户粘贴**需求描述/补充说明**一次消解多点<br>• 确认后回填描述并移除已消解项;未确认不得写入定稿 |
## 多条拆解示例
**输入(多行):**
```text
还车应结款生成后自动展示违章事故信息,不必等安全员提交
验车完成后才能车辆入库
氢费账户对账单要能关联收款记录
```
**输出**3 份独立的「原始诉求AutoRDO每份各自标题+描述;不要揉成一条。
## 标题提炼对比示例
-**坏标题(直抄口语/带废话)**`我们现在要做一个验车管理功能主要是采购合同和三方租赁合同自动形成验车记录验车完成之后才能车辆入库`
-**好标题(自然清晰,覆盖标准模块)**`验车入库:采购与三方租赁合同自动生成验车记录及入库`(模块名对齐 oneos-domain
## 不做
- 不生成 AutoPRD 十章或「产品说明」
- 不写验收清单、故事点、mermaid
- 不改云效、不建【交付】/分析/设计
- 不加载 `yunxiao-requirement-lifecycle`
- 不把多条独立诉求合并成一条「大杂烩」需求
## 录音
1. 已有转写 → 按上文清洗转写稿并拆解标题与描述;转写中若含多条独立诉求,同样先拆后洗
2. 仅音频 → 回报「请提供转写文本后再 AutoRDO」停止声称已清洗完成
## 质量自检
- [ ] 多行/多条输入时,已按条拆成多份结果(条数与输入独立诉求数一致或已说明待确认边界)
- [ ] 已对照 `oneos-domain.md`ONE-OS 相关材料)
- [ ] **标题清晰通顺**(标准模块名 + 核心动作,无死板句式绑定,无口语废话)
- [ ] 部门/业财关键词已映射或保留为词典标准口径
- [ ] **描述为原文的转译结果**,干系人能认出这是自己说的意思;未脑补词典故事点
- [ ] 无口头禅堆砌、无未决矛盾被写成定论
- [ ] 描述末尾无 `。`
- [ ] 未冒充完整 PRD未把词典全文写入输出
- [ ] 已输出类型/优先级/标签/提交部门/提交人(有依据或已标待确认;未臆造提交人)
- [ ] 若存在待确认:已同轮强制进 Plan未等「确认待确认」口令优先选择题、选项有词典依据文字补充已映射到对应点定稿无未确认臆造
- [ ] 若无待确认:未多余进 Plan

View File

@@ -0,0 +1,139 @@
---
name: AutoVUL
description: >-
Generates OneOS PC version update logs from a Yunxiao (云效) iteration name by
loading all linked requirements, or from a pasted changelog list. Use when testers
or PMs say AutoVUL, 版本更新日志, 按迭代生成更新日志, 发版公告, or give a 迭代名称.
---
# AutoVULOneOS PC 版本更新日志)
面向**测试人员发版**:输入云效**迭代名称** → 拉取该迭代关联需求 → 自动生成对外版本更新日志。
也可手动粘贴变更清单(兜底)。**预计维护时长**由人工单独通知,不写进日志。
## 何时使用
- 测试说:`按 $AutoVUL` / `生成版本更新日志` / `按迭代 xxx 出更新日志`
- 输入含云效「迭代名称」
- 发版前需要统一文案口径
## 主流程(测试 · 按迭代,默认)
完整取数步骤见 [references/yunxiao-sprint.md](references/yunxiao-sprint.md)。
```text
1. 确认云效项目缺省统一运营管理平台PC端可改
2. 向用户索取「迭代名称」(若口令里已带则直接用)
3. 在云效查找该迭代 → 立即反馈成功或失败(见下)
4. 成功:列出迭代内关联「需求」清单(编号 + 标题 + 状态)供用户快速核对
5. 从每条需求提取变更素材(优先级见「素材优先级」)
6. 按本文格式分类、合并、润色 → 输出成稿正文
```
### 迭代读取 · 成功 / 失败反馈(强制)
查找迭代后**必须先反馈**,再继续或停止:
| 结果 | 反馈文案(可微调,语义不变) | 下一步 |
|------|------------------------------|--------|
| 精确命中 1 个迭代 | `✅ 已找到迭代「{名称}」(状态:{状态}),关联需求 {N} 条。` | 继续拉需求并生成 |
| 0 个匹配 | `❌ 未找到迭代「{输入}」。请核对后重新输入迭代名称(可复制云效迭代标题)。` | **停止生成**;等待用户重输 |
| 多个模糊匹配 | `⚠️ 找到多个相似迭代1)… 2)… 请回复序号或完整精确名称。` | 等用户选定后再继续 |
| 登录/权限失败 | `❌ 无法访问云效(未登录或无权限)。请在浏览器登录云效后重试,或改用手动清单。` | 停止;提示登录或兜底 |
| 迭代存在但 0 条需求 | `⚠️ 迭代「{名称}」已找到,但暂无关联需求。请确认规划后再试,或改用手动清单。` | 停止生成对外正文 |
**失败后**:用户只需再发一次迭代名称(或纠正项目名),从步骤 2 重跑;不要要求用户重装 Skill。
### 素材优先级(每条需求)
| 顺序 | 来源 | 用法 |
|------|------|------|
| 1 | 需求描述中的「更新内容」段(非「更新内容·历史」) | 首选,直接改写成日志条目 |
| 2 | AutoPRD「功能变更记录」中可对外部分 | 次选 |
| 3 | 需求标题 + 简短描述摘要 | 仅当前两者皆空时;价值句可合理补全 |
| — | 纯技术债、内部监控、未对用户开放 | **不写入**对外日志 |
Bug 类需求(类型/标签含缺陷修复、或更新内容写「修复」归入【Bug修复】其余归【新功能】。边界不清优先 Bug修复。
### 版本号与更新时间
| 字段 | 规则 |
|------|------|
| 版本号 | 优先从迭代名解析(如含 `V1.1.5` / `1.1.5`);解析不到再问用户 |
| 更新时间 | 用户提供则用;未提供可写迭代计划开始日的 `MM月DD日HH:MM`,或先问 |
| 产品线 | 默认 `OneOS PC版` |
## 兜底流程(手动清单)
无云效权限、或迭代为空时:用 [input-template.md](input-template.md) 粘贴清单,跳过迭代步骤,直接分类润色。
## 固定输出格式
```text
OneOS PC版V{主.次.修订}更新日志:
更新时间:{MM}月{DD}日{HH}:{MM}
----------------------------------------------------
【新功能】
1「{模块名}」{做了什么}{责任部门}可{用户价值 / 解决的问题}
2「{模块名}」{…}
【Bug修复】
3「{模块名}」{修复了什么}{责任部门}可{恢复的能力 / 避免的影响}
```
### 版式硬约束
| 项 | 规则 |
|----|------|
| 标题 | `OneOS PC版V` + 版本号 + `更新日志:`(如 `V1.1.5`,无空格) |
| 更新时间 | 仅开始时刻;`MM月DD日HH:MM`**禁止**「预计x分钟内完成」 |
| 分隔线 | `----------------------------------------------------` |
| 分区 | 仅 `【新功能】` / `【Bug修复】`;空类整段省略 |
| 序号 | 全篇连续,从 1 起 |
| 模块名 | `「」`;与产品菜单正式名一致 |
| 对外正文 | **不写**需求号、缺陷号、迭代 ID核对清单可另附 |
| 结尾 | 无签名、无「感谢使用」、无技术附录 |
## 分类 / 合并 / 文案(成稿规则)
| 归入【新功能】 | 归入【Bug修复】 | 不写进对外日志 |
|----------------|-----------------|----------------|
| 新增能力、新入口、新字段/流程、可感知体验优化 | 原有能力异常、报错、数据错、交互失效 | 技术债、无感性能、未开放灰度、仅内部监控 |
- **同分区同模块**合并为一条,分点用 ``
- **跨分区**同模块分栏各写一条
- 每条含:做什么 + 用户价值 + 责任部门自然嵌入(`{部门}人员可…`
- **禁止**「供…条线…使用」;部门对照 [module-role-mapping.md](module-role-mapping.md)
- 禁止编造迭代内不存在的能力;存疑跳过或标待确认(不进正式成稿)
- 单条建议 ≤100 字
排序:先新功能后修复;同分区全员影响优先;资金/合规修复置修复区最前。
## 输出纪律
1. **先**输出迭代读取反馈(✅/❌/⚠️)
2. 成功时:可先给「本迭代需求清单」短表(含编号,便于测试核对)
3. 再输出**纯文本成稿正文**(默认不要 Markdown 大标题包裹成稿)
4. 用户明确要求时,可在正文后附「分类依据 / 跳过项」
## 发布前自检
- [ ] 已反馈迭代查找结果;失败时未强行编造成稿
- [ ] 成稿条目均可追溯到本迭代关联需求素材
- [ ] 标题、时间行、分隔线正确;无预计时长
- [ ] 同模块合并正确;每条含价值 + 部门自然嵌入
- [ ] 对外正文无需求号/缺陷号/技术黑话;序号连续
## 给测试同事的口令
```text
按 $AutoVUL 生成版本更新日志。
项目统一运营管理平台PC端
迭代名称V1.1.5发版迭代
更新时间07月16日16:00
```
迭代名写错时,按提示改完再发一次即可。
手动兜底见 [input-template.md](input-template.md);成稿范例见 [examples.md](examples.md)。

View File

@@ -0,0 +1,77 @@
# AutoVUL 成稿与交互范例
## 1. 迭代读取失败 → 重输
**用户:**
```text
按 $AutoVUL迭代名称V1.1.5
```
**Agent**
```text
❌ 未找到迭代「V1.1.5」。请核对后重新输入迭代名称(可复制云效迭代标题)。
```
**用户:**
```text
V1.1.5发版迭代
```
**Agent**
```text
✅ 已找到迭代「V1.1.5发版迭代」(进行中),关联需求 3 条:
1. ONEOSP-201 车辆管理运营城市展示优化
2. ONEOSP-202 还车应结款租金计算修复
3. ONEOSP-203 业务管理新增租赁物流统计
OneOS PC版V1.1.5更新日志:
更新时间07月16日16:00
----------------------------------------------------
【新功能】
1「车辆管理」优化车辆「运营城市」展示运维部人员可快速辨认车辆所属运营区域及数据来源
2「业务管理」新增租赁、物流业务统计模块业务管理组、业务员可查看租赁经营数据业务服务组、财务部可跟踪自营物流经营情况
【Bug修复】
3「还车应结款」修复租金费用项重复及计算错误业务管理组、安全部、运维部、能源部人员还车结算金额更准确
```
## 2. 完整成稿风格基准(手动/迭代素材均可)
> 责任部门对照:`module-role-mapping.md`OneOS 业务条线说明)
```text
OneOS PC版V1.1.5更新日志:
更新时间07月16日16:00
----------------------------------------------------
【新功能】
1「加氢站管理」升级新版加氢站模块采购部可统一维护签约站与非签约站信息签约加氢站可便捷管理站点日常运营
2「车辆管理」优化车辆「运营城市」展示运维部人员可快速辨认车辆所属运营区域及数据来源
3「审批中心」支持按客户名称搜索关联合同业务员、法务部审批时可快速定位合同还车应结款添加照片附件后业务管理组、安全部、运维部、能源部会签人员可在审批流中查看完整附件
4「保险采购」支持保比价单按车辆单独勾选并分开提交审批运维部、安全部人员可按车辆分批推进投保审批
5「故障管理」增加「故障来源」字段展示运维部人员可区分上报渠道并跟进处理
6「证照管理」特种设备使用登记证/使用标识照片支持OCR识别运维部、安全部人员可减少手工录入、加快证照建档
7「全局显示」统一各模块列表分页样式与交互各模块操作人员跨页面浏览时体验一致、上手更快
8「交还车管理」支持交车/还车签章文件在线预览,运维部、业务管理组、司机可现场核对签章文件;提交时增加胎纹数据必填校验,减少漏填导致的后续结算争议
9「还车应结款」调整安全部待办区域权限安全部人员仅处理职责范围内的还车应结款审批
10「业务管理」新增租赁、物流业务统计模块业务管理组、业务员可查看租赁经营数据业务服务组、财务部可跟踪自营物流经营情况
【Bug修复】
11「还车管理」修复签字单与还车检查单/还车应结款轮胎数据不一致,运维部、业务管理组人员还车验收与结算依据保持一致
12「租赁合同」修复编辑合同提交时异常提示内容冗余业务员、法务部人员可快速定位真正错误原因
13「交还车管理」修复交车/还车签章客户名称关联错误,避免运维部、业务管理组、司机现场核对时客户信息张冠李戴
14「车辆氢费明细」修复同客户不同生效时段、以及不同客户成本单价显示异常能源部人员可准确核对氢费核算单价
15「还车应结款」修复租金费用项重复及计算错误业务管理组、安全部、运维部、能源部人员还车结算金额更准确
```
## 对照要点
| 规则 | 体现 |
|------|------|
| 先反馈迭代结果 | 失败可重输;成功列出需求再成稿 |
| 无预计时长 | 更新时间仅 `07月16日16:00` |
| 对外无需求号 | 成稿正文不出现 ONEOSP-xxx |
| 部门自然嵌入 | `运维部人员可…`,无「供…条线使用」 |

View File

@@ -0,0 +1,69 @@
# AutoVUL · 输入模板
## A. 测试人员 · 按云效迭代(推荐)
复制下面口令发给 AI改迭代名即可
```text
按 $AutoVUL 生成版本更新日志。
项目统一运营管理平台PC端
迭代名称:
更新时间:
```
### 期望反馈
- 成功:`✅ 已找到迭代「…」,关联需求 N 条` → 随后输出成稿
- 失败:`❌ 未找到迭代「…」。请重新输入迭代名称` → 改名后再发一次即可
**说明**:预计维护时长由人工单独通知,不写入版本更新日志。
---
## B. 手动清单(云效不可用时兜底)
### 版本元信息
| 字段 | 填写 | 示例 |
|------|------|------|
| 产品线 | | OneOS PC版 |
| 版本号 | | V1.1.5 |
| 更新开始时间 | | 07月16日16:00 |
| 发布范围 | 全量 / 灰度(说明) | 全量 |
| 是否对外发布 | 是 / 否 | 是 |
### 新功能(原始材料,可粗糙)
| 模块 | 做了什么 | 解决什么问题 / 用户故事 | 业务条线 | 责任部门 | 是否写入日志 |
|------|----------|-------------------------|----------|----------|--------------|
| 例:加氢站管理 | 升级新版模块 | 统一维护站点 | 能源业务条线 | 采购部、加氢站 | 是 |
| | | | | | |
### Bug修复原始材料可粗糙
| 模块 | 原问题现象 | 修复后表现 | 对用户的影响 | 业务条线 | 责任部门 | 是否写入日志 |
|------|------------|------------|--------------|----------|----------|--------------|
| 例:还车应结款 | 租金费用项重复 | 金额正确 | 避免结算偏差 | 租赁业务条线 | 业务管理组、安全部、运维部、业务管理组-能源部 | 是 |
| | | | | | | |
### 明确不要写入对外日志
- (如:重构、依赖升级、仅内部监控、未上线配置)
### 粘贴给 AI
```text
请按 $AutoVUL 用下方手动清单生成成稿(跳过云效迭代)。
要求:同模块合并;每条含「做什么 + 用户价值」;责任部门自然融入;只输出正文。
【版本元信息】
- 产品线OneOS PC版
- 版本号V
- 更新开始时间:
【新功能】
(粘贴)
【Bug修复】
(粘贴)
```

View File

@@ -0,0 +1,60 @@
# 模块 → 业务条线 / 责任部门对照
> 数据源OneOS「业务条线说明」页责任部门定义租赁 / 能源 / 运维 / 安全 / 自营)
> 生成更新日志时,**适用对象**须从此表取 `roles`,不得自造部门名。
## 五条业务条线
| ID | 条线名称 |
|----|----------|
| lease | 租赁业务条线 |
| energy | 能源业务条线 |
| ops | 运维管理条线 |
| safety | 安全管理条线 |
| self-operated | 自营业务条线 |
## 本版变更模块对照
| 更新日志模块名 | 业务条线 | lines.ts 模块 | 责任部门roles原文 |
|----------------|----------|---------------|-------------------------|
| 加氢站管理 | 能源业务条线 | 加氢站管理 | 采购部、加氢站 |
| 车辆管理 | 运维管理条线 | 验车入库 / 车辆管理(资产底座) | 运维部、采购部 |
| 审批中心 | 跨条线 | 租赁合同 + 还车应结款(审批场景) | 业务员、法务部、业务管理组、安全部、运维部、业务管理组-能源部 |
| 保险采购 | 运维管理条线 | 证照 / 保险(车辆资产关联) | 运维部、安全部 |
| 故障管理 | 运维管理条线 | 故障管理 | 运维部、司机 |
| 租赁合同 | 租赁业务条线 | 租赁合同 | 业务员、法务部 |
| 证照管理 | 运维管理条线 | 证照管理 | 运维部、安全部 |
| 全局显示 | 全系统 | 系统介绍(五条条线) | 业务管理组、运维部、采购部、安全部、法务部、财务部、业务管理组-能源部、业务服务组 |
| 交还车管理 | 运维管理条线 | 交车管理 + 还车管理 | 运维部、业务管理组、司机 |
| 还车应结款 | 租赁业务条线 | 还车应结款 | 业务管理组、安全部、运维部、业务管理组-能源部 |
| 还车管理 | 运维管理条线 | 还车管理 | 运维部、业务管理组 |
| 车辆氢费明细 | 能源业务条线 | 车辆氢费明细 | 业务管理组-能源部 |
| 业务管理 · 租赁统计 | 租赁业务条线 | 租赁业务台账 / 客户管理 | 业务管理组、业务员 |
| 业务管理 · 物流统计 | 自营业务条线 | 自营台账 | 业务服务组、财务部 |
## 写法规则
- 部门名与 `roles` **完全一致**`业务管理组-能源部` 对外可简写「能源部人员」)
- **禁止**「供…业务条线…使用」「供…人员使用」
- **推荐**`{部门}人员可…` / `{部门}可…` / `{部门}审批时可…`
- 同模块合并后,多部门用顿号或分号自然串联
- 找不到模块时:查 `lines.ts`;仍无则标「待产品确认」不进成稿
## 自然表述示例
| 模块 | 生硬(禁止) | 自然(推荐) |
|------|--------------|--------------|
| 车辆管理 | 供运维管理条线运维部使用 | 运维部人员可快速辨认车辆所属运营区域 |
| 加氢站管理 | 供能源业务条线采购部、加氢站使用 | 采购部可统一维护站点信息,加氢站可便捷管理日常运营 |
| 还车应结款 | 供租赁业务条线业务管理组…使用 | 业务管理组、安全部、运维部、能源部还车结算金额更准确 |
## 常见错误(禁止)
| 错误写法 | 正确写法 |
|----------|----------|
| 氢能运营业务人员 | 采购部、加氢站(能源 · 加氢站管理) |
| 车辆运营及资产管理业务人员 | 运维部、采购部(运维 · 车辆管理) |
| 各业务条线审批人员 | 业务员、法务部、…(按审批场景枚举) |
| 保险采购业务人员 | 运维部、安全部 |
| 还车结算业务人员 | 业务管理组、安全部、运维部、业务管理组-能源部 |
| 经营分析及管理部门 | 业务管理组、业务服务组(分租赁 / 自营) |

View File

@@ -0,0 +1,81 @@
# 云效迭代 → 需求清单AutoVUL 取数)
测试人员只提供**迭代名称**Agent 负责在云效定位迭代、拉取关联需求、抽出更新素材。
## 安全边界(强制)
- **禁止**在对话、Skill、日志、成稿中写入 Token、密码、Cookie、私钥。
- 优先复用**已登录浏览器会话**操作云效 Projex`yunxiao-requirement-lifecycle` 一致)。
- 若团队已配置本机环境变量访问 OpenAPI可走 APIToken 只读自环境,永不回显。
建议环境变量(可选,名称可按团队调整):
| 变量 | 用途 |
|------|------|
| `YUNXIAO_TOKEN` | 个人访问令牌(`x-yunxiao-token` |
| `YUNXIAO_DOMAIN` | 服务接入点域名 |
| `YUNXIAO_ORG_ID` | 组织 ID中心版 |
| `YUNXIAO_PROJECT_ID` | 默认项目 ID或运行时按项目名解析 |
## 默认项目
口令未指定时:`统一运营管理平台PC端`。项目名不精确时先问清再查迭代。
## 判定顺序:解析迭代
| 顺序 | 条件 | 结果 |
|------|------|------|
| 1 | 用户未给迭代名称 | 询问:「请输入云效迭代名称(可复制标题)」;不继续 |
| 2 | 项目未确定 | 询问精确项目名;不继续 |
| 3 | 云效不可访问 | `❌ 无法访问云效…`;不继续 |
| 4 | 名称精确匹配 1 条迭代 | `✅ 已找到迭代…`;进入拉需求 |
| 5 | 0 条 | `❌ 未找到迭代…请重新输入`;不继续 |
| 6 | >1 条相似 | `⚠️ 多个相似…请回复序号或精确名称`;等用户选定 |
| 7 | 命中但关联需求 0 | `⚠️ …暂无关联需求`;不生成对外正文 |
匹配规则:先**全等**(去首尾空格);全等失败再做包含/去空格模糊;模糊多条必须让用户确认,禁止擅自挑一个。
## 拉取关联需求
只收集工作项类型为**需求Req**且正式关联到该迭代的项。
- **浏览器路径**:打开项目 → 迭代 → 该迭代规划/工作项列表 → 筛选类型=需求 → 导出或逐条打开描述。
- **OpenAPI 路径(示意)**
1. `ListSprints`:按项目列迭代,用 `name` 匹配用户输入,得到 `sprintId`
2. `SearchWorkitems``category=Req``spaceId=项目Id``conditions` 中按字段 `sprint` CONTAINS `[sprintId]`(以租户实际 fieldIdentifier 为准;可先在需求列表页过滤后复制 `workitem/list` 的 conditions
3. 分页直到收齐(关注响应头 `x-total`
4. 需要正文时再 `GetWorkitem` 取 description
每条需求最少记录:
| 字段 | 说明 |
|------|------|
| serialNumber | 如 ONEOSP-123仅用于核对清单**不进对外成稿** |
| subject | 标题 |
| status | 状态展示名 |
| description | 用于抽取「更新内容」 |
| category / type / labels | 辅助判断新功能 vs 修复 |
## 从描述抽「更新内容」
1. 定位标题「更新内容」或「## 更新内容」段落
2. **不要**把「更新内容·历史」并入本版素材(历史仅备查)
3. 若无「更新内容」:用标题 + 需求说明摘要;仍无有效产品语义则跳过并在内部备注
## 成功反馈后的核对清单(推荐短表)
在生成成稿前输出,例如:
```text
✅ 已找到迭代「V1.1.5发版迭代」(进行中),关联需求 5 条:
1. ONEOSP-101 保险采购比价分车提交
2. ONEOSP-102 交还车签章预览
正在按 AutoVUL 格式生成更新日志…
```
用户若立刻纠正「某条不要进日志」,从素材中剔除后再出成稿。
## 与发版任务关系
本 Skill **只读**迭代与需求,**不创建**【发版】任务、不改云效状态。发版挂链仍用 `yunxiao-requirement-lifecycle`(如「准备发布」口令 / A08

View File

@@ -0,0 +1,113 @@
---
name: YunxiaoPM
description: >-
产品经理云效Projex自动化记录需求压缩点选 1a2b3a4d类型/项目/优先级/标签)、
实时点选云效项目、推进 待处理→已确认→分析中→设计中→设计完成→待开发,
交付树【交付】ASSOCIATED /【分析】【设计】TASK_SUB无单快轨与编号直推交棒何斐
创建迭代并挂【交付】(不挂需求)。用户说 YunxiaoPM、YunxiaoPMapp、需求任务、记录需求、受理确认、开始分析、
开始设计、设计完成、交棒开发、快轨待开发、编号直推、创建迭代 时使用。
不建【开发】/【测试】。凡写云效先 Plan 确认再一口气 apply禁止对齐
yunxiao-requirement-lifecycle。
---
# 需求任务YunxiaoPM
产品部云效自动化。斜杠调起 **`/YunxiaoPM`**;对外中文名 **需求任务**(原名 YunxiaoPMapp。本 Skill **自洽成篇****禁止** fork / include / 「对齐」`yunxiao-requirement-lifecycle`
产品经理会话**不要**同时挂载旧 lifecycle Skill避免双建任务。
## Plan 模式门禁(强制 · 凡写云效)
凡会改云效的操作(建单、改状态、建/改任务、打标、传附件、改负责人、建迭代等Agent **第一步**必须:
1. `SwitchMode`**plan**(说明:先对齐参数与执行清单,确认后再一口气 apply
2. **新建**依赖项目空间时:先按 [references/project-selection.md](references/project-selection.md) **实时拉项目列表并点选(门禁 PJ**;禁止静默使用 `runtime-ids.json` 默认 `spaceIdentifier`。口令/选项**无法对应**时:**自动重拉项目列表一次**再匹配;仍失败则停请用户重选(禁止第 3 次空转拉取)。
3. Plan 写清:**已选项目名 + spaceId**、目标需求/任务**编号**、将改状态、将建/复用的交付·分析·设计编号策略、迭代版本类型若适用、§0.1① 占位风险勾选(若适用)、**不会做的事**(不建【开发】/【测试】、不按标题查重)。**记录需求**须按 [compact-select.md](references/compact-select.md) 给出 14 题字母表,接受压缩答复如 `1a2b3a4d`
4. **用户确认 / 批准 Plan / 「执行」之前**:禁止 apply项目未点选同禁。压缩串须先解析回显再等「执行」。
5. 确认后切回 Agent**同一轮按清单一口气执行到底**,再一次性校验回报;中途缺参才停下。
**例外(可读可不进 Plan** 仅查状态 / 为什么没流转 / 给我方案。
**禁止:** 以「参数已齐」「速度路径」「用户很熟」跳过 Plan「批准计划」若清单未点齐关键参数**PJ 项目**),仍视为未完成门禁。
## 真相源模型
```text
需求状态 = 阶段看板唯一真相
【交付】 = 每需求最多 1 条容器ASSOCIATED→需求
【分析】/【设计】 = TASK_SUB→交付交付「子项」必可见与 ASSOCIATED 同 create 互斥)
【开发】/【测试】 = 不进本 Skill
查重/复用唯一渠道 = 任务编号ONEOS-xx禁止按标题
```
编号权威:需求描述 `## 工作项编号(系统)`(见 [references/workitem-ids.md](references/workitem-ids.md))。
操作顺序:口令显式编号 > 读该区块 > ASSOCIATED/SUB 校验;冲突则停。
## 外置调用(禁止本 Skill 内嵌对方全文)
| 时机 | 调用 |
|---|---|
| 入库清洗聊天/录音 | **`$AutoRDO`**(独立 Skill路径 `AutoRDO/SKILL.md`;不内嵌清洗细则) |
| 设计完成 PRD + 对象存储链接 + 回填【交付】 | **`$oneos-autoprd`AutoPRD**;创建【交付】仍占位,设计完成才灌 MD |
| 人员 / 状态 / 字段 ID项目 catalog 仅缓存 | [assets/runtime-ids.json](assets/runtime-ids.json) |
| **PJ 云效项目点选**(新建必选;实时列表) | [references/project-selection.md](references/project-selection.md) · [scripts/list_projects.py](scripts/list_projects.py) |
| **压缩点选 `1a2b3a4d`**(类型/项目/优先级/标签) | [references/compact-select.md](references/compact-select.md) · [scripts/list_tags.py](scripts/list_tags.py) |
| 阶段日历工时 | [references/work-hours.md](references/work-hours.md) + [assets/cn-workday-calendar.json](assets/cn-workday-calendar.json) + [scripts/workday_hours.py](scripts/workday_hours.py) |
## 路由(按需完整阅读)
| 场景 | 模块 |
|---|---|
| 交付树、关联约定、禁止项 | [references/model.md](references/model.md) |
| 描述双段 · AutoRDO / 占位 / AutoPRD | [references/description-split.md](references/description-split.md) |
| 步骤 05 标准路径 | [references/stage-flow.md](references/stage-flow.md) |
| 无单快轨到待开发 | [references/fast-track.md](references/fast-track.md) |
| 编号直推交棒 | [references/number-push.md](references/number-push.md) |
| 交棒门禁 · 回退最小集 | [references/handoff-and-rollback.md](references/handoff-and-rollback.md) |
| 计划开始/完成 · 阶段日历工时 | [references/work-hours.md](references/work-hours.md) |
| Make 导出 ZIP + 复制截图 | [references/make-export-attach.md](references/make-export-attach.md) |
| 创建迭代 · V主.副.子 · 只挂交付 | [references/sprint.md](references/sprint.md) |
| 口令面 | [references/commands.md](references/commands.md) |
| 记录需求元字段(优先级/标签/提交部门/提交人) | [references/record-meta-fields.md](references/record-meta-fields.md) |
| 云效项目点选 PJ | [references/project-selection.md](references/project-selection.md) |
| 验收清单 · 回报模板 | [references/acceptance.md](references/acceptance.md) |
| 交接契约(开发 Skill 入口) | [references/handoff-contract.md](references/handoff-contract.md) |
| 已验证实写 API · 极速建单 | [references/live-api.md](references/live-api.md) · [scripts/live_create_fast.py](scripts/live_create_fast.py) |
| 2026-07-23 复盘与耗时对比 | [references/live-perf-2026-07-23.md](references/live-perf-2026-07-23.md) |
## 口令速查
```text
记录需求:…;项目=Plan 点选,勿默认);优先级=紧急|高|中|低;标签=…;提交部门=…;提交人=…;推进至=暂不推进|已确认|分析中|设计中|设计完成|待开发|待开发(快轨)
受理确认ONEOS-xx
开始分析ONEOS-xx
开始设计ONEOS-xx交付任务=…;分析任务=…
设计完成ONEOS-xx设计任务=…;原型=…
交棒开发ONEOS-xx交付任务=…
快轨待开发ONEOS-xx
编号直推:分析任务=ONEOS-b / 设计任务=ONEOS-c / 交付任务=ONEOS-a
创建迭代:版本类型=主|副|子;交付任务=ONEOS-a,ONEOS-b,…;名称前缀=…
```
**PJ 项目**:新建前必须从云效实时列表点选(见 [project-selection.md](references/project-selection.md));口令带项目名仅作预填建议。
**压缩点选**:记录需求 Plan 展示 `1.类型 2.项目 3.优先级 4.标签` 字母表;你可回 `1a2b3a4d`(见 [compact-select.md](references/compact-select.md))。标签未命中会自动重拉一次标签候选并重生选项。
**记录需求**元字段(优先级/标签/提交部门/提交人):与压缩点选并用;缺项用字母表补齐。见 [references/record-meta-fields.md](references/record-meta-fields.md)。
后续口令**优先带任务编号**;未带则读「工作项编号(系统)」;仍无则询问;**禁止按标题补全**。
## 本 Skill 终点
交棒完成(需求=待开发;【交付】负责人=何斐)后结束。可一句:「请技术经理使用开发 Skill」。
例外:交棒后「创建迭代并关联交付」仍属 YunxiaoPM。
**明确不做:** 创建【开发】/【测试】、挂仓库、开分支、提测、写用例。
## §0.1 五条补齐(摘要)
1. **交棒占位**:标准路径下交付仍为 `等待设计任务完成后自动填入` 时**允许**交棒,但 Plan 必须勾选风险,回报首行标红。**快轨**有手工/原型时禁止占位(见 [fast-track.md](references/fast-track.md))。
2. **预计工时**:标准路径 = **阶段日历工时**工作日×8**快轨待开发**需求默认预计/实际各 **2**
3. **编号真相源**在需求「工作项编号(系统)」;新建后立即 PATCH 该区块。
4. **无单快轨**:【设计】描述同步需求;计划起止=当日TASK_SUB→交付后补 ASSOCIATED→需求【交付】描述手工同步或 AutoPRD交付/设计与需求同标签;设计当日完成态。
5. **描述双段**不互相覆盖;迭代**只挂【交付】**(需求不挂迭代);回退重做设计则**新开设计编号**,交付计划开始不改。
细则见各 references。

View File

@@ -0,0 +1,49 @@
# 验收清单与回报
## apply 后必须自检
| # | 项 | 通过标准 |
|---|---|---|
| 1 | 需求编号 | 回报含 ONEOS-xx |
| 2 | 任务编号 | 交付/分析/设计凡新建或操作均回报编号;禁止只报标题 |
| 3 | 编号区块 | 需求「工作项编号(系统)」与实际一致 |
| 4 | ASSOCIATED | **仅交付**详情关联项可见需求(`createWorkitemRelationInfo=ASSOCIATED`;禁止 PARENT 冒充) |
| 5 | SUB | **必过**:分析/设计 create 用 `TASK_SUB→交付`(含 `parent`+`parentIdentifier`交付「子项」tab 须可见。与 ASSOCIATED 同 create 互斥,阶段任务关联项可空(见 live-api.md |
| 6 | 计划开始 | 未误覆盖已有值 |
| 7 | 阶段日历工时 | 有计划完成时已写入;脚注存在;回报用语正确 |
| 8 | 交棒 | 需求=待开发;交付负责人=何斐(交棒场景) |
| 9 | 占位风险 | 交付仍占位时首行标红 |
| 10 | 负向 | 本轮**无**【开发】/【测试】任务;未按标题查重 |
设计完成额外AutoPRD 段已写交付非占位除非失败停下ZIP+截图已挂或已列出缺项。
迭代额外:只挂【交付】(需求不挂);版本号符合递增规则。
## 回报模板(精简)
```text
【YunxiaoPMapp】
风险:(若有占位交棒则首行标红)
需求ONEOS-xx | 状态=…
交付ONEOS-a | 负责人=…
分析ONEOS-b | …(无则写无)
设计ONEOS-c | …(无则写无)
阶段日历工时:分析 Hh / 设计 Hh若本轮写入
附件:…(若本轮)
迭代:…(若本轮)
下一步:请技术经理使用开发 Skill交棒后
```
## 适合全自动 vs 人工门禁
| 适合全自动 | 建议半自动/人工门禁 |
|---|---|
| 建单、打标签、挂迭代、写描述、建交付树、改状态、交棒负责人、幂等查重 | 受理(已确认)、是否快轨、设计完成是否真可开发、跨需求优先级与迭代容量、回退与取消 |
## 实写性能2026-07-23 复盘)
| 项 | 要求 |
|---|---|
| 改状态 | 只用 `status/transit`(见 [live-api.md](live-api.md) |
| 改【交付】负责人 | 只用 `PATCH …/{id}` + `propertyKey=assignedTo` |
| 极速复测 | `scripts/live_create_fast.py`;默认不开浏览器 |

View File

@@ -0,0 +1,4 @@
interface:
display_name: "需求任务"
short_description: "云效:压缩点选记录需求→分析/设计→交棒待开发→挂迭代"
default_prompt: "按需求任务(/YunxiaoPM处理先 Plan 出压缩点选字母表并确认项目,用户回 1a2b3a4d 与「执行」后再 apply。"

View File

@@ -0,0 +1,95 @@
{
"schema_version": 1,
"timezone": "Asia/Shanghai",
"note": "法定放假日 holidays国务院公布的周末调休补班日 workdays_on_weekend。缺年则禁止静默按仅去周末计算。",
"source": {
"2025": "国办发明电202412号 https://www.gov.cn/zhengce/zhengceku/202411/content_6986383.htm",
"2026": "国办发明电20257号 https://www.gov.cn/zhengce/content/202511/content_7047090.htm"
},
"years": {
"2025": {
"holidays": [
"2025-01-01",
"2025-01-28",
"2025-01-29",
"2025-01-30",
"2025-01-31",
"2025-02-01",
"2025-02-02",
"2025-02-03",
"2025-02-04",
"2025-04-04",
"2025-04-05",
"2025-04-06",
"2025-05-01",
"2025-05-02",
"2025-05-03",
"2025-05-04",
"2025-05-05",
"2025-05-31",
"2025-06-01",
"2025-06-02",
"2025-10-01",
"2025-10-02",
"2025-10-03",
"2025-10-04",
"2025-10-05",
"2025-10-06",
"2025-10-07",
"2025-10-08"
],
"workdays_on_weekend": [
"2025-01-26",
"2025-02-08",
"2025-04-27",
"2025-09-28",
"2025-10-11"
]
},
"2026": {
"holidays": [
"2026-01-01",
"2026-01-02",
"2026-01-03",
"2026-02-15",
"2026-02-16",
"2026-02-17",
"2026-02-18",
"2026-02-19",
"2026-02-20",
"2026-02-21",
"2026-02-22",
"2026-02-23",
"2026-04-04",
"2026-04-05",
"2026-04-06",
"2026-05-01",
"2026-05-02",
"2026-05-03",
"2026-05-04",
"2026-05-05",
"2026-06-19",
"2026-06-20",
"2026-06-21",
"2026-09-25",
"2026-09-26",
"2026-09-27",
"2026-10-01",
"2026-10-02",
"2026-10-03",
"2026-10-04",
"2026-10-05",
"2026-10-06",
"2026-10-07"
],
"workdays_on_weekend": [
"2026-01-04",
"2026-02-14",
"2026-02-28",
"2026-05-09",
"2026-09-20",
"2026-10-10"
]
}
}
}

View File

@@ -0,0 +1,221 @@
{
"schema_version": 1,
"skill": "YunxiaoPM",
"verified_at": "2026-07-25",
"note": "YunxiaoPM constants. Project space MUST be user-selected (PJ gate); project.spaceIdentifier is last-known cache only — never auto-apply. See references/project-selection.md.",
"project": {
"selection_mode": "user_pick_required",
"name": null,
"name_aliases": [
"01_ONEOS",
"ONEOS",
"统一运营管理平台",
"统一运营管理平台PC端",
"统一运营管理平台 PC 端"
],
"spaceIdentifier": null,
"customCode": null,
"spaceType": "Project",
"organizationIdentifier": "697c54a19df7fdfa65466405",
"default_sprint_name_prefix": "统一运营管理平台PC端",
"list_api": "GET /projex/api/workspace/project/search/list",
"last_selected": {
"name": "01_ONEOS",
"spaceIdentifier": "1280be963a5a2cc126a4118dca",
"customCode": "ONEOS",
"note": "历史常用项;仅作预填建议,禁止未点选即使用"
},
"refreshed_at": "2026-07-25"
},
"projects_catalog": [
{
"name": "05_羚牛碳资产平台",
"identifier": "ff104a3bce09463da136a97999",
"customCode": "CARBON"
},
{
"name": "06_对外客户项目",
"identifier": "baca8b4d676c5af67e475caec0",
"customCode": "CUST"
},
{
"name": "07_LNBOX",
"identifier": "35e1e915a052379bbdfb993aac",
"customCode": "LNBOX"
},
{
"name": "04_AI应用",
"identifier": "d9002ea72c6c3a1a97b02be750",
"customCode": "AIAPP"
},
{
"name": "03_数据中台",
"identifier": "a801cef5c9a68fa051c07432c7",
"customCode": "DATA"
},
{
"name": "02_小羚羚APP",
"identifier": "db771a2cca07bed43b369af077",
"customCode": "XLLAPP"
},
{
"name": "01_ONEOS",
"identifier": "1280be963a5a2cc126a4118dca",
"customCode": "ONEOS"
},
{
"name": "敏捷研发示例项目",
"identifier": "65eca0c2e16a23939081e19e14",
"customCode": "DEMO"
}
],
"people": {
"wangmian": {
"displayName": "王冕",
"identifier": "6811df000601d2fea60144a9",
"role": "产品创建人/默认负责人"
},
"hefei": {
"displayName": "何斐",
"identifier": "695f0400562f09713f9c3a93",
"role": "待开发交棒【交付】负责人"
}
},
"tags": {
"故障管理": "ceb526a7343995577645317e9a",
"还车应结款": "4204960ce658c94b17abb7c5f6",
"工作台": "b62d21beac55c0b43389915eab",
"交车管理": "b6947b5aca82a8c759612ba039",
"合同管理": "23873be81931cb0dc1bf87a456",
"安全培训": "76988b5f73ef515de5930d59b9",
"证照管理": "11f4c2ec65901a8f3199c81706",
"还车管理": "1e0fce2d6929ff4ac13b310e97"
},
"status": {
"req": {
"待处理": "100005",
"已确认": "32",
"分析中": "154395",
"设计中": "156603",
"设计完成": "307012",
"待开发": "1582fc929d429111b925309493"
},
"task": {
"待处理": "100005",
"已完成": "100014"
},
"transit_api": "POST /projex/api/workitem/workitem/{id}/status/transit",
"fast_handoff_hops": [
"设计完成",
"待开发"
],
"note": "见 references/live-api.md禁止再用 updateStatus"
},
"workitem_types": {
"product_req": {
"name": "产品类需求",
"category": "Req",
"identifier": "9uy29901re573f561d69jn40"
},
"task": {
"name": "任务",
"category": "Task",
"identifier": "ba102e46bc6a8483d9b7f25c"
}
},
"priority": {
"紧急": "646004e97f54bb77fec7b455df",
"高": "95b89e0a524d9693e1f335ffe5",
"中": "fa155d1214f9f8db222d39db3b",
"低": "92924feff9c1085891e7511872"
},
"fields": {
"plan_start": {
"fieldIdentifier": "79",
"name": "计划开始时间",
"value_shape": "YYYY-MM-DD HH:mm:ss China wall time preferred; epoch ms string also accepted",
"example": "2026-07-27 12:00:00",
"update_api": "POST /projex/api/workitem/workitem/field/value/{workitemId} form fieldValueList=JSON"
},
"plan_end": {
"fieldIdentifier": "80",
"name": "计划完成时间",
"value_shape": "YYYY-MM-DD HH:mm:ss or epoch ms string",
"update_api": "POST /projex/api/workitem/workitem/field/value/{workitemId} form fieldValueList=JSON"
},
"estimated_hours": {
"fieldIdentifier": "101586",
"name": "预计工时",
"note": "不可直接改字段;须工时预估登记",
"create_api": "POST /projex/api/workitem/workitem/time/estimate body spentTime,type,recordUserIdentifier,workitemIdentifier",
"delete_api": "DELETE /projex/api/workitem/workitem/time/estimate/{workitemId}/{estimateId}",
"list_api": "GET /projex/api/workitem/workitem/time/estimate/list?workitemIdentifier="
},
"actual_hours": {
"name": "实际工时",
"note": "快轨待开发默认 2",
"create_api": "POST /projex/api/workitem/workitem/time body actualTime,type,recordUserIdentifier,workitemIdentifier,gmtStart,gmtEnd (epoch ms string)",
"list_api": "GET /projex/api/workitem/workitem/time/list?workitemIdentifier=",
"fast_track_default": 2,
"verified_at": "2026-07-27",
"verified_on": "ONEOS-293"
},
"fast_track": {
"req_estimated_hours": 2,
"req_actual_hours": 2,
"design_plan_start_end_same_day": true,
"design_description": "copy_req_document",
"delivery_description": "manual_sync_or_autoprd",
"delivery_design_same_tags_as_req": true,
"design_associated_to_req_after_task_sub": true,
"document_update_api": "PATCH /projex/api/workitem/workitem/{id}/document {content,formatType:RICHTEXT}"
},
"submit_department": {
"fieldIdentifier": "3132597a9718d1c282b7ba5a0c",
"name": "提交部门",
"format": "string input",
"update_api": "POST /projex/api/workitem/workitem/field/value/{workitemId} form fieldValueList=JSON",
"verified_at": "2026-07-27",
"verified_on": "ONEOS-293"
},
"submitter": {
"fieldIdentifier": "9e01269e96f91fbb97d36bf5b3",
"name": "提交人",
"format": "string input",
"update_api": "POST /projex/api/workitem/workitem/field/value/{workitemId} form fieldValueList=JSON",
"verified_at": "2026-07-27",
"verified_on": "ONEOS-293"
},
"tag": {
"fieldIdentifier": "tag",
"name": "标签",
"propertyKey": "tag"
}
},
"assignee_rules": {
"待开发_交付任务": "hefei",
"分析中_交付与分析": "creator",
"设计中_设计": "creator"
},
"relation": {
"delivery_to_req": "ASSOCIATED",
"stage_to_delivery": "TASK_SUB",
"create_field": "createWorkitemRelationInfo",
"forbid": [
"PARENT_as_关联项",
"ASSOCIATED_only_for_stage_tasks_without_TASK_SUB"
],
"note": "交付必须 ASSOCIATED→需求。分析/设计默认 TASK_SUB→交付子项 tab。二者同 create 互斥。见 references/live-api.md"
},
"delivery_placeholder": "等待设计任务完成后自动填入",
"task_title_prefixes": {
"delivery": "【交付】",
"analysis": "【分析】",
"design": "【设计】"
},
"publish_url": {
"shape": "{baseUrl}/{prototype-id}/index.html",
"forbid_prototypes_prefix": true,
"require_index_html": true
}
}

View File

@@ -0,0 +1,317 @@
# YunxiaoPMapp 实现原理说明
> 供**开发部门**设计 / 制作「开发侧 Skill」暂称 **YunxiaoDevapp**)时对齐契约。
> 本文描述产品侧 Skill **YunxiaoPMapp** 的模型、边界、数据契约与交棒接口;**不是**对 `yunxiao-requirement-lifecycle` 的兼容说明。
> 技能包https://github.com/15810879921-coder/oneos-pm-skills · `skills/YunxiaoPMapp/`
> 文档版本2026-07-24
---
## 1. 为什么拆成两个 Skill
| | YunxiaoPMapp产品 | 开发 Skill待建 |
|---|---|---|
| 职责 | 需求从「待处理」到「待开发」交棒 | 从「待开发」到开发完成 / 提测前 |
| 任务类型 | 【交付】【分析】【设计】 | 【开发】(可多条)、可选挂仓库/分支 |
| 负责人交接 | 交棒时【交付】→ **何斐** | 拆【开发】子任务并指派研发 |
| 明确不做 | 建【开发】/【测试】、开分支、提测 | 不建【分析】/【设计】、不改 AutoRDO 段 |
**硬规则:** 两个 Skill **禁止互相 include / fork 全文**;只认本文第 6 章「交棒契约」。产品会话与开发会话不要同时挂载旧 `yunxiao-requirement-lifecycle`,避免双建任务树。
---
## 2. 核心真相源(必须先统一)
```text
需求状态 = 阶段看板唯一真相(分析中 / 设计中 / 待开发 …)
【交付】任务 = 每需求最多 1 条「交付容器」
【分析】【设计】 = 【交付】下的阶段子项(产品侧建)
【开发】【测试】 = 开发 / 测试 Skill 建(产品侧永不创建)
查重 / 复用 = 只认云效任务编号 ONEOS-xx禁止按标题
```
### 2.1 关系模型(云效)
```mermaid
flowchart TB
Req["产品类需求 ONEOS-R"]
DEL["【交付】ONEOS-a"]
AN["【分析】ONEOS-b"]
DE["【设计】ONEOS-c"]
DEV["【开发】… 开发 Skill"]
TEST["【测试】… 测试 Skill"]
DEL -->|"ASSOCIATED 关联项"| REQ
AN -->|"TASK_SUB 子项"| DEL
DE -->|"TASK_SUB 子项"| DEL
DEV -.->|"建议SUB→交付 或 ASSOCIATED→需求+交付"| DEL
TEST -.->|"测试 Skill"| REQ
```
| 关系 | 谁写 | 验收 |
|---|---|---|
| `ASSOCIATED` | **仅【交付】→ 需求** | 交付详情「关联项」可见需求 |
| `TASK_SUB` | 【分析】/【设计】→【交付】 | 交付详情「子项」可见阶段任务 |
| (开发侧建议) | 【开发】→【交付】或需求 | 由开发 Skill 自定,但须可编号查重 |
**踩坑(已复现):** 对分析/设计只写 `parentIdentifier` + `ASSOCIATED→需求`交付「子项」会为空。正确create 时 `createWorkitemRelationInfo=TASK_SUB` + `parent`/`parentIdentifier`=交付。同一 create **只能**带一条关系ASSOCIATED 与 TASK_SUB 互斥。
### 2.2 标题只是展示
- 形式:`【交付】`/`【分析】`/`【设计】` + 需求标题
- **不参与查重**;改标题不影响幂等
- 开发侧【开发】标题建议 `【开发】` + 范围简述,同样**只认编号**
---
## 3. 编号权威源
需求描述固定区块(机器可解析):
```markdown
## 工作项编号(系统)
- 交付ONEOS-a
- 分析ONEOS-b无则写无
- 设计ONEOS-c无则写无
```
| 规则 | 说明 |
|---|---|
| 新建后立即 PATCH | 只改本区块,不动 AutoRDO / AutoPRD |
| 操作顺序 | 口令显式编号 > 读本区块 > ASSOCIATED/SUB 反查 |
| 冲突 | 停下人工;**禁止按标题猜** |
| 多交付编号 | 停止并列号请人合并 |
**开发 Skill 入口建议:** 口令必须带 `需求=ONEOS-R` + `交付任务=ONEOS-a`;缺则读本区块;仍无则询问。
---
## 4. 需求描述双段(产品写 · 开发只读)
```markdown
## 原始诉求AutoRDO
(聊天/录音清洗稿;设计完成也不删)
## 产品说明AutoPRD
(设计完成才灌满;含对象存储预览链接)
## 工作项编号(系统)
- 交付 / 分析 / 设计
```
| 段 | 谁写 | 开发侧用法 |
|---|---|---|
| AutoRDO | `$AutoRDO` → 产品记需求时 | 占位交棒时**唯一可信**业务原文 |
| AutoPRD | `$oneos-autoprd` → 设计完成时 | 正式需求说明;缺则有权要求产品补设计完成 |
| 编号区块 | YunxiaoPMapp | 定位交付树 |
**【交付】描述:** 设计完成前固定占位文案 `等待设计任务完成后自动填入`;设计完成后替换为 AutoPRD 正文。
**允许占位交棒**,但产品回报必须标红风险;开发 Skill 应检测占位并提示「材料不齐,可凭 AutoRDO 开工或退回补设计」。
对象存储预览 URL 形态:`{baseUrl}/{prototype-id}/index.html`(禁止加 `prototypes/` 前缀、禁止去掉 `index.html`)。
---
## 5. 产品侧阶段状态机0→5
```text
0 创建需求(待处理) ─AutoRDO→ 仅需求,不建任务
1 受理确认(已确认) 仍不建任务
2 分析中 建【交付】+【分析】
3 设计中 建【设计】;收口【分析】计划完成
4 设计完成 收口【设计】AutoPRD+附件;灌【交付】描述
5 待开发交棒 ★ 需求→待开发;【交付】负责人→何斐
★ = YunxiaoPMapp 终点 / 开发 Skill 起点
```
### 5.1 各步要点(开发需知道的副作用)
| 步骤 | 需求状态 | 任务侧关键动作 |
|---|---|---|
| 2 分析中 | 分析中 | 新建【交付】ASSOCIATED→需求描述=占位;计划开始仅空写当日且**此后不可改**新建【分析】TASK_SUB→交付 |
| 3 设计中 | 设计中 | 新建【设计】;【分析】计划完成=当日 + 阶段日历工时 |
| 4 设计完成 | 设计完成 | 【设计】完成态;需求+交付挂 ZIP/截图;交付描述换正式说明 |
| 5 交棒 | **待开发** | **只改交付负责人→何斐**;不新建分析/设计;不写交付计划完成 |
### 5.2 两条旁路(仍交到同一终点)
| 路径 | 前提 | 行为 |
|---|---|---|
| **无单快轨** | 尚无分析路径 / 明确跳过分析 | 待开发 + 新建交付+设计(设计当日收口);**不建分析**;默认可不跑 AutoPRD |
| **编号直推** | 已有分析/设计**编号** | 收口空计划完成 → 待开发 + 交付交棒何斐;不新建冗余单 |
---
## 6. 交棒契约(开发 Skill 必须实现)
### 6.1 入口条件(产品已完成)
```text
需求状态 = 待开发
【交付】任务编号 = ONEOS-a唯一
【交付】负责人 = 何斐
【交付】ASSOCIATED → 该需求
可选:分析/设计编号在「工作项编号(系统)」中
```
### 6.2 开发 Skill 建议入口口令
```text
接手开发:需求=ONEOS-R交付任务=ONEOS-a
拆分开发:交付任务=ONEOS-a范围=前端|后端|…;负责人=…
开始开发:开发任务=ONEOS-d
开发完成:开发任务=ONEOS-d
```
### 6.3 开发 Skill 建议职责边界
| 应做 | 不应做 |
|---|---|
| 在【交付】下建一条或多条【开发】(编号幂等) | 再建【分析】/【设计】或第二套【交付】 |
| 正式关联:建议 SUB→交付或同时 ASSOCIATED→需求 | 只按标题「【开发】xxx」查重 |
| 挂仓库 / 分支 / MR按你们 Codeup 规范) | 覆盖需求 AutoRDO 段 |
| 改【开发】状态与负责人 | 擅自把需求从待开发退回(除非产品授权回退口令) |
| 检测交付描述是否仍为占位并提示 | 假装 AutoPRD 已齐全 |
| 全部【开发】完成后通知测试 Skill / 建【测试】 | 在产品 Skill 会话里混跑 |
### 6.4 共享常量(可引用,勿整包加载)
路径均在 `skills/YunxiaoPMapp/assets/`
| 文件 | 内容 |
|---|---|
| `runtime-ids.json` | 项目 spaceId、何斐 ID、工作项类型、状态 transit、字段 79/80 |
| `cn-workday-calendar.json` | 法定节假日 / 调休(阶段日历工时) |
开发侧可复制一份到自己的 `assets/`,或只读引用短路径;**不要**把 YunxiaoPMapp 的 references 全文 include 进开发 Skill。
---
## 7. 计划时间与「阶段日历工时」
产品侧口径(开发侧若写计划时间建议对齐语义):
| 对象 | 计划开始 | 计划完成 | 预计工时 |
|---|---|---|---|
| 【交付】 | 首次分析中空则写当日,**永不覆盖** | 产品侧不写(留给上线) | 一般不推全周期 |
| 【分析】【设计】 | 创建时空则写当日,**永不覆盖** | 阶段收口日 | `工作日×8` |
```text
预计工时 = 阶段日历工时Lead Time≠ 人力投入人天
算法起止日含首尾扣周末与法定假计入调休补班×8 小时
禁止:(结束−开始+1×8 的自然日算法
```
脚注固定:`【系统】预计工时=阶段日历工时工作日×8非人力投入预估`
脚本:`scripts/workday_hours.py`
**建议:** 开发 Skill 若给【开发】写预计工时,在文档中明确是「人力投入预估」还是「阶段日历工时」,避免与产品侧混称。
---
## 8. Agent 运行时原理(制作 Skill 时照抄模式)
### 8.1 Plan 门禁
凡写云效:`SwitchMode → plan` → 用户确认 → 一口气 apply → 一次校验回报。
禁止用「参数已齐 / 速度路径」跳过 Plan。
### 8.2 模块化路由
`SKILL.md` 只做路由与门禁;细则在 `references/*.md`;常量在 `assets/`;脚本在 `scripts/`
外置能力AutoRDO、AutoPRD**调用对方 Skill**,不内嵌对方全文。
### 8.3 幂等
```text
幂等键 = 项目 + 需求编号 + 任务类型角色(交付/分析/设计/开发…)+ 已登记任务编号
命中编号 → 复用并补缺字段;禁止新建第二条同角色主容器(交付唯一)
```
### 8.4 验收与回报
每次 apply 后自检(产品侧清单见 `references/acceptance.md`)。开发侧建议至少回报:
```text
【YunxiaoDevapp】
需求ONEOS-R | 状态=待开发|开发中|…
交付ONEOS-a | 负责人=…
开发ONEOS-d1, ONEOS-d2 | …
仓库/分支:…
下一步:…
```
### 8.5 已验证写路径(可复用思路)
| 动作 | 约定(见 live-api.md |
|---|---|
| 改状态 | `POST …/status/transit`(勿用错误 updateStatus |
| 改负责人 | `PATCH …/{id}` + `propertyKey=assignedTo` |
| 建单关系 | create 带 `createWorkitemRelationInfo` |
| 极速复测 | `scripts/live_create_fast.py`(可参考,开发侧另写自己的脚本) |
---
## 9. 回退最小集(开发需配合)
| 场景 | 产品侧规则 | 开发侧注意 |
|---|---|---|
| 待开发 → 退回设计中 | 需求回退;交付负责人可改回产品;**交付计划开始不改**;重做设计则**新开设计编号** | 已建【开发】是否取消 / 暂停由开发 Skill 定义;勿静默删编号 |
| 设计完成后需求大变 | Plan 问是否回退;更新 AutoPRDAutoRDO 保留+变更纪要 | 勿覆盖 AutoRDO |
| 取消需求 | 任务标取消;不删编号区块 | 同步取消未完成【开发】 |
---
## 10. 建议的「YunxiaoDevapp」目录骨架
```text
YunxiaoDevapp/
├── SKILL.md # 门禁 + 路由 + 边界(引用本文契约,不 include PMapp
├── assets/
│ └── runtime-ids.json # 可从 PMapp 复制/裁剪
├── references/
│ ├── model.md # 【开发】与交付/需求的关系约定
│ ├── handoff-intake.md # 认交付编号 + 占位检测
│ ├── split-dev-tasks.md # 拆前端/后端多【开发】
│ ├── codeup.md # 分支 / MR / 关联
│ ├── commands.md # 口令面
│ └── acceptance.md
└── scripts/ # 可选极速 API
```
`SKILL.md` description 建议写明:触发词「接手开发 / 拆分开发 / 开始开发」;**Does NOT create 【分析】/【设计】**;入口条件需求=待开发。
---
## 11. 对照检查表(开发 Skill 评审用)
- [ ] 是否只认「需求编号 + 交付任务编号」,禁止标题查重
- [ ] 是否拒绝创建第二套【交付】或【分析】【设计】
- [ ] 占位交棒时是否提示风险且不假装 PRD 齐全
- [ ] 【开发】是否可编号幂等、可挂到交付树
- [ ] 是否与 YunxiaoPMapp **会话隔离**(不同 Skill、不同口令
- [ ] 计划开始字段是否遵守「已有值不覆盖」(若沿用同一字段)
- [ ] 提测 / 【测试】是否交给测试 Skill本包边界清晰
---
## 12. 相关文档索引
| 主题 | 路径(仓库内) |
|---|---|
| Skill 入口 | `skills/YunxiaoPMapp/SKILL.md` |
| 交付树模型 | `skills/YunxiaoPMapp/references/model.md` |
| 交棒契约 | `skills/YunxiaoPMapp/references/handoff-contract.md` |
| 标准路径 05 | `skills/YunxiaoPMapp/references/stage-flow.md` |
| 交棒门禁 / 回退 | `skills/YunxiaoPMapp/references/handoff-and-rollback.md` |
| 描述双段 | `skills/YunxiaoPMapp/references/description-split.md` |
| 编号区块 | `skills/YunxiaoPMapp/references/workitem-ids.md` |
| 快轨 / 编号直推 | `references/fast-track.md` · `number-push.md` |
| 工时算法 | `references/work-hours.md` |
| 实写 API | `references/live-api.md` |
安装产品 Skill
```bash
npx skills add 15810879921-coder/oneos-pm-skills --skill YunxiaoPMapp -a cursor -g -y
```

View File

@@ -0,0 +1,179 @@
# 产品部流转YunxiaoPMapp到交棒为止
> 用途:先把**产品部**在云效上的工作流转说清楚;开发 / 测试 / 发版不在本 Skill 内,仅在文末标出交接点。
> 依据:`references/stage-flow.md` · `model.md` · `fast-track.md` · `handoff-contract.md`
> 日期2026-07-24
---
## 1. 产品部管到哪里
```text
产品部YunxiaoPMapp终点 = 需求状态「待开发」+【交付】负责人「何斐」
之后 = 请技术经理使用开发 Skill不建【开发】/【测试】)
```
| 谁 | 做什么 | 不做什么 |
|---|---|---|
| 产品 / YunxiaoPMapp | 建需求、打标签、建【交付】【分析】【设计】、推进状态、设计完成灌 AutoPRD、交棒 | 建【开发】【测试】、开分支、提测、发版 |
| 技术经理(接手) | 从「待开发」起拆开发 | 不改写 AutoRDO不新建第二套【交付】 |
---
## 2. 总览流程图(标准路径)
```mermaid
flowchart TB
subgraph inputs [材料入口]
Chat[聊天/录音/口述]
AutoRDO["$AutoRDO 清洗"]
Proto[原型页 Make]
end
subgraph pm [产品部 · YunxiaoPMapp]
S0["0 创建需求\n状态=待处理\n只写 AutoRDO\n不建任务"]
S1["1 受理确认\n状态=已确认\n仍不建任务"]
S2["2 分析中\n建【交付】+【分析】"]
S3["3 设计中\n建【设计】\n收口【分析】"]
S4["4 设计完成\n收口【设计】\nAutoPRD+附件\n灌【交付】描述"]
S5["5 待开发交棒\n交付负责人→何斐\n★ 产品终点"]
end
subgraph after [产品之后 · 不在本 Skill]
Dev["开发 Skill\n拆【开发】…"]
Test["测试 Skill"]
Rel["发版"]
end
Chat --> AutoRDO --> S0
Proto -.-> S4
S0 --> S1 --> S2 --> S3 --> S4 --> S5
S5 -->|"交棒契约:需求编号+交付编号"| Dev
Dev --> Test --> Rel
```
---
## 3. 各步说明(产品侧)
| 步骤 | 需求状态 | 云效任务动作 | 描述写什么 | 口令示例 |
|---|---|---|---|---|
| 0 创建 | 待处理 | 无 | `## 原始诉求AutoRDO`;编号区块待建 | `记录需求:…;推进至=暂不推进` |
| 1 受理 | 已确认 | 仍无 | 不动 | `受理确认ONEOS-xx` |
| 2 分析中 | 分析中 | 新建【交付】ASSOCIATED→需求新建【分析】TASK_SUB→交付 | 交付=占位文案 | `开始分析ONEOS-xx` |
| 3 设计中 | 设计中 | 新建【设计】TASK_SUB→交付分析计划完成=当日+阶段日历工时 | — | `开始设计ONEOS-xx交付=…;分析=…` |
| 4 设计完成 | 设计完成 | 设计完成态;需求+交付挂 ZIP/截图;交付描述换 AutoPRD | `$oneos-autoprd``## 产品说明` | `设计完成ONEOS-xx设计=…;原型=…` |
| 5 交棒 | **待开发** | **只**把【交付】负责人改为何斐 | 若仍占位须标红风险 | `交棒开发ONEOS-xx交付=…` |
**编号权威:** 需求描述 `## 工作项编号(系统)`(交付 / 分析 / 设计)。后续口令优先带 `ONEOS-xx`,禁止按标题查重。
---
## 4. 交付树(产品建出来的结构)
```mermaid
flowchart TB
REQ["产品类需求 ONEOS-R\n状态=阶段真相"]
DEL["【交付】ONEOS-a\nASSOCIATED→需求"]
AN["【分析】ONEOS-b"]
DE["【设计】ONEOS-c"]
DEL -->|"关联项 ASSOCIATED"| REQ
AN -->|"子项 TASK_SUB"| DEL
DE -->|"子项 TASK_SUB"| DEL
```
验收口诀:
- 打开【交付】→「关联项」能看到需求
- 打开【交付】→「子项」能看到分析/设计(必须 `TASK_SUB`,不能只写 parentIdentifier
---
## 5. 两条旁路(仍交到同一终点)
```mermaid
flowchart LR
subgraph standard [标准]
A1[分析中] --> A2[设计中] --> A3[设计完成] --> A4[待开发]
end
subgraph fast [无单快轨]
B1[待处理/已确认等] --> B2["待开发\n建交付+设计当日收口\n不建分析"]
end
subgraph push [编号直推]
C1[已有分析/设计编号] --> C2[收口空计划完成] --> C3[待开发+交棒何斐]
end
```
| 路径 | 何时用 | 注意 |
|---|---|---|
| 标准 0→5 | 正常产品节奏 | 设计完成才灌 AutoPRD |
| 快轨 | 明确跳过分析、急交棒 | 默认可不跑 AutoPRD交付常占位→回报标红 |
| 编号直推 | 树上已有阶段任务编号 | 不新建冗余单;只认编号 |
---
## 6. 产品部人机边界Plan 门禁)
```text
凡写云效Plan 对齐 → 人确认 → 一口气 apply → 一次校验回报
```
| 适合全自动 | 建议人点一下 |
|---|---|
| 建单、打标、建树、改状态、交棒负责人、幂等复用 | 优先级、标签、是否快轨、设计是否真可开发、占位是否接受交棒 |
---
## 7. 交棒给下游时交出什么
产品回报至少包含:
```text
【YunxiaoPMapp】
风险:(占位交棒则首行标红)
需求ONEOS-R | 状态=待开发
交付ONEOS-a | 负责人=何斐
分析ONEOS-b 或 无
设计ONEOS-c 或 快轨占位说明
下一步:请技术经理使用开发 Skill
```
下游入口条件见 `references/handoff-contract.md`:认 **需求编号 + 交付任务编号**
---
## 8. 和全链路的关系(本文件边界)
```mermaid
flowchart LR
PM[产品部本文] --> Handoff[待开发交棒]
Handoff --> Dev[开发]
Dev --> QA[测试]
QA --> Rel[发版]
```
全链路(含谢佳伟 / 时生亮)见仓库原型:
`src/prototypes/yunxiao-pipeline-handbook/`
产品 Skill 对接开发说明:
`docs-YunxiaoPMapp-实现原理-开发Skill对接.md`
---
## 9. 相关 references
| 主题 | 路径 |
|---|---|
| 标准 05 | `references/stage-flow.md` |
| 交付树 / 子项 | `references/model.md` |
| 快轨 | `references/fast-track.md` |
| 编号直推 | `references/number-push.md` |
| 交棒门禁 | `references/handoff-and-rollback.md` |
| 交棒契约 | `references/handoff-contract.md` |
| 口令 | `references/commands.md` |
---
## 延伸阅读
- 四角色泳道(产品/开发/测试/发版):`docs-四角色泳道流程图.md`
- 开发侧草案:`docs-开发侧流转草案.md`

View File

@@ -0,0 +1,318 @@
# 全流程分步说明:产品 → 开发 → 测试 → 发版
> 把整条链路拆成**按顺序执行的步骤**,每步说清:谁做、做什么、云效上变成什么、下一步谁接。
> 读完应能照着口令/动作走完一轮(标准路径)。
> 日期2026-07-24
---
## 先记住三件事
1. **需求状态 = 阶段真相**
看需求状态就知道现在卡在哪一段(分析中 / 待开发 / 开发中 / 待测试…)。
2. **每条需求只有 1 个【交付】容器**
分析、设计、开发、测试都挂在这个交付下面(子项),不要再建第二个【交付】。
3. **编号说话,不靠标题查**
口令尽量带 `ONEOS-xx`;改标题不影响关联。
```text
需求(状态主轴)
└─【交付】(容器,关联到需求)
├─【分析】【设计】 ← 产品建
├─【开发】… ← 开发建
└─【测试】 ← 开发提测时建
【发版】另建,挂迭代 + 范围内需求
```
---
## 总步骤一览(共 18 步)
| 阶段 | 步骤 | 一句话 |
|---|---|---|
| **产品** | 16 | 从记诉求到交棒给何斐 |
| **开发** | 712 | 从拆任务到提测 |
| **测试** | 1315 | 从接测到测试完成 |
| **发版** | 1617 | 从建发版到发布结果 |
| **收口** | 18 | 产品验收关闭 |
---
## 阶段 A产品步骤 16
### 步骤 1记录需求
| | |
|---|---|
| **谁** | 产品 / AIYunxiaoPMapp |
| **做什么** | 把聊天、录音、口述先洗成 AutoRDO再建一条**产品类需求** |
| **需求状态** | **待处理** |
| **云效任务** | 不建任何任务 |
| **描述里写** | `## 原始诉求AutoRDO`;编号区先空着 |
| **口令例** | `记录需求:…;推进至=暂不推进` |
| **为什么** | 先落盘,避免口头需求丢;还没确认值不值得做 |
---
### 步骤 2受理确认
| | |
|---|---|
| **谁** | 产品 |
| **做什么** | 确认要做:定优先级、打标签(从云效标签里点选) |
| **需求状态** | **已确认** |
| **云效任务** | 仍不建任务 |
| **口令例** | `受理确认ONEOS-xx` |
| **为什么** | 和「还没想清楚」的待处理分开;确认后才进分析/设计 |
---
### 步骤 3开始分析
| | |
|---|---|
| **谁** | 产品 / AI |
| **做什么** | ① 建 **【交付】**(整条需求的唯一容器,关联到需求)② 建 **【分析】**(挂在交付**子项**下) |
| **需求状态** | **分析中** |
| **云效任务** | 【交付】+【分析】 |
| **口令例** | `开始分析ONEOS-xx` |
| **验收** | 打开【交付】→「关联项」有需求;「子项」有【分析】 |
| **为什么** | 分析要有落点;后续设计/开发/测试都挂同一棵树 |
---
### 步骤 4开始设计
| | |
|---|---|
| **谁** | 产品 / AI |
| **做什么** | 建 **【设计】**(子项挂交付);收口【分析】计划时间 |
| **需求状态** | **设计中** |
| **云效任务** | 新增【设计】 |
| **口令例** | `开始设计ONEOS-xx交付=…;分析=…` |
| **为什么** | 进入原型/方案设计;分析阶段收口 |
---
### 步骤 5设计完成
| | |
|---|---|
| **谁** | 产品 / AI |
| **做什么** | 收口【设计】;跑 AutoPRD把**产品说明**灌进【交付】描述;挂原型 ZIP/截图等附件 |
| **需求状态** | **设计完成** |
| **口令例** | `设计完成ONEOS-xx设计=…;原型=…` |
| **为什么** | 开发接手时看的是【交付】里的产品说明,不是聊天记录 |
---
### 步骤 6交棒开发产品终点
| | |
|---|---|
| **谁** | 产品 / AI |
| **做什么** | 需求改为待开发;**【交付】负责人改为何斐**(不新建开发/测试任务) |
| **需求状态** | **待开发** ★ |
| **交出什么** | 需求编号 +【交付】编号 |
| **口令例** | `交棒开发ONEOS-xx交付=…` |
| **为什么** | 产品部到此结束;技术经理从这里拆开发 |
> 旁路:急单可用**快轨**(跳过分析、直接待开发),仍交到同一终点「待开发 + 交付→何斐」。
---
## 阶段 B开发步骤 712
### 步骤 7分配开发任务
| | |
|---|---|
| **谁** | 开发主管何斐 / 开发 Skill |
| **做什么** | 输入**交付任务编号** → 自动建 **【开发】**;标题=`【开发】`+需求标题;**描述人工补**;指定开发人;自动写计划时间 |
| **关联** | 子项挂【交付】;关联项挂需求 |
| **需求状态** | 仍为 **待开发**(确认即可,一般不用再改) |
| **口令例** | `分配任务:交付=ONEOS-a开发人=张三` |
| **为什么** | 一条需求可拆多个开发任务;都挂在同一交付下 |
---
### 步骤 8开始开发
| | |
|---|---|
| **谁** | 开发人员 |
| **做什么** | 口令带上**开发任务编号** |
| **开发任务** | → **处理中** |
| **需求状态** | → **开发中** |
| **口令例** | `开始开发ONEOS-d` |
| **为什么** | 看板一眼能看出「正在写代码」 |
---
### 步骤 9写代码 / 提 MR
| | |
|---|---|
| **谁** | 开发人员 |
| **做什么** | 按【交付】里的产品说明实现;分支/MR 建议挂上开发任务编号与需求编号 |
| **需求状态** | 仍为 **开发中** |
| **为什么** | 代码可追溯到哪条开发任务、哪条需求 |
---
### 步骤 10AI 自测门禁(开发侧草案)
| | |
|---|---|
| **谁** | AI开发完成后触发 |
| **做什么** | 找与**需求同标题**的测试计划 → 按用例自测 → 不过则自动提缺陷(标题含开发任务编号)并尝试修复,直到本计划用例全过 |
| **需求状态** | 仍为 **开发中**(未全过前) |
| **为什么** | 在正式提测前先挡住明显问题(属草案,规则可再收紧) |
---
### 步骤 11开发任务完成
| | |
|---|---|
| **谁** | 系统 / AI用例全过之后 |
| **做什么** | 该条【开发】标为**已完成** |
| **需求状态** | → **开发完成**(若有多条开发,建议等**全部**完成再改,避免过早) |
| **为什么** | 标记「代码+门禁」这一段结束 |
---
### 步骤 12完成开发 · 正式提测
| | |
|---|---|
| **谁** | 开发人员(自测也完成) |
| **做什么** | 口令「完成开发」→ 自动建 **【测试】**(标题=`【测试】`+任务名);子项挂【交付】;建议再关联需求;指派测试(如谢佳伟) |
| **需求状态** | → **待测试** ★ |
| **口令例** | `完成开发ONEOS-d` |
| **为什么** | 开发交棒给测试;测试侧开始接单 |
---
## 阶段 C测试步骤 1315
### 步骤 13接测试任务
| | |
|---|---|
| **谁** | 测试(谢佳伟等) |
| **做什么** | 打开【测试】任务;确认关联的需求与交付;准备/核对测试计划与用例包(建议按**需求编号**分包,比「同标题」更稳) |
| **需求状态** | **待测试** → 开始执行后改为 **测试中** |
| **为什么** | 正式测试以计划用例为准,不靠口头「测过了」 |
---
### 步骤 14执行用例 · 缺陷回流
| | |
|---|---|
| **谁** | 测试执行;失败时回流开发修 |
| **做什么** | 按用例执行;失败建缺陷 → 开发修复 → 再测 |
| **需求状态** | **测试中** |
| **为什么** | 质量关口;未绿不能进发版 |
---
### 步骤 15测试完成
| | |
|---|---|
| **谁** | 测试 / AI 辅助判定 |
| **做什么** | **本需求**相关用例全绿 →【测试】收口;通知发版对接人 |
| **需求状态** | → **测试完成** ★ |
| **注意** | 只卡本需求,不卡同迭代里别的需求 |
| **为什么** | 发版范围以「测试完成」的需求为准 |
---
## 阶段 D发版步骤 1617
### 步骤 16建发版任务
| | |
|---|---|
| **谁** | 发版对接人(时生亮)· 手工或 AI |
| **做什么** | 建 **【发版】**;关联**迭代** + 本期内要上的需求(建议再挂交付/测试);汇总更新说明 |
| **需求状态** | 进入发布流程时 → **发布中** |
| **为什么** | 一次发版可能含多条需求;要有明确范围清单 |
---
### 步骤 17发布结果回写
| | |
|---|---|
| **谁** | 发版对接人 / 流水线 |
| **做什么** | 执行发布 |
| **结果** | 成功 → **发布完成**;失败 → **发布失败**(可重试再进发布中) |
| **为什么** | 成败要回写云效,避免「以为发了其实没发」 |
---
## 阶段 E收口步骤 18
### 步骤 18业务验收 · 关闭
| | |
|---|---|
| **谁** | 产品 |
| **做什么** | 业务验收通过后,关闭需求,并收口【交付】 |
| **需求状态** | → **已关闭** |
| **为什么** | 全链路结束;树上任务与需求一致收口 |
---
## 状态主链(串起来看)
```text
待处理 → 已确认 → 分析中 → 设计中 → 设计完成
→ 待开发 ← 产品交棒给何斐
→ 开发中 → 开发完成
→ 待测试 → 测试中 → 测试完成
→ 发布中 → 发布完成(或发布失败可重试)
→ 已关闭 ← 产品验收关单
```
---
## 四个交棒口(最重要)
| 交棒 | 交出人 | 接棒人 | 交出物 | 状态落点 |
|---|---|---|---|---|
| ① 产品→开发 | 产品 | 何斐 | 需求号 + 交付号 | 待开发 |
| ② 开发→测试 | 开发人 | 测试 | 【测试】任务已建好 | 待测试 |
| ③ 测试→发版 | 测试 | 发版 | 本需求用例全绿 | 测试完成 |
| ④ 发版→产品 | 发版 | 产品 | 发布完成 / 更新说明 | 发布完成 → 已关闭 |
---
## 谁在什么时候动(对照表)
| 步骤 | 产品 | 开发主管 | 开发人 | 测试 | 发版 |
|---|---|---|---|---|---|
| 12 记需求/确认 | ● | | | | |
| 35 分析设计 | ● | | | | |
| 6 交棒 | ● | 接 | | | |
| 7 分配任务 | | ● | | | |
| 89 开始写码 | | | ● | | |
| 1011 AI门禁/完成任务 | | | ●/AI | | |
| 12 提测 | | | ● | 接 | |
| 1315 测试 | | | 修缺陷 | ● | |
| 1617 发版 | | | | | ● |
| 18 关闭 | ● | | | | |
---
## 相关文档
| 文档 | 用途 |
|---|---|
| `docs-四角色泳道流程图.md` | 泳道图总览 |
| `docs-产品部流转流程图.md` | 产品 16 细规 |
| `docs-开发侧流转草案.md` | 开发 712 细规与待拍板 |
| `yunxiao-pipeline-handbook` | 云效规则与配置 |

View File

@@ -0,0 +1,181 @@
# 四角色泳道图:产品 · 开发 · 测试 · 发版
> 用途:一张图看清从建需求到发版关闭,四条泳道各自做什么、在哪交棒。
> 依据:产品部流转 · 开发侧草案 · 生产线手册(测试/发版)
> 日期2026-07-24
> 说明开发泳道含「AI 用例门禁」草案;测试泳道为正式提测后的人/计划执行。
---
## 1. 泳道总览(推荐主图)
```mermaid
flowchart TB
subgraph PM["泳道① 产品"]
direction TB
P0["建需求 · 待处理<br/>只写 AutoRDO"]
P1["受理确认 · 已确认"]
P2["分析中<br/>建【交付】+【分析】"]
P3["设计中<br/>建【设计】"]
P4["设计完成<br/>AutoPRD 灌交付"]
P5["交棒 · 待开发<br/>交付负责人→何斐"]
P6["业务验收后<br/>关闭需求+交付"]
P0 --> P1 --> P2 --> P3 --> P4 --> P5
end
subgraph DEV["泳道② 开发"]
direction TB
D1["何斐:分配任务<br/>建【开发】SUB→交付"]
D2["开发人:开始开发<br/>任务处理中 · 需求开发中"]
D3["写代码 / 提 MR"]
D4["AI 按同标题测试计划自测<br/>不过→提缺陷并修"]
D5["开发任务已完成<br/>需求→开发完成"]
D6["完成开发(含自测)<br/>建【测试】· 需求待测试"]
D1 --> D2 --> D3 --> D4 --> D5 --> D6
end
subgraph QA["泳道③ 测试"]
direction TB
T1["接【测试】任务<br/>需求=待测试"]
T2["建/挂测试计划与用例<br/>(建议按需求编号分包)"]
T3["测试中 · 执行用例"]
T4["缺陷回流开发修复"]
T5["本需求用例全绿<br/>需求→测试完成"]
T1 --> T2 --> T3
T3 -.->|失败| T4
T4 -.->|再测| T3
T3 -->|通过| T5
end
subgraph REL["泳道④ 发版"]
direction TB
R1["建【发版】任务<br/>挂迭代+范围内需求"]
R2["汇总更新说明"]
R3["发布中"]
R4{"发布结果"}
R5["发布完成"]
R6["发布失败 · 可重试"]
R1 --> R2 --> R3 --> R4
R4 -->|成功| R5
R4 -->|失败| R6
R6 -.-> R3
end
P5 -->|"交棒契约<br/>需求编号+交付编号"| D1
D6 -->|"提测<br/>【测试】已挂交付"| T1
T5 -->|"交棒发版"| R1
R5 -->|"业务可验收"| P6
```
---
## 2. 横向时间轴版(谁在哪一阶段动)
从左到右是需求状态主链;上下是四个角色。空格表示该角色此阶段无主动动作。
```mermaid
flowchart LR
subgraph S_PM["产品阶段"]
direction TB
sp0["待处理→已确认"]
sp1["分析/设计/设计完成"]
sp2["待开发交棒"]
sp3["已关闭"]
end
subgraph S_DEV["开发阶段"]
direction TB
sd0["拆【开发】"]
sd1["开发中"]
sd2["AI门禁→开发完成"]
sd3["建【测试】→待测试"]
end
subgraph S_QA["测试阶段"]
direction TB
sq0["待测试"]
sq1["测试中"]
sq2["测试完成"]
end
subgraph S_REL["发版阶段"]
direction TB
sr0["建【发版】"]
sr1["发布中"]
sr2["完成/失败"]
end
sp0 --> sp1 --> sp2
sp2 --> sd0 --> sd1 --> sd2 --> sd3
sd3 --> sq0 --> sq1 --> sq2
sq2 --> sr0 --> sr1 --> sr2
sr2 --> sp3
```
---
## 3. 交接点一览
| # | 从 → 到 | 交出什么 | 需求状态落点 |
|---|---|---|---|
| 1 | 产品 → 开发 | 需求编号 +【交付】编号;交付负责人=何斐 | **待开发** |
| 2 | 开发 → 测试 | 【测试】任务(子项挂交付);用例计划可先备好 | **待测试** |
| 3 | 测试 → 发版 | 本需求用例全绿;范围内需求清单 | **测试完成** |
| 4 | 发版 → 产品 | 发布完成证据 / 更新说明 | **发布完成** → 产品关单 **已关闭** |
---
## 4. 各泳道职责边界(一句话)
| 角色 | 管什么 | 不管什么 |
|---|---|---|
| **产品** | 建需求、【交付】【分析】【设计】、AutoPRD、交棒待开发、验收关闭 | 不建【开发】【测试】【发版】、不开分支 |
| **开发** | 拆【开发】、写码、AI 自测门禁、建【测试】提测 | 不改写产品 AutoRDO不建第二套【交付】 |
| **测试** | 接【测试】、跑计划用例、缺陷回流、判测试完成 | 不擅自改需求状态到开发中;不建【发版】(可催) |
| **发版** | 建【发版】、挂迭代与范围、发布与回写成败 | 不替代测试判绿;不关闭需求(交给产品) |
---
## 5. 云效工作项树(跨角色)
```mermaid
flowchart TB
REQ["需求 · 状态=阶段真相"]
DEL["【交付】ASSOCIATED→需求"]
AN["【分析】"]
DE["【设计】"]
DV["【开发】"]
TE["【测试】"]
RE["【发版】ASSOCIATED→迭代/需求"]
DEL --> REQ
AN -->|TASK_SUB| DEL
DE -->|TASK_SUB| DEL
DV -->|TASK_SUB| DEL
TE -->|TASK_SUB| DEL
DV -.->|ASSOCIATED| REQ
TE -.->|ASSOCIATED| REQ
RE -.->|关联范围| REQ
```
---
## 6. 典型负责人(手册约定,可按项目改)
| 泳道 | 典型对接人 |
|---|---|
| 产品 | 王冕 · YunxiaoPMapp / AI |
| 开发 | 何斐(拆任务)→ 王雨昊 / 李振等(执行) |
| 测试 | 谢佳伟 |
| 发版 | 时生亮 |
---
## 相关文档
| 文档 | 说明 |
|---|---|
| `docs-全流程分步说明.md` | **整条链路逐步说明(推荐先读)** |
| `docs-产品部流转流程图.md` | 产品 0→5 细图 |
| `docs-开发侧流转草案.md` | 开发 D1D5 细图 |
| `yunxiao-pipeline-handbook` | 全链路配置与规则 |

View File

@@ -0,0 +1,230 @@
# 开发侧流转草案(产品交棒之后)
> 来源产品经理口述规则整理2026-07-24
> 上游终点:产品部 `docs-产品部流转流程图.md` → 需求=**待开发**,【交付】负责人=**何斐**
> 本文件目标:把「何斐拆任务 → 开发执行 → AI 用例门禁 → 提测」画清,供后续 **YunxiaoDevapp** Skill 定稿
> 状态:**草案**(文末有待拍板项)
---
## 1. 总览流程图
```mermaid
flowchart TB
subgraph handoff [产品已交棒]
Ready["需求=待开发\n【交付】负责人=何斐"]
end
subgraph d1 [D1 分配开发]
Assign["何斐:分配任务 + 交付任务编号"]
CreateDev["自动建【开发】+需求标题\n描述人工补\n指定开发人\n写计划时间"]
Link["子项 TASK_SUB→交付\n关联项 ASSOCIATED→需求"]
StReady["需求保持/确认为 待开发"]
end
subgraph d2 [D2 开始开发]
Start["开发人:开始开发 + 开发任务编号"]
DevDoing["开发任务→处理中"]
ReqDoing["需求→开发中"]
end
subgraph d3 [D3 AI 用例门禁]
CodeDone["代码开发完成触发"]
FindPlan["按需求同标题找测试计划"]
AITest["AI 按用例自测"]
Fail["未通过→自动提缺陷\n标题含开发任务编号\nAI 写标题描述"]
Fix["自动修复→再测"]
PassGate["用例全部通过"]
end
subgraph d4 [D4 开发任务完成]
DevDone["该条【开发】→已完成"]
ReqDevDone["需求→开发完成"]
end
subgraph d5 [D5 完成开发·提测]
Finish["开发人:完成开发\n含自测完成"]
CreateTest["自动建【测试】+任务名\n子项→交付"]
PendingTest["需求→待测试"]
end
Ready --> Assign --> CreateDev --> Link --> StReady
StReady --> Start --> DevDoing --> ReqDoing
ReqDoing --> CodeDone --> FindPlan --> AITest
AITest -->|未通过| Fail --> Fix --> AITest
AITest -->|全通过| PassGate --> DevDone --> ReqDevDone
ReqDevDone --> Finish --> CreateTest --> PendingTest
```
---
## 2. 分步说明(按你的 5 条)
### D1何斐分配任务
| 项 | 规则 |
|---|---|
| 触发 | Skill 口令:`分配任务` + **交付任务编号** |
| 新建 | 【开发】任务;标题 = `【开发】` + **需求标题** |
| 描述 | **人工添加**Skill 不代写正文,或只留空模板) |
| 负责人 | 口令指定开发人员 |
| 计划时间 | **自动创建**计划开始/计划完成(算法待定:阶段日历工时 or 人力预估,见待拍板) |
| 关联 | **子项** `TASK_SUB` →【交付】;**关联项** `ASSOCIATED` → 需求 |
| 需求状态 | 改为 / 确认为 **待开发**(见待拍板:与产品交棒是否重复) |
### D2开始开发
| 项 | 规则 |
|---|---|
| 触发 | `开始开发` + **开发任务编号** |
| 开发任务 | → **处理中** |
| 需求 | → **开发中**(有 ≥1 条开发进入处理中即可,或本条触发即改,见待拍板) |
### D3代码完成后 · AI 按测试计划自测
| 项 | 规则 |
|---|---|
| 触发 | 「代码开发完成」MR 合并 / 口令 / Webhook触发源待定 |
| 找计划 | **自动寻找与需求同标题的测试计划** |
| 执行 | AI 按该计划中用例自行测试 |
| 失败 | 自动提缺陷:标题含 **开发任务编号** + AI 生成标题/描述;再自动修复,循环直到用例全过 |
### D4用例全通过
| 项 | 规则 |
|---|---|
| 该条【开发】 | → **已完成** |
| 需求 | → **开发完成** |
### D5开发人「完成开发」自测也完成
| 项 | 规则 |
|---|---|
| 触发 | `完成开发` +(建议带)开发任务编号 |
| 新建 | 【测试】任务;标题 = `【测试】` + 任务名称(建议=需求标题) |
| 关联 | 子项 →【交付】(建议同时 ASSOCIATED→需求 |
| 需求 | → **待测试** |
---
## 3. 与产品部的衔接
```mermaid
flowchart LR
PM["产品 YunxiaoPMapp\n待开发 + 交付→何斐"] --> DevSkill["开发 Skill 草案\n本文 D1D5"]
DevSkill --> QA["测试执行人/Skill\n待测试之后"]
```
| 上游已具备 | 开发侧依赖 |
|---|---|
| 需求编号 +【交付】编号 | D1 入口只认编号,不按标题拆第二套交付 |
| 交付 ASSOCIATED→需求 | D1 开发任务再 ASSOCIATED→需求、SUB→交付 |
| 产品不建【开发】【测试】 | 仅开发 Skill 建这两类 |
---
## 4. 待拍板(建议你先定这几条)
### 4.1 状态顺序是否自洽
你现在的顺序是:
```text
D3 AI 用例全过 → 开发任务已完成 + 需求「开发完成」
D5 完成开发 → 建【测试】+ 需求「待测试」
```
与现有手册常见顺序对比:
```text
手册常见:开发人完成自测 → 待测试 →(测试执行)→ 测试完成
你草案: AI 先跑测试计划用例过关 → 开发完成 → 人再点完成开发 → 待测试
```
需要确认:
1. D3 的「测试计划」是 **开发自测门禁**,正式【测试】任务仍留给谢佳伟?
2. 还是 D3 已等同正式测试,那 D5 再建【测试】是否重复?
### 4.2 「需求→待开发」写在 D1
产品交棒时需求**已经是待开发**。D1 再改一次通常多余。建议改为:
- D1 **校验**需求已是待开发;若不是则停下或只允许从设计完成快轨补交棒
- 有开发任务进入处理中时,需求才变为 **开发中**(即你的 D2
### 4.3 「与需求同标题的测试计划」
标题易改、易撞名。更稳的是:
- 测试计划关联 **需求编号 / 迭代**,或
- 用例包命名 `CP-{需求编号}-…`
否则同名需求/改标题会导致找错计划。
### 4.4 AI 自动提缺陷并自动修复
风险高:无上限循环、误报、改回旧逻辑。建议门禁:
- 最多 N 轮;失败转人工
- 缺陷必须关联 **开发任务编号 + 需求编号 + 用例 ID**
- 与「防回归」清单联动,禁止静默改无关模块
### 4.5 多条【开发】时需求状态
| 场景 | 建议 |
|---|---|
| 任一条开始开发 | 需求 → 开发中 |
| 需求 → 开发完成 | **全部**未取消【开发】均为已完成(与手册 Y21 一致) |
| 需求 → 待测试 | 全部【开发】完成后,由末位「完成开发」或系统自动建【测试】 |
你原文 D4 写「该条」通过就把需求改成开发完成——多开发人并行时会过早。建议改成「全员开发任务完成」。
### 4.6 关联写法(与产品侧一致)
同一 create 只能带一条 `createWorkitemRelationInfo`
- 优先保证【开发】/【测试】**子项挂在交付**(交付详情「子项」可见)
- ASSOCIATED→需求若同 create 互斥,需约定:先 SUB再补 ASSOCIATED或 OpenAPI 双挂
---
## 5. 建议口令面(草案)
```text
分配任务:交付任务=ONEOS-a开发人=张三,李四;计划开始=…;计划完成=…
开始开发:开发任务=ONEOS-d
代码完成:开发任务=ONEOS-d → 触发 AI 用例门禁(或 Webhook
完成开发:开发任务=ONEOS-d → 建【测试】;需求→待测试
```
---
## 6. 推荐定稿后的状态主链(供你勾选)
**方案 A贴近你原文AI 测作开发门禁)**
```text
待开发 → 开发中 →AI 用例门禁)→ 开发完成 → 待测试 → 测试中 → 测试完成 → …
```
**方案 B贴近现有生产线手册**
```text
待开发 → 开发中 → 开发完成(人自测+MR→ 待测试 → 测试中(人/AI 跑计划)→ 测试完成 → …
```
AI 跑测试计划放在 **待测试之后**,与【测试】任务负责人(如谢佳伟)对齐。
---
## 7. 下一步
1. 你拍板:**方案 A 或 B**,以及多【开发】时「开发完成 / 待测试」的聚合规则
2. 我按定稿输出 `YunxiaoDevapp``SKILL.md` 骨架 + 与产品交棒契约对齐段落
3. 再补一版「仅开发侧」验收清单10 条以内)
---
## 相关文档
| 文档 | 路径 |
|---|---|
| 产品部流转 | `docs-产品部流转流程图.md` |
| 产品↔开发契约 | `docs-YunxiaoPMapp-实现原理-开发Skill对接.md` |
| 全链路手册 | `src/prototypes/yunxiao-pipeline-handbook/` |

View File

@@ -0,0 +1,47 @@
# 无单快轨到待开发
适用:口令明确「快轨」或「推进至待开发」且当前需求尚无标准分析路径任务(或用户确认跳过分析)。
## 动作表
| 对象 | 动作 |
|---|---|
| 需求 | 状态 → **待开发****预计工时=2**、**实际工时=2**(覆盖同日 8h 日历工时默认);标签按口令;更新编号区块 |
| 【交付】 | 无则新建ASSOCIATED→需求勿用 PARENT负责人→何斐**计划开始=创建当日**`79`**不写**计划完成;**描述双路径**(见下);**标签与需求相同**;更新编号区块 |
| 【设计】 | **必须新建****TASK_SUB→交付**(交付「子项」须可见);**描述=复制需求当前描述正文**;计划开始/完成均=当日create 后 `field/value``79`+`80`);任务→完成态;**标签与需求相同**;建后再尝试 **ASSOCIATED→原始需求**Cookie 常失败,见 live-api失败须标红**子项优先于关联项**);更新编号区块 |
| 【分析】 | **禁止创建** |
## 交付描述双路径A1
| 口令/材料 | 【交付】描述 |
|---|---|
| **手工描述**(无指定原型) | 同步需求当前手工/AutoRDO 正文(与设计一致可复制 document |
| **指定原型页面** | 调用 `$oneos-autoprd`,从原型生成 AutoPRD「产品说明」写入【交付】 |
| 既无手工可同步正文、又无原型 | 才允许占位 `等待设计任务完成后自动填入`Plan 勾选交棒占位风险,回报首行标红 |
有手工或原型时**禁止**交棒占位。
## AutoPRD
- 快轨默认可不跑 AutoPRD**例外**:口令指定原型 → 交付走 AutoPRD 路径(上表)。
- 口令同时「设计完成 + 原型」时仍按步骤 4 灌需求产品说明段。
## 查重
只认任务编号。已有分析单不得因「快轨」被删除。
## 回报必含
- 需求 / 交付 / 设计编号
- 「快轨:未建分析;设计已同步需求描述并当日收口」
- 交付描述来源:手工同步 / AutoPRD / 占位(若占位则首行标红)
- 需求预计工时=2、实际工时=2
- 设计关联项含需求编号;交付子项含设计编号
## 与标准 / 编号直推对比
```text
标准:分析中→交付+分析 → 设计中→设计+收口分析 → 设计完成→收口设计 → 待开发交棒
快轨(无既有阶段单):→ 待开发:新建交付+设计+交棒何斐(无分析;设计当日收口;需求工时 2+2
编号直推:已有分析/设计编号 → 收口空计划完成 → 待开发+交付交棒(不新建冗余单)
```

View File

@@ -0,0 +1,242 @@
# 云效实写 APIYunxiaoPMapp 已验证)
`verified_at`: 2026-07-25 · **项目须门禁 PJ 点选**(见 [project-selection.md](project-selection.md));历史验证样本项目为 `01_ONEOS` / 原「统一运营管理平台」(`last_selected.spaceIdentifier``assets/runtime-ids.json`,禁止未点选即使用)。
本文件只记**已跑通**的写法;禁止再盲试 `updateStatus` / 错误 `updateFieldValue` POST。
## 认证
- CookieChrome 域 `.aliyun.com` / `devops.aliyun.com``browser_cookie3` 或 Playwright storage
- Header`x-xsrf-token` = cookie `XSRF-TOKEN`URL 解码后)
- `Origin` / `Referer``https://devops.aliyun.com`
## 建单
`POST|PUT /projex/api/workitem/workitem?_input_charset=utf-8`
创建响应 `result.identifier` / `serialNumber` 即编号真相;**禁止按标题查重**。
## 改负责人(已通)
```http
PATCH /projex/api/workitem/workitem/{id}?_input_charset=utf-8
{"propertyKey":"assignedTo","propertyValue":"<userId>","operateType":"COVER"}
```
交棒:【交付】`propertyValue` = 何斐 ID。
## 打标签(已通)
```http
PATCH /projex/api/workitem/workitem/{id}?_input_charset=utf-8
{"workitemIdentifier":"{id}","propertyKey":"tag","propertyValue":"<tagId>[,<tagId>]","operateType":"COVER"}
```
## 改状态(已通 · 唯一推荐)
```http
POST /projex/api/workitem/workitem/{id}/status/transit?_input_charset=utf-8
{"fromStatus":"<status.identifier>","toStatus":"<status.identifier>"}
```
成功:`code=200``result=true`。失败时 `errorMsg` 含「不能流转」。
### 需求状态 ID本项目
| 显示名 | identifier |
|---|---|
| 待处理 | `100005` |
| 已确认 | `32` |
| 分析中 | `154395` |
| 设计中 | `156603` |
| 设计完成 | `307012` |
| 待开发 | `1582fc929d429111b925309493` |
### 任务状态 ID
| 显示名 | identifier |
|---|---|
| 待处理 | `100005` |
| 已完成 | `100014` |
### 极速交棒跳转(工作流允许)
从「待处理」菜单可见直达「设计完成」;推荐最少跳:
```text
待处理 → 设计完成 → 待开发
```
标准路径若需看板留痕,可走完整链:已确认→分析中→设计中→设计完成→待开发(仍用本 API勿开 UI
### 禁止(已证伪)
| 写法 | 结果 |
|---|---|
| `PATCH …/updateStatus` + `statusIdentifier` | `400 不能为空` |
| `PATCH …/{id}` + `propertyKey=status` | `property not found` |
| Playwright 点左侧/列表上的状态色块(`x<1100` | 假成功、状态不落库 |
仅当 `status/transit` 不可用时,才用 UI右侧详情状态钮`getBoundingClientRect().x > 1100`+ `.next-menu-item`
## 计划开始/完成 · 提交部门/人 · 预计工时2026-07-27 修订)
**通用字段写入(已通):**
```http
POST /projex/api/workitem/workitem/field/value/{workitemId}?_input_charset=utf-8
Content-Type: application/x-www-form-urlencoded
fieldValueList=[{"fieldIdentifier":"79","value":"2026-07-27 12:00:00"},{"fieldIdentifier":"3132597a9718d1c282b7ba5a0c","value":""},{"fieldIdentifier":"9e01269e96f91fbb97d36bf5b3","value":""}]
```
| 字段 | fieldIdentifier | value |
|---|---|---|
| 计划开始 | `79` | `YYYY-MM-DD HH:mm:ss`(推荐正午)或 epoch ms 字符串 |
| 计划完成 | `80` | 同上 |
| 提交部门 | `3132597a9718d1c282b7ba5a0c` | 纯文本 |
| 提交人 | `9e01269e96f91fbb97d36bf5b3` | 纯文本 |
**预计工时 `101586`:禁止直接改字段**(报「不可直接修改」)。须登记:
```http
POST /projex/api/workitem/workitem/time/estimate?_input_charset=utf-8
{"workitemIdentifier":"<id>","spentTime":8,"type":"develop","description":"","recordUserIdentifier":"<userId>","forCreate":false,"containsRestDay":false}
```
删除多余预估:`DELETE /projex/api/workitem/workitem/time/estimate/{workitemId}/{estimateId}`
列表:`GET …/time/estimate/list?workitemIdentifier=`
旧写法 `PATCH …/updateWorkitemFieldValue` 对上述自定义字段常 `400 不能为空`,勿再优先使用。
## 父子 / 子项 / 关联项(已通 · 2026-07-23 修订 · 子项优先)
### 关联项(【交付】强制 · ASSOCIATED
任务详情「关联项」只认 `ASSOCIATED`。**仅【交付】**建单时 `createWorkitemRelationInfo` 必须指向**需求**
```json
{
"createWorkitemRelationInfo": {
"relatedWorkitemIdentifier": "<需求id>",
"relatedToRelationIdentifier": "ASSOCIATED"
}
}
```
校验:
```http
GET /projex/api/workitem/v2/workitem/{id}/relation/workitem/list/by-relation-category?category=ASSOCIATED&isForward=true
```
`result` 含该需求即通过。
### 禁止(关联项)
| 写法 | 结果 |
|---|---|
| `relatedToRelationIdentifier=PARENT` 把交付挂需求 | 详情可能有 parent**关联项仍为空** |
| 分析/设计只用 `ASSOCIATED→需求` + `parentIdentifier` | 关联项可能有,**交付子项仍为空**ONEOS-246/247 |
| 建后再 `POST …/relation/record` 补关系 | Cookie 路径下常报「不能关联相同的工作项」 |
| `createWorkitemRelationList` | 不落 ASSOCIATED |
### 子项(【分析】/【设计】强制 · TASK_SUB
「子项」页读 `PARENT_SUB` / `TASK_SUB`,分析/设计**必须**
```json
{
"parent": "<交付id>",
"parentIdentifier": "<交付id>",
"createWorkitemRelationInfo": {
"relatedWorkitemIdentifier": "<交付id>",
"relatedToRelationIdentifier": "TASK_SUB"
}
}
```
同一 create 只能带一条 `createWorkitemRelationInfo`
`ASSOCIATED→需求``TASK_SUB→交付` **不能同时写**
**产品优先级交付「子项」tab > 阶段任务「关联项」。**
交付本身仍必须 `ASSOCIATED→需求`。标准路径下分析/设计的「关联项」允许为空。
**无单快轨例外(设计双挂):** create 用 `TASK_SUB→交付` 后,须再补 **ASSOCIATED→原始需求**,使设计详情「关联项」可见需求。
```http
POST /projex/api/workitem/workitem/{id}/relation/record?_input_charset=utf-8
{"relationIdentifier":"ASSOCIATED","toWorkitemIdentifier":"<id>"}
```
**已证伪Cookie · 2026-07-27** 凡工作项**已创建**后再 `relation/record` 补挂(含 ASSOCIATED / TASK_SUB常报「不能关联相同的工作项」与是否已有父项无关。`createWorkitemRelationList` 亦不落 ASSOCIATED。
**可行路径:**
| 目标 | 做法 |
|---|---|
| 交付「子项」可见设计(优先) | create 带 `TASK_SUB→交付` |
| 设计「关联项」可见需求 | create 带 `ASSOCIATED→需求`(与上互斥,同 create 只能一条) |
| 双挂 | 需个人 `x-yunxiao-token` OpenAPICookie 路径**不得**声称成功 |
产品默认:**子项优先**;关联项失败须在回报中标红并列出缺项。
校验子项:
```http
GET /projex/api/workitem/v2/workitem/{id}/relation/workitem/list/by-relation-category?category=PARENT_SUB&isForward=true
```
结果须含对应分析/设计 identifier。
校验设计关联项:
```http
GET /projex/api/workitem/v2/workitem/{id}/relation/workitem/list/by-relation-category?category=ASSOCIATED&isForward=true
```
`result` 须含原始需求 identifier。
### 无单快轨字段默认2026-07-27
| 对象 | 规则 |
|---|---|
| 【设计】描述 | 复制需求 document HTML |
| 【设计】`79`/`80` | 当日 `12:00:00` / `23:59:59`create 后 `field/value`(勿 create 同时带 79+80 |
| 【交付】描述 | 手工同步需求正文或原型→AutoPRD禁止无故占位 |
| 【交付】`79` | 创建当日;不写 `80` |
| 【交付】/【设计】标签 | 与需求相同,`PATCH propertyKey=tag` |
| 需求预计工时 | `time/estimate` **spentTime=2**(先删多余预估) |
| 需求实际工时 | `POST …/workitem/time`body 用 **`actualTime`**(非 spentTime+ `gmtStart`/`gmtEnd` epoch ms 字符串;见 `runtime-ids.json` `fields.actual_hours` |
| 描述更新 | `PATCH …/workitem/{id}/document``{"content":"<html>","formatType":"RICHTEXT"}` |
## 迭代挂接(已通 · 2026-07-27 · 只挂交付)
创建迭代:`POST /projex/api/workspace/sprint`(必填 `staffIds`;可写 `capacityHours`)。
挂【交付】到迭代:
```http
PATCH /projex/api/workitem/workitem/{id}?_input_charset=utf-8
{"workitemIdentifier":"{id}","propertyKey":"sprint","propertyValue":"{sprintId}","operateType":"COVER"}
```
清空误挂(如需求):`propertyValue:""` + `operateType:"COVER"`
**校验**必须读 `/extra`(详情主接口常不含 sprint 字段,禁止据此判失败):
```http
GET /projex/api/workitem/workitem/{id}/extra?_input_charset=utf-8
result.sprint[].identifier / name
```
产品规则:**只挂【交付】**;需求 / 分析 / 设计默认不挂(除非口令显式)。
### 极速建单注意
1. Cookie 只刷一次;全程纯 HTTP默认**不开浏览器**。
2. 交付建完后,【分析】与【设计】**并行**创建(均 TASK_SUB→交付标准/快轨两树可并行。
3. 状态用 `transit` + **本地追踪 fromStatus**(禁止每次 GET负责人在交棒场景下**创建时即何斐**。
4. 建单 `fieldValueList` 可带计划开始 `79`**不要**在 create 同时写 `79+80`(同日会 400
5. 标签必须 PATCHcreate 带 tag 不落库);可与建子任务重叠;快轨交付/设计须与需求同标签。
6. `requests.Session` keep-alive**禁止**对共享 opener 加全局锁。
7. 脚本入口:`scripts/live_create_fast.py`v5快轨描述/计划/标签/工时 2+2/设计 ASSOCIATED 补挂)。

View File

@@ -0,0 +1,660 @@
#!/usr/bin/env python3
"""YunxiaoPM 极速真实建单 v5快轨描述/计划/标签/工时 2+2/设计 ASSOCIATED 补挂。"""
from __future__ import annotations
import json
import time
import urllib.parse
from concurrent.futures import ThreadPoolExecutor, as_completed
from datetime import datetime, timedelta, timezone
from pathlib import Path
from typing import Any
try:
import browser_cookie3
except ImportError: # pragma: no cover
browser_cookie3 = None
import requests
ROOT = Path(__file__).resolve().parents[1]
RUNTIME = json.loads((ROOT / "assets" / "runtime-ids.json").read_text())
STATUS = RUNTIME["status"]["req"]
TASK_STATUS = RUNTIME["status"]["task"]
FAST = RUNTIME.get("fields", {}).get("fast_track") or {}
SPACE = (
RUNTIME.get("project", {}).get("spaceIdentifier")
or (RUNTIME.get("project", {}).get("last_selected") or {}).get("spaceIdentifier")
)
if not SPACE:
raise RuntimeError(
"未选定项目 spaceIdentifier须先走门禁 PJ 点选,或设置 runtime project.last_selected"
)
REQ_TYPE = RUNTIME["workitem_types"]["product_req"]["identifier"]
TASK_TYPE = RUNTIME["workitem_types"]["task"]["identifier"]
HEFEI = RUNTIME["people"]["hefei"]["identifier"]
WANG = RUNTIME["people"].get("wangmian", {}).get("identifier", "6811df000601d2fea60144a9")
PRI = RUNTIME["priority"][""]
TAG_FAULT = RUNTIME.get("tags", {}).get("故障管理", "ceb526a7343995577645317e9a")
PLACEHOLDER = RUNTIME["delivery_placeholder"]
PROTO = "https://prototype.lnoneos.com/vehicle-fault-handling/index.html"
TZ = timezone(timedelta(hours=8))
TODAY = datetime.now(TZ).strftime("%Y-%m-%d")
NOON = f"{TODAY} 12:00:00"
EOD = f"{TODAY} 23:59:59"
NOON_MS = str(
int(datetime.now(TZ).replace(hour=12, minute=0, second=0, microsecond=0).timestamp() * 1000)
)
START_MS = str(
int(datetime.now(TZ).replace(hour=9, minute=0, second=0, microsecond=0).timestamp() * 1000)
)
END_MS = str(
int(datetime.now(TZ).replace(hour=11, minute=0, second=0, microsecond=0).timestamp() * 1000)
)
FAST_EST = int(FAST.get("req_estimated_hours", 2))
FAST_ACT = int(FAST.get("req_actual_hours", 2))
PENDING = STATUS["待处理"]
DESIGN_DONE = STATUS["设计完成"]
PENDING_DEV = STATUS["待开发"]
TASK_DONE = TASK_STATUS["已完成"]
_COOKIE = ""
_XSRF = ""
def load_auth() -> None:
global _COOKIE, _XSRF
jar: dict[str, str] = {}
if browser_cookie3:
for domain in (".aliyun.com", "devops.aliyun.com", ".devops.aliyun.com"):
try:
for c in browser_cookie3.chrome(domain_name=domain):
jar[c.name] = c.value
except Exception:
pass
if not jar:
p = Path("/tmp/yunxiao_cookies.json")
if p.exists():
raw = json.loads(p.read_text())
jar = (
raw
if isinstance(raw, dict) and "XSRF-TOKEN" in raw
else {c["name"]: c["value"] for c in raw.get("cookies", [])}
)
_COOKIE = "; ".join(f"{k}={v}" for k, v in jar.items())
x = jar.get("XSRF-TOKEN", "")
_XSRF = urllib.parse.unquote(x) if "%" in x else x
if not _XSRF:
raise RuntimeError("缺少 XSRF-TOKEN请先在 Chrome 登录 devops.aliyun.com")
def session() -> requests.Session:
s = requests.Session()
s.headers.update(
{
"Content-Type": "application/json",
"Cookie": _COOKIE,
"x-xsrf-token": _XSRF,
"X-XSRF-TOKEN": _XSRF,
"Origin": "https://devops.aliyun.com",
"Referer": f"https://devops.aliyun.com/projex/project/{SPACE}/req",
"accept": "application/json",
"User-Agent": "YunxiaoPM-live_create_fast/5.0",
"Connection": "keep-alive",
}
)
return s
def api(s: requests.Session, method: str, url: str, body: Any = None) -> dict:
r = s.request(method, url, json=body, timeout=60)
try:
return r.json()
except Exception:
r.raise_for_status()
raise
def create(s: requests.Session, payload: dict) -> dict:
url = "https://devops.aliyun.com/projex/api/workitem/workitem?_input_charset=utf-8"
j = api(s, "POST", url, payload)
r = j.get("result") or {}
if j.get("code") == 200 and isinstance(r, dict) and r.get("identifier"):
return r
j = api(s, "PUT", url, payload)
r = j.get("result") or {}
if j.get("code") == 200 and isinstance(r, dict) and r.get("identifier"):
return r
raise RuntimeError(f"create failed: {j}")
def get(s: requests.Session, wid: str) -> dict:
return api(
s,
"GET",
f"https://devops.aliyun.com/projex/api/workitem/workitem/{wid}?_input_charset=utf-8",
)["result"]
def apply_tag(s: requests.Session, wid: str, tag_id: str = TAG_FAULT) -> None:
j = api(
s,
"PATCH",
f"https://devops.aliyun.com/projex/api/workitem/workitem/{wid}?_input_charset=utf-8",
{
"workitemIdentifier": wid,
"propertyKey": "tag",
"propertyValue": tag_id,
"operateType": "COVER",
},
)
if j.get("code") != 200:
raise RuntimeError(f"tag failed {wid}: {j}")
def set_document(s: requests.Session, wid: str, html: str) -> None:
j = api(
s,
"PATCH",
f"https://devops.aliyun.com/projex/api/workitem/workitem/{wid}/document?_input_charset=utf-8",
{"content": html, "formatType": "RICHTEXT"},
)
if j.get("code") != 200 or j.get("errorMsg"):
raise RuntimeError(f"document failed {wid}: {j}")
def set_fields(s: requests.Session, wid: str, pairs: list[tuple[str, str]]) -> None:
data = urllib.parse.urlencode(
{
"fieldValueList": json.dumps(
[{"fieldIdentifier": k, "value": v} for k, v in pairs], ensure_ascii=False
)
}
)
r = s.post(
f"https://devops.aliyun.com/projex/api/workitem/workitem/field/value/{wid}?_input_charset=utf-8",
data=data,
headers={"Content-Type": "application/x-www-form-urlencoded"},
timeout=60,
)
j = r.json()
if j.get("code") != 200:
raise RuntimeError(f"field/value failed {wid}: {j}")
def set_estimate_hours(s: requests.Session, wid: str, hours: int, user: str = WANG) -> None:
est = api(
s,
"GET",
f"https://devops.aliyun.com/projex/api/workitem/workitem/time/estimate/list?workitemIdentifier={wid}",
).get("result") or []
for row in est:
eid = row.get("identifier")
if eid:
api(
s,
"DELETE",
f"https://devops.aliyun.com/projex/api/workitem/workitem/time/estimate/{wid}/{eid}",
)
j = api(
s,
"POST",
"https://devops.aliyun.com/projex/api/workitem/workitem/time/estimate?_input_charset=utf-8",
{
"workitemIdentifier": wid,
"spentTime": hours,
"type": "develop",
"description": "快轨默认预计工时",
"recordUserIdentifier": user,
"forCreate": False,
"containsRestDay": False,
},
)
if j.get("code") != 200:
raise RuntimeError(f"estimate failed {wid}: {j}")
def set_actual_hours(s: requests.Session, wid: str, hours: int, user: str = WANG) -> None:
j = api(
s,
"POST",
"https://devops.aliyun.com/projex/api/workitem/workitem/time?_input_charset=utf-8",
{
"workitemIdentifier": wid,
"actualTime": hours,
"type": "develop",
"description": "快轨默认实际工时",
"recordUserIdentifier": user,
"gmtStart": START_MS,
"gmtEnd": END_MS,
},
)
if j.get("code") != 200 or not j.get("result"):
raise RuntimeError(f"actual time failed {wid}: {j}")
def try_associate_to_req(s: requests.Session, stage_id: str, req_id: str) -> bool:
"""建后补 ASSOCIATED→需求。Cookie 下常失败,成功返回 True。"""
bodies = [
{"relationIdentifier": "ASSOCIATED", "toWorkitemIdentifier": req_id},
{
"relationIdentifier": "ASSOCIATED",
"fromWorkitemIdentifier": stage_id,
"toWorkitemIdentifier": req_id,
},
]
for body in bodies:
for url in (
f"https://devops.aliyun.com/projex/api/workitem/workitem/{stage_id}/relation/record?_input_charset=utf-8",
f"https://devops.aliyun.com/projex/api/workitem/v2/workitem/{stage_id}/relation/record?_input_charset=utf-8",
):
j = api(s, "POST", url, body)
if j.get("code") == 200 and j.get("result") not in (None, False):
if not (isinstance(j.get("result"), dict) and j["result"].get("status") in (404, 405)):
rows = list_associated(s, stage_id)
if req_id in {r.get("identifier") for r in rows}:
return True
return False
def transit(s: requests.Session, wid: str, from_status: str, to_status: str) -> None:
if from_status == to_status:
return
j = api(
s,
"POST",
f"https://devops.aliyun.com/projex/api/workitem/workitem/{wid}/status/transit?_input_charset=utf-8",
{"fromStatus": from_status, "toStatus": to_status},
)
if not (j.get("code") == 200 and j.get("result") is True):
raise RuntimeError(f"transit {wid} {from_status}->{to_status}: {j}")
def md_to_html(md: str) -> str:
parts = []
for line in md.splitlines():
if line.startswith("## "):
parts.append(f"<h2>{line[3:]}</h2>")
elif line.startswith("### "):
parts.append(f"<h3>{line[4:]}</h3>")
elif line.startswith("- "):
parts.append(f"<p>• {line[2:]}</p>")
elif line.strip():
parts.append(f"<p>{line}</p>")
return "".join(parts)
def req_document_html(s: requests.Session, rid: str) -> str:
w = get(s, rid)
return ((w.get("document") or {}).get("content") or w.get("description") or "").strip()
def req_payload(subject: str, html: str) -> dict:
return {
"subject": subject,
"description": html,
"formatType": "RICHTEXT",
"document": {"content": html, "formatType": "RICHTEXT"},
"spaceIdentifier": SPACE,
"space": SPACE,
"spaceType": "Project",
"workitemTypeIdentifier": REQ_TYPE,
"workitemType": REQ_TYPE,
"categoryIdentifier": "Req",
"category": "Req",
"assignedTo": WANG,
"fieldValueList": [
{"fieldIdentifier": "priority", "value": PRI},
{"fieldIdentifier": "assignedTo", "value": WANG},
],
"attachmentIdList": [],
"cloneFrom": None,
"createWorkitemRelationList": [],
}
def task_payload(
subject: str,
html: str,
assignee: str,
*,
plan_start: bool = True,
associated_req: str | None = None,
parent_delivery: str | None = None,
) -> dict:
fvl = [
{"fieldIdentifier": "priority", "value": PRI},
{"fieldIdentifier": "assignedTo", "value": assignee},
]
if plan_start:
fvl.append({"fieldIdentifier": "79", "value": NOON_MS})
payload: dict[str, Any] = {
"subject": subject,
"description": html,
"formatType": "RICHTEXT",
"spaceIdentifier": SPACE,
"space": SPACE,
"spaceType": "Project",
"workitemTypeIdentifier": TASK_TYPE,
"workitemType": TASK_TYPE,
"categoryIdentifier": "Task",
"category": "Task",
"assignedTo": assignee,
"fieldValueList": fvl,
"attachmentIdList": [],
"cloneFrom": None,
}
if parent_delivery:
payload["parent"] = parent_delivery
payload["parentIdentifier"] = parent_delivery
payload["createWorkitemRelationInfo"] = {
"relatedWorkitemIdentifier": parent_delivery,
"relatedToRelationIdentifier": "TASK_SUB",
}
else:
if not associated_req:
raise ValueError("associated_req required for delivery: ASSOCIATED→需求")
payload["createWorkitemRelationInfo"] = {
"relatedWorkitemIdentifier": associated_req,
"relatedToRelationIdentifier": "ASSOCIATED",
}
return payload
def list_associated(s: requests.Session, wid: str) -> list[dict]:
j = api(
s,
"GET",
f"https://devops.aliyun.com/projex/api/workitem/v2/workitem/{wid}/relation/workitem/list/by-relation-category?category=ASSOCIATED&isForward=true",
)
return j.get("result") or []
def assert_associated_to_req(s: requests.Session, wid: str, req_id: str, label: str) -> None:
rows = list_associated(s, wid)
ids = {r.get("identifier") for r in rows}
if req_id not in ids:
raise RuntimeError(
f"{label} 关联项未挂需求:期望 {req_id},实际 {[r.get('serialNumber') for r in rows]}"
)
AUTO_RDO = """## 原始诉求AutoRDO
运维需在故障处置页承接机器人上报的故障,完成处置、挂起与归档,并保留证据链;工作台相关统计口径需与处置页一致
待确认:
- 本期是否含真实短信/邮件通道(现口径一般为演示模板)
## 工作项编号(系统)
- 交付:待建
- 分析:待建
- 设计:待建
"""
def summarize_from_create(w: dict, *, status: str, assignee_name: str) -> dict:
return {
"serial": w.get("serialNumber"),
"id": w.get("identifier"),
"subject": w.get("subject"),
"status": status,
"assignee": assignee_name,
"parent": w.get("parentIdentifier"),
}
def build_normal() -> dict:
t0 = time.perf_counter()
s = session()
title = "【新增】故障处置YunxiaoPMapp标准·极速v2"
req = create(s, req_payload(title, md_to_html(AUTO_RDO + f"\n原型:{PROTO}\n")))
rid = req["identifier"]
with ThreadPoolExecutor(max_workers=2) as pool:
f_tag_r = pool.submit(apply_tag, session(), rid)
f_deliv = pool.submit(
create,
session(),
task_payload(
f"【交付】{title}",
f"<p>{PLACEHOLDER}</p>",
HEFEI,
associated_req=rid,
),
)
deliv = f_deliv.result()
f_tag_r.result()
did = deliv["identifier"]
with ThreadPoolExecutor(max_workers=3) as pool:
f_tag_d = pool.submit(apply_tag, session(), did)
f_ana = pool.submit(
create,
session(),
task_payload(
f"【分析】{title}",
"<p>分析阶段:故障处置台账、挂起归档与证据链。</p>",
WANG,
associated_req=rid,
parent_delivery=did,
),
)
f_des = pool.submit(
create,
session(),
task_payload(
f"【设计】{title}",
f"<p>设计阶段:对齐原型 {PROTO}</p>",
WANG,
associated_req=rid,
parent_delivery=did,
),
)
ana = f_ana.result()
des = f_des.result()
f_tag_d.result()
with ThreadPoolExecutor(max_workers=3) as pool:
list(
as_completed(
[
pool.submit(transit, session(), rid, PENDING, DESIGN_DONE),
pool.submit(transit, session(), ana["identifier"], PENDING, TASK_DONE),
pool.submit(transit, session(), des["identifier"], PENDING, TASK_DONE),
]
)
)
transit(s, rid, DESIGN_DONE, PENDING_DEV)
return {
"path": "normal",
"elapsed_s": round(time.perf_counter() - t0, 3),
"req": summarize_from_create(req, status="待开发", assignee_name="王冕"),
"delivery": summarize_from_create(deliv, status="待处理", assignee_name="何斐"),
"analysis": summarize_from_create(ana, status="已完成", assignee_name="王冕"),
"design": summarize_from_create(des, status="已完成", assignee_name="王冕"),
}
def build_fast(
*,
tag_id: str = TAG_FAULT,
has_prototype: bool = True,
delivery_html: str | None = None,
) -> dict:
"""无单快轨。
- 设计描述 = 需求 document
- 交付描述 = 手工同步需求正文(无原型)或传入 AutoPRD HTML禁止无故占位
- 设计 79/80=当日;交付 79=当日
- 需求/交付/设计同标签
- 需求预计/实际工时各 2
- 设计 TASK_SUB→交付后尝试 ASSOCIATED→需求
"""
t0 = time.perf_counter()
s = session()
title = "【新增】故障处置YunxiaoPM快轨·极速v5"
req_html = md_to_html(AUTO_RDO + (f"\n原型:{PROTO}\n" if has_prototype else "\n"))
req = create(s, req_payload(title, req_html))
rid = req["identifier"]
# 以落库 document 为准(与手动建需后读需求一致)
req_html = req_document_html(s, rid) or req_html
if delivery_html:
deliv_html = delivery_html
desc_source = "autoprd"
elif req_html.strip():
deliv_html = req_html
desc_source = "manual_sync"
else:
deliv_html = f"<p>{PLACEHOLDER}</p>"
desc_source = "placeholder"
with ThreadPoolExecutor(max_workers=2) as pool:
f_tag_r = pool.submit(apply_tag, session(), rid, tag_id)
f_deliv = pool.submit(
create,
session(),
task_payload(
f"【交付】{title}",
deliv_html,
HEFEI,
associated_req=rid,
),
)
deliv = f_deliv.result()
f_tag_r.result()
did = deliv["identifier"]
with ThreadPoolExecutor(max_workers=2) as pool:
f_tag_d = pool.submit(apply_tag, session(), did, tag_id)
f_des = pool.submit(
create,
session(),
task_payload(
f"【设计】{title}",
req_html,
WANG,
parent_delivery=did,
),
)
des = f_des.result()
f_tag_d.result()
des_id = des["identifier"]
apply_tag(s, des_id, tag_id)
# 计划时间设计起止当日交付开始当日create 已带 79再 field/value 加固)
set_fields(s, des_id, [("79", NOON), ("80", EOD)])
set_fields(s, did, [("79", NOON)])
# 设计关联项补挂需求(可能失败,回报 risk
design_assoc_ok = try_associate_to_req(s, des_id, rid)
with ThreadPoolExecutor(max_workers=2) as pool:
list(
as_completed(
[
pool.submit(transit, session(), rid, PENDING, DESIGN_DONE),
pool.submit(transit, session(), des_id, PENDING, TASK_DONE),
]
)
)
transit(s, rid, DESIGN_DONE, PENDING_DEV)
set_estimate_hours(s, rid, FAST_EST)
set_actual_hours(s, rid, FAST_ACT)
risk = None
if desc_source == "placeholder":
risk = "交付描述仍为占位"
if not design_assoc_ok:
risk = (risk + "" if risk else "") + "设计 ASSOCIATED→需求补挂失败Cookie须 UI/OpenAPI 兜底"
return {
"path": "fast",
"elapsed_s": round(time.perf_counter() - t0, 3),
"req": summarize_from_create(req, status="待开发", assignee_name="王冕"),
"delivery": summarize_from_create(deliv, status="待处理", assignee_name="何斐"),
"design": summarize_from_create(des, status="已完成", assignee_name="王冕"),
"analysis": None,
"delivery_desc_source": desc_source,
"design_associated_ok": design_assoc_ok,
"risk": risk,
}
def main() -> None:
auth0 = time.perf_counter()
load_auth()
auth_s = round(time.perf_counter() - auth0, 3)
wall0 = time.perf_counter()
with ThreadPoolExecutor(max_workers=2) as pool:
f_fast = pool.submit(build_fast)
f_normal = pool.submit(build_normal)
fast = f_fast.result()
normal = f_normal.result()
build_s = round(time.perf_counter() - wall0, 3)
s = session()
assert_associated_to_req(s, normal["delivery"]["id"], normal["req"]["id"], "normal.delivery")
assert_associated_to_req(s, fast["delivery"]["id"], fast["req"]["id"], "fast.delivery")
def assert_sub(delivery_id: str, child_id: str, label: str) -> None:
rows = api(
s,
"GET",
f"https://devops.aliyun.com/projex/api/workitem/v2/workitem/{delivery_id}/relation/workitem/list/by-relation-category?category=PARENT_SUB&isForward=true",
).get("result") or []
ids = {r.get("identifier") for r in rows}
if child_id not in ids:
raise RuntimeError(
f"{label} 未出现在交付子项:期望 {child_id},实际 {[r.get('serialNumber') for r in rows]}"
)
assert_sub(normal["delivery"]["id"], normal["analysis"]["id"], "normal.analysis")
assert_sub(normal["delivery"]["id"], normal["design"]["id"], "normal.design")
assert_sub(fast["delivery"]["id"], fast["design"]["id"], "fast.design")
verify = {
"normal_req": get(s, normal["req"]["id"])["status"]["displayName"],
"fast_req": get(s, fast["req"]["id"])["status"]["displayName"],
"normal_delivery_assignee": (
get(s, normal["delivery"]["id"]).get("assignedTo") or {}
).get("displayName"),
"fast_delivery_assignee": (get(s, fast["delivery"]["id"]).get("assignedTo") or {}).get(
"displayName"
),
"delivery_associated_ok": True,
"stage_tasks_as_sub_ok": True,
"fast_design_associated_ok": fast.get("design_associated_ok"),
}
out = {
"normal": normal,
"fast": fast,
"verify": verify,
"auth_elapsed_s": auth_s,
"wall_elapsed_s": build_s,
"created_at": datetime.now(TZ).isoformat(),
"mode": "live_create_fast_v5_fast_track_rules",
"opts": {
"create_includes_plan_start": True,
"skip_plan_end_on_create": True,
"tracked_transit_no_get": True,
"delivery_assignee_hefei_at_create": True,
"overlap_tag_with_create": True,
"fast_req_hours": f"{FAST_EST}+{FAST_ACT}",
"relation": "delivery ASSOCIATED→req; analysis/design TASK_SUB→delivery; design post ASSOCIATED→req",
"http": "requests.Session keep-alive",
},
}
Path("/tmp/yunxiao_pmapp_fast_v2_result.json").write_text(
json.dumps(out, ensure_ascii=False, indent=2)
)
print(json.dumps(out, ensure_ascii=False, indent=2))
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,60 @@
# 交付树模型与关联约定
## 真相源
```text
需求状态 = 阶段看板唯一真相(分析中/设计中/待开发…)
【交付】任务 = 该需求的交付容器(每需求最多 1 条)
【分析】/【设计】 = YunxiaoPMapp 在交付下建的阶段子项
【开发】/【测试】 = 另属开发 Skill / 测试 Skill不进本包
ASSOCIATED = 横向挂钩(【交付】 ↔ 需求)
SUB / TASK_SUB = 纵向拆解(交付 → 分析/设计)
```
## 关系验收
| 关系 | 用在哪里 | 验收 | 优先级 |
|---|---|---|---|
| ASSOCIATED | **仅【交付】** ↔ 需求 | 交付详情「关联项」能看到需求(**强制** | 交付必过 |
| TASK_SUB | 【分析】/【设计】 → 【交付】 | 交付详情「子项」能看到阶段任务(**强制** | 阶段任务必过 |
建单规则Cookie 路径 · 同一 create 只能一条 `createWorkitemRelationInfo`
| 对象 | `createWorkitemRelationInfo` | 另写字段 |
|---|---|---|
| 【交付】 | `ASSOCIATED` → 需求 | — |
| 【分析】/【设计】 | `TASK_SUB` → 交付 | `parent` + `parentIdentifier` = 交付 |
**禁止**对分析/设计只写 `parentIdentifier` + `ASSOCIATED→需求`关联项可能有但交付「子项」仍为空ONEOS-246/247 已复现)。
勿用 `PARENT` 冒充关联项。细则见 [live-api.md](live-api.md)。
## 禁止
| 禁止 | 说明 |
|---|---|
| 创建或描述【开发】/【测试】 | 口令与回报均不出现 |
| 分析/设计未挂成交付子项(无 TASK_SUB | 交付「子项」为 0交棒验收失败 |
| 用任务名称/标题做唯一性或查重 | 不得 `subject` 匹配复用 |
| 同一需求认定多个交付任务编号 | 列出编号请人合并后再继续 |
| 功能模块标签用「分析/设计/交付」 | 模块标签打在需求(可选交付)上 |
## 任务标题(仅展示)
- 【交付】+ 需求标题
- 【分析】+ 需求标题
- 【设计】+ 需求标题
标题可改,**不参与查重**。
## 任务编号唯一性
**唯一允许的查重/复用渠道:云效任务编号**(如 `ONEOS-99` / `serialNumber`)。
| 场景 | 正确 | 错误 |
|---|---|---|
| 首次创建【交付】 | 建单成功后回报并写入「工作项编号(系统)」 | 下次用标题搜 |
| 复用【交付】 | 口令或编号区块带 `交付任务=ONEOS-xx` | list 后按 subject 相等 |
| 判断是否已有交付 | 编号区块或交付 ASSOCIATED 编号集合 | 数【交付】开头标题 |
| 分析/设计幂等 | 仅已登记编号 | 按【分析】+需求标题 |
按编号命中则复用;**计划开始已有值禁止改写**。

View File

@@ -0,0 +1,49 @@
# 验收清单与回报
## apply 后必须自检
| # | 项 | 通过标准 |
|---|---|---|
| 1 | 需求编号 | 回报含 ONEOS-xx |
| 2 | 任务编号 | 交付/分析/设计凡新建或操作均回报编号;禁止只报标题 |
| 3 | 编号区块 | 需求「工作项编号(系统)」与实际一致 |
| 4 | ASSOCIATED | **仅交付**详情关联项可见需求(`createWorkitemRelationInfo=ASSOCIATED`;禁止 PARENT 冒充) |
| 5 | SUB | **必过**:分析/设计 create 用 `TASK_SUB→交付`(含 `parent`+`parentIdentifier`交付「子项」tab 须可见。与 ASSOCIATED 同 create 互斥,阶段任务关联项可空(见 live-api.md |
| 6 | 计划开始 | 未误覆盖已有值 |
| 7 | 阶段日历工时 | 有计划完成时已写入;脚注存在;回报用语正确 |
| 8 | 交棒 | 需求=待开发;交付负责人=何斐(交棒场景) |
| 9 | 占位风险 | 交付仍占位时首行标红 |
| 10 | 负向 | 本轮**无**【开发】/【测试】任务;未按标题查重 |
设计完成额外AutoPRD 段已写交付非占位除非失败停下ZIP+截图已挂或已列出缺项。
迭代额外:只挂【交付】(需求不挂);版本号符合递增规则。
## 回报模板(精简)
```text
【YunxiaoPM】
风险:(若有占位交棒则首行标红)
需求ONEOS-xx | 状态=…
交付ONEOS-a | 负责人=…
分析ONEOS-b | …(无则写无)
设计ONEOS-c | …(无则写无)
阶段日历工时:分析 Hh / 设计 Hh若本轮写入
附件:…(若本轮)
迭代:…(若本轮)
下一步:请技术经理使用开发 Skill交棒后
```
## 适合全自动 vs 人工门禁
| 适合全自动 | 建议半自动/人工门禁 |
|---|---|
| 建单、打标签、挂迭代、写描述、建交付树、改状态、交棒负责人、幂等查重 | **PJ 云效项目点选**、受理(已确认)、是否快轨、设计完成是否真可开发、跨需求优先级与迭代容量、回退与取消 |
## 实写性能2026-07-23 复盘)
| 项 | 要求 |
|---|---|
| 改状态 | 只用 `status/transit`(见 [live-api.md](live-api.md) |
| 改【交付】负责人 | 只用 `PATCH …/{id}` + `propertyKey=assignedTo` |
| 极速复测 | `scripts/live_create_fast.py`;默认不开浏览器 |

View File

@@ -0,0 +1,22 @@
# 口令面
```text
记录需求:…;项目=必选·Plan 点选);优先级=紧急|高|中|低;标签=…;提交部门=…;提交人=…;推进至=暂不推进|已确认|分析中|设计中|设计完成|待开发|待开发(快轨)
受理确认ONEOS-xx
开始分析ONEOS-xx → 【交付】+【分析】并回报编号
开始设计ONEOS-xx交付任务=…;分析任务=… → 【设计】+收口分析
设计完成ONEOS-xx设计任务=…;原型=…
交棒开发ONEOS-xx交付任务=… → 待开发 + 该编号负责人=何斐
快轨待开发ONEOS-xx → 待开发 +【交付】+【设计】(无【分析】)+ 交付负责人=何斐
编号直推:分析任务=ONEOS-b / 设计任务=ONEOS-c → 收口未完成计划完成 + 需求待开发 + 交付交棒何斐
创建迭代:版本类型=主|副|子;交付任务=ONEOS-a,ONEOS-b,…;名称前缀=…
AutoRDO粘贴聊天/附录音)→ 再记录需求
```
版本自动规则:取同前缀下最大 `Vx.y.z`(旧 `Vx.y` 视为 `Vx.y.0`)再按主/副/子递增;迭代名=`{前缀}{新版本}`
**PJ 项目**:新建需求/迭代前须点选云效项目(实时列表);禁止默认直指。见 [project-selection.md](project-selection.md)。
后续推进口令**优先显式带任务编号**;未带则读「工作项编号(系统)」;仍无则询问;**禁止按标题补全**。
YunxiaoPM 回报止于交棒;可一句「请技术经理使用开发 Skill」。

View File

@@ -0,0 +1,95 @@
# 压缩点选(`1a2b3a4d`
记录需求 Plan **默认**用编号题 + 字母选项;用户可用一行压缩答复确认。
## Plan 展示模板
```text
请回复压缩点选1a2b3a4d
(数字=题号,字母=选项;大小写不敏感;可写 1A2B3A4D
1. 类型
A. 新增
B. 优化
2. 项目(云效实时列表;建议项可标★)
A. 01_ONEOSONEOS
B. 02_小羚羚APPXLLAPP
C. …
3. 优先级
A. 紧急
B. 高
C. 中
D. 低
4. 标签(云效候选;建议项可标★)
A. 故障管理★
B. 还车应结款
C. …
```
可选续题(口令已齐则可写入清单、压缩串可不含):
```text
5. 推进至 …
6. 迭代 …
```
## 解析规则
| 规则 | 说明 |
|---|---|
| 形态 | `(题号)(字母)` 连续拼接,如 `1a2b3a4d` |
| 题号 | `1`=类型 `2`=项目 `3`=优先级 `4`=标签;可扩展 `5` `6` |
| 字母 | `a`→第 1 项 … `z`→第 26 项;超出选项数 → 非法,停 |
| 缺题 | 该题若口令已唯一预填且列表唯一命中,可用预填;否则停并追问缺题 |
| 多答同题 | 后写覆盖先写 |
| 非法字符 | 停,重贴模板 |
解析成功后 Plan 回显人话确认一行,例如:
```text
已解析 1a2b3a4d → 类型=新增;项目=02_小羚羚APP优先级=紧急;标签=D 项名)
确认后回复「执行」
```
用户再回「执行」才 apply仍守 Plan 门禁)。
## 与口令预填
口令已写 `类型新增项目01_ONEOS优先级标签故障管理` 时:
- 对应选项标 ★,并给出**建议压缩串**(如 `1a2a3b4a`),用户可直接改字母或整段重答。
- **不得**因有预填而跳过展示字母表;压缩确认(或逐题点选)仍是门禁。
## 标签未命中 → 自动重拉一次候选并重生选项
「标签无法对应」:口令标签名在**当前标签候选**中 0 命中(或多命中无法唯一)。
| 步骤 | 动作 |
|---|---|
| 1 | **自动重拉一次**标签候选(见下「标签候选来源」;强制刷新,不用旧缓存) |
| 2 | 用新列表**重新生成 4.A/B/C…** 选择项 |
| 3 | 回报:`已自动重拉标签列表(因无法对应)`;请用户重答 `4x` 或整串 |
| 4 | 仍无法对应 → 停;**禁止**第 3 次空转;**禁止**猜 tagId |
> 说明:此处重拉的是**标签候选列表**,不是项目列表。项目无法对应仍走 [project-selection.md](project-selection.md) 的「自动重拉一次」。
### 标签候选来源(当前已验证路径)
1. `runtime-ids.json``tags`
2. 目标项目(或预填项目)下近期工作项 `tag` 字段聚合去重
3. 重拉 = 再请求工作项列表聚合 + 合并 runtime命中后可回写 `tags` 缓存
(专用 `tag/list` Cookie API 尚未稳定;有稳定端点后改写入 `live-api.md` 并切换。)
## 项目列表顺序
生成 2. 选项时:口令预填/建议项目置 **A** 并标 ★,其余按云效返回顺序接 B/C/…。
## Agent 义务
1. 记录需求进 Plan 时必须输出本模板(至少 14 题)。
2. 收到压缩串先解析回显,再等「执行」。
3. 标签/项目无法对应:各自动重拉**一次**并刷新对应题选项。

View File

@@ -0,0 +1,69 @@
# 需求描述 vs 交付描述
两类描述职责不同;禁止混写;禁止建【交付】时把 AutoPRD 六大块提前塞进交付描述。
## A. 需求描述 · AutoRDO 清洗
| 项 | 规则 |
|---|---|
| 触发 | 对话建需求 / 碎片材料入库 |
| 调用 | **必须**使用独立 Skill「**`$AutoRDO`**」(`AutoRDO/SKILL.md`;本 Skill 不内嵌清洗细则) |
| 输入 | 聊天记录、录音、口述材料 |
| 处理 | 保留原意;书面化;去口头禅;**去除结尾句号**(细则在 AutoRDO `references/rules.md` |
| 输出 | 写入 `## 原始诉求AutoRDO` |
| 不做 | 本阶段不写 AutoPRD 六大块;不要求已有原型;不覆盖已有「产品说明」 |
口令:`AutoRDO…` → 确认后 `记录需求:【新增】标题;描述=整理稿;推进至=…`
## B. 交付描述
### B1. 标准路径(分析中起建交付)
| 时机 | 【交付】描述 |
|---|---|
| 首次创建起至设计完成前 | 固定文案:`等待设计任务完成后自动填入` |
| 设计完成时 | 用 AutoPRD「产品说明」正文替换占位 |
### B2. 无单快轨建交付(覆盖 B1
| 口令/材料 | 【交付】描述 |
|---|---|
| 手工描述(无指定原型) | **同步需求**当前手工/AutoRDO 正文;禁止占位 |
| 指定原型页面 | `$oneos-autoprd` 从原型生成写入;禁止占位 |
| 既无正文又无原型 | 才允许占位并标红风险 |
快轨【设计】描述始终复制需求当前描述正文(见 [fast-track.md](fast-track.md))。
## C. 需求描述双段模板(不可互相覆盖)
```markdown
## 原始诉求AutoRDO
(清洗稿;设计完成也不删除)
## 产品说明AutoPRD
(六大块+对象存储链接;未设计完成前可无此节或写「待设计完成后填入」)
## 工作项编号(系统)
- 交付:…
- 分析:…
- 设计:…
```
## D. 设计完成 · AutoPRD + 附件
前提:设计任务完成且已关联对应原型页。
1. 调用 **`$oneos-autoprd`AutoPRD**,产出并落盘 `.spec/requirements-prd.md` + 标注同步:
- 对象存储预览链接:`{baseUrl}/{prototype-id}/index.html`(禁止加 `prototypes/` 前缀、禁止去掉 `index.html`
- 产品说明 Markdown总览/角色/流程/状态/风险/交付等,见 AutoPRD 模板)
2. 写入需求 `## 产品说明AutoPRD`**禁止覆盖** `## 原始诉求AutoRDO` / `## 工作项编号(系统)`
3. 【交付】描述:按**交付任务编号**用产品说明正文**替换**占位(细则见 AutoPRD `references/yunxiao-delivery-sync.md`);可附「原始诉求见需求描述」。**创建【交付】时不得提前灌 MD。**
4. 附件(需求 +【交付】均挂;失败则不得声称成功):
- Make「导出 HTML含源码」ZIP → [make-export-attach.md](make-export-attach.md)
- Make「复制截图」全交互页 → 同上
缺原型 / AutoPRD 失败 / 导出或截图失败 → **不得**报到设计完成并宣称附件齐全;停下并列出缺项。
执行顺序:先 AutoPRD 落盘与附件就绪 → 再改需求/交付描述与设计计划完成 → 最后改需求状态。
**禁止**加载 `yunxiao-requirement-lifecycle`;阶段任务树只由本 SkillYunxiaoPMapp创建。

View File

@@ -0,0 +1,47 @@
# 无单快轨到待开发
适用:口令明确「快轨」或「推进至待开发」且当前需求尚无标准分析路径任务(或用户确认跳过分析)。
## 动作表
| 对象 | 动作 |
|---|---|
| 需求 | 状态 → **待开发****预计工时=2**、**实际工时=2**(覆盖同日 8h 日历工时默认);标签按口令;更新编号区块 |
| 【交付】 | 无则新建ASSOCIATED→需求勿用 PARENT负责人→何斐**计划开始=创建当日**`79`**不写**计划完成;**描述双路径**(见下);**标签与需求相同**;更新编号区块 |
| 【设计】 | **必须新建****TASK_SUB→交付**(交付「子项」须可见);**描述=复制需求当前描述正文**;计划开始/完成均=当日create 后 `field/value``79`+`80`);任务→完成态;**标签与需求相同**;建后再尝试 **ASSOCIATED→原始需求**Cookie 常失败,见 live-api失败须标红**子项优先于关联项**);更新编号区块 |
| 【分析】 | **禁止创建** |
## 交付描述双路径A1
| 口令/材料 | 【交付】描述 |
|---|---|
| **手工描述**(无指定原型) | 同步需求当前手工/AutoRDO 正文(与设计一致可复制 document |
| **指定原型页面** | 调用 `$oneos-autoprd`,从原型生成 AutoPRD「产品说明」写入【交付】 |
| 既无手工可同步正文、又无原型 | 才允许占位 `等待设计任务完成后自动填入`Plan 勾选交棒占位风险,回报首行标红 |
有手工或原型时**禁止**交棒占位。
## AutoPRD
- 快轨默认可不跑 AutoPRD**例外**:口令指定原型 → 交付走 AutoPRD 路径(上表)。
- 口令同时「设计完成 + 原型」时仍按步骤 4 灌需求产品说明段。
## 查重
只认任务编号。已有分析单不得因「快轨」被删除。
## 回报必含
- 需求 / 交付 / 设计编号
- 「快轨:未建分析;设计已同步需求描述并当日收口」
- 交付描述来源:手工同步 / AutoPRD / 占位(若占位则首行标红)
- 需求预计工时=2、实际工时=2
- 设计关联项含需求编号;交付子项含设计编号
## 与标准 / 编号直推对比
```text
标准:分析中→交付+分析 → 设计中→设计+收口分析 → 设计完成→收口设计 → 待开发交棒
快轨(无既有阶段单):→ 待开发:新建交付+设计+交棒何斐(无分析;设计当日收口;需求工时 2+2
编号直推:已有分析/设计编号 → 收口空计划完成 → 待开发+交付交棒(不新建冗余单)
```

View File

@@ -0,0 +1,20 @@
# 交棒门禁与回退最小集
## 交棒门禁(待开发)
| 情形 | 规则 |
|---|---|
| 【交付】描述已是 AutoPRD 正式说明(非占位) | 允许交棒Plan 正常列交付任务编号 + 负责人→何斐 |
| 【交付】描述仍为 `等待设计任务完成后自动填入` | **仍允许交棒**,但 Plan **必须**勾选风险项「交付描述仍为占位,技术侧仅可凭需求 AutoRDO 稿理解」;回报**首行标红**该风险;**禁止**静默交棒假装材料齐全 |
| 口令同时带原型且要求设计完成 | 先走步骤 4AutoPRD+附件)成功,再交棒,不再勾占位风险 |
## 回退 / 变更(最小集 · 兼容计划开始不篡改)
| 场景 | 规则 |
|---|---|
| 待开发 → 退回设计中 | 需求状态回退;【交付】负责人可改回创建人/产品;**交付计划开始不改**;若需重做设计 → **新开**设计任务编号(旧设计保持已收口,不改其计划开始);更新「工作项编号(系统)」中的设计编号为新号 |
| 设计完成后需求大变 | 不自动改状态Plan 询问是否回退设计中并新开设计编号;更新 AutoPRD 段AutoRDO 段保留并追加「变更纪要」 |
| 取消需求 | 关联任务标取消/废止;不删编号区块;不改已写计划开始 |
| 度量含义 | 交付计划开始保留 = 全周期仍从首次开工起算;回退重做会拉长日历工时——回报注明「含回退重做」 |
凡写云效的回退仍须走 Plan 门禁。

View File

@@ -0,0 +1,14 @@
# 交接契约(开发 Skill 入口)
YunxiaoPMapp 与开发 Skill **不要**互相 include 全文;仅认下列契约。
```text
PM 完成交棒 → 需求=待开发;【交付】任务编号=ONEOS-xx负责人=何斐ASSOCIATED 需求
若交付描述仍为占位 → 回报已标红风险
开发 Skill 入口 → 认「需求编号 + 交付任务编号」
占位时只可信需求「原始诉求AutoRDO」并有权要求产品补设计完成
```
共享常量(项目 ID、何斐 ID、节假日日历可引用本 Skill 的 `assets/` 短路径,勿加载整份对方规则。
测试 Skill 另开;本契约不覆盖提测/缺陷。

View File

@@ -0,0 +1,242 @@
# 云效实写 APIYunxiaoPMapp 已验证)
`verified_at`: 2026-07-25 · **项目须门禁 PJ 点选**(见 [project-selection.md](project-selection.md));历史验证样本项目为 `01_ONEOS` / 原「统一运营管理平台」(`last_selected.spaceIdentifier``assets/runtime-ids.json`,禁止未点选即使用)。
本文件只记**已跑通**的写法;禁止再盲试 `updateStatus` / 错误 `updateFieldValue` POST。
## 认证
- CookieChrome 域 `.aliyun.com` / `devops.aliyun.com``browser_cookie3` 或 Playwright storage
- Header`x-xsrf-token` = cookie `XSRF-TOKEN`URL 解码后)
- `Origin` / `Referer``https://devops.aliyun.com`
## 建单
`POST|PUT /projex/api/workitem/workitem?_input_charset=utf-8`
创建响应 `result.identifier` / `serialNumber` 即编号真相;**禁止按标题查重**。
## 改负责人(已通)
```http
PATCH /projex/api/workitem/workitem/{id}?_input_charset=utf-8
{"propertyKey":"assignedTo","propertyValue":"<userId>","operateType":"COVER"}
```
交棒:【交付】`propertyValue` = 何斐 ID。
## 打标签(已通)
```http
PATCH /projex/api/workitem/workitem/{id}?_input_charset=utf-8
{"workitemIdentifier":"{id}","propertyKey":"tag","propertyValue":"<tagId>[,<tagId>]","operateType":"COVER"}
```
## 改状态(已通 · 唯一推荐)
```http
POST /projex/api/workitem/workitem/{id}/status/transit?_input_charset=utf-8
{"fromStatus":"<status.identifier>","toStatus":"<status.identifier>"}
```
成功:`code=200``result=true`。失败时 `errorMsg` 含「不能流转」。
### 需求状态 ID本项目
| 显示名 | identifier |
|---|---|
| 待处理 | `100005` |
| 已确认 | `32` |
| 分析中 | `154395` |
| 设计中 | `156603` |
| 设计完成 | `307012` |
| 待开发 | `1582fc929d429111b925309493` |
### 任务状态 ID
| 显示名 | identifier |
|---|---|
| 待处理 | `100005` |
| 已完成 | `100014` |
### 极速交棒跳转(工作流允许)
从「待处理」菜单可见直达「设计完成」;推荐最少跳:
```text
待处理 → 设计完成 → 待开发
```
标准路径若需看板留痕,可走完整链:已确认→分析中→设计中→设计完成→待开发(仍用本 API勿开 UI
### 禁止(已证伪)
| 写法 | 结果 |
|---|---|
| `PATCH …/updateStatus` + `statusIdentifier` | `400 不能为空` |
| `PATCH …/{id}` + `propertyKey=status` | `property not found` |
| Playwright 点左侧/列表上的状态色块(`x<1100` | 假成功、状态不落库 |
仅当 `status/transit` 不可用时,才用 UI右侧详情状态钮`getBoundingClientRect().x > 1100`+ `.next-menu-item`
## 计划开始/完成 · 提交部门/人 · 预计工时2026-07-27 修订)
**通用字段写入(已通):**
```http
POST /projex/api/workitem/workitem/field/value/{workitemId}?_input_charset=utf-8
Content-Type: application/x-www-form-urlencoded
fieldValueList=[{"fieldIdentifier":"79","value":"2026-07-27 12:00:00"},{"fieldIdentifier":"3132597a9718d1c282b7ba5a0c","value":""},{"fieldIdentifier":"9e01269e96f91fbb97d36bf5b3","value":""}]
```
| 字段 | fieldIdentifier | value |
|---|---|---|
| 计划开始 | `79` | `YYYY-MM-DD HH:mm:ss`(推荐正午)或 epoch ms 字符串 |
| 计划完成 | `80` | 同上 |
| 提交部门 | `3132597a9718d1c282b7ba5a0c` | 纯文本 |
| 提交人 | `9e01269e96f91fbb97d36bf5b3` | 纯文本 |
**预计工时 `101586`:禁止直接改字段**(报「不可直接修改」)。须登记:
```http
POST /projex/api/workitem/workitem/time/estimate?_input_charset=utf-8
{"workitemIdentifier":"<id>","spentTime":8,"type":"develop","description":"","recordUserIdentifier":"<userId>","forCreate":false,"containsRestDay":false}
```
删除多余预估:`DELETE /projex/api/workitem/workitem/time/estimate/{workitemId}/{estimateId}`
列表:`GET …/time/estimate/list?workitemIdentifier=`
旧写法 `PATCH …/updateWorkitemFieldValue` 对上述自定义字段常 `400 不能为空`,勿再优先使用。
## 父子 / 子项 / 关联项(已通 · 2026-07-23 修订 · 子项优先)
### 关联项(【交付】强制 · ASSOCIATED
任务详情「关联项」只认 `ASSOCIATED`。**仅【交付】**建单时 `createWorkitemRelationInfo` 必须指向**需求**
```json
{
"createWorkitemRelationInfo": {
"relatedWorkitemIdentifier": "<需求id>",
"relatedToRelationIdentifier": "ASSOCIATED"
}
}
```
校验:
```http
GET /projex/api/workitem/v2/workitem/{id}/relation/workitem/list/by-relation-category?category=ASSOCIATED&isForward=true
```
`result` 含该需求即通过。
### 禁止(关联项)
| 写法 | 结果 |
|---|---|
| `relatedToRelationIdentifier=PARENT` 把交付挂需求 | 详情可能有 parent**关联项仍为空** |
| 分析/设计只用 `ASSOCIATED→需求` + `parentIdentifier` | 关联项可能有,**交付子项仍为空**ONEOS-246/247 |
| 建后再 `POST …/relation/record` 补关系 | Cookie 路径下常报「不能关联相同的工作项」 |
| `createWorkitemRelationList` | 不落 ASSOCIATED |
### 子项(【分析】/【设计】强制 · TASK_SUB
「子项」页读 `PARENT_SUB` / `TASK_SUB`,分析/设计**必须**
```json
{
"parent": "<交付id>",
"parentIdentifier": "<交付id>",
"createWorkitemRelationInfo": {
"relatedWorkitemIdentifier": "<交付id>",
"relatedToRelationIdentifier": "TASK_SUB"
}
}
```
同一 create 只能带一条 `createWorkitemRelationInfo`
`ASSOCIATED→需求``TASK_SUB→交付` **不能同时写**
**产品优先级交付「子项」tab > 阶段任务「关联项」。**
交付本身仍必须 `ASSOCIATED→需求`。标准路径下分析/设计的「关联项」允许为空。
**无单快轨例外(设计双挂):** create 用 `TASK_SUB→交付` 后,须再补 **ASSOCIATED→原始需求**,使设计详情「关联项」可见需求。
```http
POST /projex/api/workitem/workitem/{id}/relation/record?_input_charset=utf-8
{"relationIdentifier":"ASSOCIATED","toWorkitemIdentifier":"<id>"}
```
**已证伪Cookie · 2026-07-27** 凡工作项**已创建**后再 `relation/record` 补挂(含 ASSOCIATED / TASK_SUB常报「不能关联相同的工作项」与是否已有父项无关。`createWorkitemRelationList` 亦不落 ASSOCIATED。
**可行路径:**
| 目标 | 做法 |
|---|---|
| 交付「子项」可见设计(优先) | create 带 `TASK_SUB→交付` |
| 设计「关联项」可见需求 | create 带 `ASSOCIATED→需求`(与上互斥,同 create 只能一条) |
| 双挂 | 需个人 `x-yunxiao-token` OpenAPICookie 路径**不得**声称成功 |
产品默认:**子项优先**;关联项失败须在回报中标红并列出缺项。
校验子项:
```http
GET /projex/api/workitem/v2/workitem/{id}/relation/workitem/list/by-relation-category?category=PARENT_SUB&isForward=true
```
结果须含对应分析/设计 identifier。
校验设计关联项:
```http
GET /projex/api/workitem/v2/workitem/{id}/relation/workitem/list/by-relation-category?category=ASSOCIATED&isForward=true
```
`result` 须含原始需求 identifier。
### 无单快轨字段默认2026-07-27
| 对象 | 规则 |
|---|---|
| 【设计】描述 | 复制需求 document HTML |
| 【设计】`79`/`80` | 当日 `12:00:00` / `23:59:59`create 后 `field/value`(勿 create 同时带 79+80 |
| 【交付】描述 | 手工同步需求正文或原型→AutoPRD禁止无故占位 |
| 【交付】`79` | 创建当日;不写 `80` |
| 【交付】/【设计】标签 | 与需求相同,`PATCH propertyKey=tag` |
| 需求预计工时 | `time/estimate` **spentTime=2**(先删多余预估) |
| 需求实际工时 | `POST …/workitem/time`body 用 **`actualTime`**(非 spentTime+ `gmtStart`/`gmtEnd` epoch ms 字符串;见 `runtime-ids.json` `fields.actual_hours` |
| 描述更新 | `PATCH …/workitem/{id}/document``{"content":"<html>","formatType":"RICHTEXT"}` |
## 迭代挂接(已通 · 2026-07-27 · 只挂交付)
创建迭代:`POST /projex/api/workspace/sprint`(必填 `staffIds`;可写 `capacityHours`)。
挂【交付】到迭代:
```http
PATCH /projex/api/workitem/workitem/{id}?_input_charset=utf-8
{"workitemIdentifier":"{id}","propertyKey":"sprint","propertyValue":"{sprintId}","operateType":"COVER"}
```
清空误挂(如需求):`propertyValue:""` + `operateType:"COVER"`
**校验**必须读 `/extra`(详情主接口常不含 sprint 字段,禁止据此判失败):
```http
GET /projex/api/workitem/workitem/{id}/extra?_input_charset=utf-8
result.sprint[].identifier / name
```
产品规则:**只挂【交付】**;需求 / 分析 / 设计默认不挂(除非口令显式)。
### 极速建单注意
1. Cookie 只刷一次;全程纯 HTTP默认**不开浏览器**。
2. 交付建完后,【分析】与【设计】**并行**创建(均 TASK_SUB→交付标准/快轨两树可并行。
3. 状态用 `transit` + **本地追踪 fromStatus**(禁止每次 GET负责人在交棒场景下**创建时即何斐**。
4. 建单 `fieldValueList` 可带计划开始 `79`**不要**在 create 同时写 `79+80`(同日会 400
5. 标签必须 PATCHcreate 带 tag 不落库);可与建子任务重叠;快轨交付/设计须与需求同标签。
6. `requests.Session` keep-alive**禁止**对共享 opener 加全局锁。
7. 脚本入口:`scripts/live_create_fast.py`v5快轨描述/计划/标签/工时 2+2/设计 ASSOCIATED 补挂)。

View File

@@ -0,0 +1,59 @@
# 2026-07-23 真实建单复盘与极速优化
## 测试结论
标准 + 快轨均可建到「待开发」交棒;交付树、标签「故障管理」、快轨无【分析】均正确。
| 轮次 | 编号 |
|---|---|
| 第一轮(探测+UI | ONEOS-141147 |
| 极速 v1 | ONEOS-148154 |
| 极速 v2 | ONEOS-164177含中间探针 |
## 过程问题(已修)
| # | 问题 | 根因 | 修复 |
|---|---|---|---|
| 1 | 状态改不动 / 假成功 | 误用 `updateStatus`UI 点列表区 | `POST …/status/transit` |
| 2 | 负责人改不成 | `updateFieldValue` 错 | `PATCH …/{id}` + `assignedTo` |
| 3 | 状态 ID 不全 | 未抓网络 | 写入 `runtime-ids.json` |
| 4 | 极慢 | Playwright + 串行探测 | 纯 HTTP + 并行 |
| 5 | v1 仍偏慢 | 多余 GET、串行 PATCH 计划、交棒再改负责人 | 见下节 v2 |
## 性能对比
| 口径 | 优化前(第一轮) | 极速 v1 | 极速 v2本轮 |
|---|---|---|---|
| 会话墙钟 | ≈ **17.9 分钟** | — | — |
| 两路径并行建单墙钟 | ≈4.1 分钟自动化 | **4.4 s** | **2.2 s** |
| 标准单路径 | 失败反复 | 3.7 s | **2.2 s** |
| 快轨单路径 | 失败反复 | 3.7 s | **2.1 s** |
| 浏览器 | 多次 | 无 | 无 |
相对第一轮会话 ≈ **490×**;相对 v1 再快约 **2×**
## v2 压榨点(已落地)
1. `status/transit` **本地追踪** `fromStatus`,跳过每次 GET。
2. 建单 `fieldValueList` 带**计划开始(79)**;计划完成不在 create 写(同日会 400
3. 【交付】创建时负责人直接 **何斐**(省 PATCH
4. `requests.Session` keep-alive**去掉全局锁**(否则并行失效)。
5. 打标签与建子任务 **重叠**;两路径并行。
6. 交棒后汇总用创建响应,校验 GET 移出主路径计时。
## 探针结论(未采用)
| 尝试 | 结果 |
|---|---|
| create `fieldValueList` 带 tag | 建单成功但标签不落库 → 仍须 PATCH |
| create 同时写 79+80 | `400 计划…转化异常` |
| urllib 全局 lock + 单 opener | 并行被串行化,单路径 ≈4 s |
## 仍可再压(收益变小)
1. 标签 API 若将来支持 create 落库,可再少 24 次 PATCH。
2. HTTP/2 或连接预热DNS/TLS 复用到进程级)。
3. 业务允许「建单即待开发」且平台支持初始状态 → 少 2 次 transit。
4. 计划完成改为交棒后异步补写(当前故意跳过)。
脚本:`scripts/live_create_fast.py`mode=`live_create_fast_v2`)。

View File

@@ -0,0 +1,53 @@
# Make 导出与截图附件
设计完成(步骤 4且已关联原型页时需求与【交付】均挂附件。任一侧失败 → 不得声称设计完成附件齐全。
## 1. 导出 HTML含源码ZIP
与 Make「发布 → 导出 HTML含源码」对齐。
优先本地 Make Admin
```http
GET {adminOrigin}/api/export-html?path={prototypePath}&projectId={projectId}&includeSource=true
```
| 参数 | 要求 |
|---|---|
| `path` | 原型路径(如 `prototypes/oneos-h5-vehicle-assets` |
| `includeSource` | **必须** `true` |
| 响应 | ZIP`PK` 头);文件名建议 `{prototype-id}-html-source.zip` |
失败时:提示用户在 Make 客户端对该原型执行「发布 → 导出 HTML含源码把 ZIP 路径发回。
**禁止**用「仅对象存储链接」冒充已附带源码包。
## 2. 复制截图(全交互页)
1. Make「发布 → **复制截图**」(或等价:导出该原型主界面及所有交互页截图)。
2. 上传到需求附件与【交付】附件。
3. 缺页/失败 → 列出缺项,不得报成功。
## 3. 挂载范围
同一 ZIP / 同一批截图:
1. 上传到需求 identifier
2. 上传到【交付】任务 identifier
优先 API未知 upload 端点时用已登录浏览器在详情页「附件」上传。
## 4. 与对象存储的关系
| 产物 | 用途 |
|---|---|
| `{baseUrl}/{id}/index.html` | AutoPRD 描述内可点预览链接 |
| 导出 ZIP含源码 | 附件,供开发离线打开 |
| 交互页截图 | 附件,供评审/开发对照 |
三者职责不同,不可互相替代。
## 负向
- 不得导出错误原型页(须 Plan 确认原型路径/名称)。
- 不得把别的需求的旧 ZIP 复用到新需求。
- 快轨交棒默认不跑本附件流程(除非口令同时设计完成+原型)。

View File

@@ -0,0 +1,60 @@
# 交付树模型与关联约定
## 真相源
```text
需求状态 = 阶段看板唯一真相(分析中/设计中/待开发…)
【交付】任务 = 该需求的交付容器(每需求最多 1 条)
【分析】/【设计】 = YunxiaoPMapp 在交付下建的阶段子项
【开发】/【测试】 = 另属开发 Skill / 测试 Skill不进本包
ASSOCIATED = 横向挂钩(【交付】 ↔ 需求)
SUB / TASK_SUB = 纵向拆解(交付 → 分析/设计)
```
## 关系验收
| 关系 | 用在哪里 | 验收 | 优先级 |
|---|---|---|---|
| ASSOCIATED | **仅【交付】** ↔ 需求 | 交付详情「关联项」能看到需求(**强制** | 交付必过 |
| TASK_SUB | 【分析】/【设计】 → 【交付】 | 交付详情「子项」能看到阶段任务(**强制** | 阶段任务必过 |
建单规则Cookie 路径 · 同一 create 只能一条 `createWorkitemRelationInfo`
| 对象 | `createWorkitemRelationInfo` | 另写字段 |
|---|---|---|
| 【交付】 | `ASSOCIATED` → 需求 | — |
| 【分析】/【设计】 | `TASK_SUB` → 交付 | `parent` + `parentIdentifier` = 交付 |
**禁止**对分析/设计只写 `parentIdentifier` + `ASSOCIATED→需求`关联项可能有但交付「子项」仍为空ONEOS-246/247 已复现)。
勿用 `PARENT` 冒充关联项。细则见 [live-api.md](live-api.md)。
## 禁止
| 禁止 | 说明 |
|---|---|
| 创建或描述【开发】/【测试】 | 口令与回报均不出现 |
| 分析/设计未挂成交付子项(无 TASK_SUB | 交付「子项」为 0交棒验收失败 |
| 用任务名称/标题做唯一性或查重 | 不得 `subject` 匹配复用 |
| 同一需求认定多个交付任务编号 | 列出编号请人合并后再继续 |
| 功能模块标签用「分析/设计/交付」 | 模块标签打在需求(可选交付)上 |
## 任务标题(仅展示)
- 【交付】+ 需求标题
- 【分析】+ 需求标题
- 【设计】+ 需求标题
标题可改,**不参与查重**。
## 任务编号唯一性
**唯一允许的查重/复用渠道:云效任务编号**(如 `ONEOS-99` / `serialNumber`)。
| 场景 | 正确 | 错误 |
|---|---|---|
| 首次创建【交付】 | 建单成功后回报并写入「工作项编号(系统)」 | 下次用标题搜 |
| 复用【交付】 | 口令或编号区块带 `交付任务=ONEOS-xx` | list 后按 subject 相等 |
| 判断是否已有交付 | 编号区块或交付 ASSOCIATED 编号集合 | 数【交付】开头标题 |
| 分析/设计幂等 | 仅已登记编号 | 按【分析】+需求标题 |
按编号命中则复用;**计划开始已有值禁止改写**。

Some files were not shown because too many files have changed in this diff Show More