@lark-apaas/coding-miaoda-sandbox-skills 0.1.0-dev.28c4f05 → 0.1.0-dev.4e64c13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/miaoda/animation-skill/SKILL.md +348 -0
- package/miaoda/authz-cli/SKILL.md +1 -0
- package/miaoda/charts-skill/SKILL.md +264 -0
- package/miaoda/creative-to-fullstack/SKILL.md +157 -0
- package/miaoda/creative-to-fullstack/references/artifact-signals.md +46 -0
- package/miaoda/creative-to-fullstack/references/ui-to-function.md +134 -0
- package/miaoda/data-analysis/SKILL.md +151 -0
- package/miaoda/data-analysis/references/json-output-specification.md +277 -0
- package/miaoda/data-analysis/references/post-analysis-guide.md +77 -0
- package/miaoda/data-analysis/references/python-analysis-reference.md +272 -0
- package/miaoda/data-analysis/references/tmp-file-management-guide.md +100 -0
- package/miaoda/debug-investigation/SKILL.md +21 -18
- package/miaoda/extract-json-schema/SKILL.md +147 -0
- package/miaoda/lark-apps/SKILL.md +37 -0
- package/miaoda/lark-apps/references/openapi-key.md +80 -0
- package/miaoda/lark-apps-authz/SKILL.md +292 -0
- package/miaoda/lark-apps-authz/references/permission-points.md +39 -0
- package/miaoda/lark-apps-authz/references/role.md +122 -0
- package/miaoda/lark-apps-db/SKILL.md +226 -0
- package/miaoda/lark-apps-db/references/full-reference.md +302 -0
- package/miaoda/lark-apps-file/SKILL.md +216 -0
- package/miaoda/lark-apps-ops/SKILL.md +62 -0
- package/miaoda/lark-apps-ops/references/lark-apps-access-scope-get.md +30 -0
- package/miaoda/lark-apps-ops/references/lark-apps-access-scope-set.md +40 -0
- package/miaoda/lark-apps-ops/references/lark-apps-cache.md +62 -0
- package/miaoda/lark-apps-ops/references/lark-apps-env.md +46 -0
- package/miaoda/lark-apps-ops/references/lark-apps-local-dev.md +25 -0
- package/miaoda/lark-apps-ops/references/lark-apps-member.md +93 -0
- package/miaoda/lark-apps-ops/references/lark-apps-observability.md +46 -0
- package/miaoda/lark-apps-ops/references/lark-apps-plugin-install.md +36 -0
- package/miaoda/lark-apps-ops/references/lark-apps-plugin-list.md +23 -0
- package/miaoda/lark-apps-ops/references/lark-apps-plugin-uninstall.md +25 -0
- package/miaoda/lark-apps-ops/references/lark-apps-release-create.md +30 -0
- package/miaoda/lark-apps-ops/references/lark-apps-release-get.md +28 -0
- package/miaoda/lark-apps-ops/references/lark-apps-release-list.md +31 -0
- package/miaoda/lark-apps-ops/references/lark-apps-update.md +30 -0
- package/miaoda/lark-apps-ops/references/openapi-key.md +80 -0
- package/miaoda/miaoda-file/SKILL.md +1 -0
- package/miaoda/miaoda-sql/SKILL.md +6 -2
- package/miaoda/performance-review/SKILL.md +144 -0
- package/miaoda/performance-review/references/business-analyzer.md +139 -0
- package/miaoda/performance-review/references/examples.md +107 -0
- package/miaoda/reviewer-usage/SKILL.md +111 -0
- package/miaoda/testing-guide/SKILL.md +218 -0
- package/miaoda-design/lark-apps-comment/SKILL.md +110 -0
- package/miaoda-design/lark-apps-ops/SKILL.md +45 -0
- package/miaoda-design/lark-apps-ops/references/lark-apps-release-create.md +51 -0
- package/miaoda-design/lark-apps-ops/references/lark-apps-release-get.md +28 -0
- package/miaoda-design/lark-apps-ops/references/lark-apps-release-list.md +31 -0
- package/miaoda-design/lark-apps-ops/references/lark-apps-update.md +33 -0
- package/{shared → miaoda-modern}/lark-apps/SKILL.md +5 -5
- package/miaoda-modern/lark-apps/references/openapi-key.md +80 -0
- package/miaoda-modern/lark-apps-ops/SKILL.md +62 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-access-scope-get.md +30 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-access-scope-set.md +40 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-cache.md +62 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-env.md +46 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-local-dev.md +25 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-member.md +93 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-observability.md +46 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-plugin-install.md +36 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-plugin-list.md +23 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-plugin-uninstall.md +25 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-release-create.md +30 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-release-get.md +28 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-release-list.md +31 -0
- package/miaoda-modern/lark-apps-ops/references/lark-apps-update.md +30 -0
- package/{shared/lark-apps → miaoda-modern/lark-apps-ops}/references/openapi-key.md +3 -3
- package/miaoda-modern/memory/SKILL.md +86 -0
- package/package.json +1 -1
- package/shared/lark-cli/SKILL.md +221 -0
- package/shared/lark-cli/lark-base/README.md +56 -0
- package/shared/lark-cli/lark-base/references/lark-base-commands.md +108 -0
- package/shared/lark-cli/lark-calendar/README.md +158 -0
- package/shared/lark-cli/lark-calendar/references/lark-calendar-meeting.md +30 -0
- package/shared/lark-cli/lark-calendar/references/lark-calendar-room-find.md +108 -0
- package/shared/lark-cli/lark-calendar/references/lark-calendar-suggestion.md +120 -0
- package/shared/lark-cli/lark-contact/README.md +35 -0
- package/shared/lark-cli/lark-contact/references/lark-contact-get-user.md +13 -0
- package/shared/lark-cli/lark-contact/references/lark-contact-search-user.md +121 -0
- package/shared/lark-cli/lark-doc/README.md +67 -0
- package/shared/lark-cli/lark-doc/references/lark-doc-fetch.md +138 -0
- package/shared/lark-cli/lark-doc/references/lark-doc-history.md +61 -0
- package/shared/lark-cli/lark-drive/README.md +129 -0
- package/shared/lark-cli/lark-drive/references/lark-drive-files-list.md +183 -0
- package/shared/lark-cli/lark-im/README.md +84 -0
- package/shared/lark-cli/lark-im/references/lark-im-chat-list.md +140 -0
- package/shared/lark-cli/lark-im/references/lark-im-chat-members-list.md +84 -0
- package/shared/lark-cli/lark-im/references/lark-im-chat-search.md +135 -0
- package/shared/lark-cli/lark-im/references/lark-im-reactions.md +232 -0
- package/shared/lark-cli/lark-minutes/README.md +51 -0
- package/shared/lark-cli/lark-minutes/references/lark-minutes-download.md +130 -0
- package/shared/lark-cli/lark-sheets/README.md +173 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-changeset.md +105 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-chart.md +45 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-conditional-format.md +42 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-filter-view.md +49 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-filter.md +42 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-float-image.md +43 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-formula-verify.md +64 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-history.md +70 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-pivot-table.md +44 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-read-data.md +216 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-search-replace.md +67 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-sheet-structure.md +52 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-sparkline.md +47 -0
- package/shared/lark-cli/lark-sheets/references/lark-sheets-workbook.md +69 -0
- package/shared/lark-cli/lark-sheets/scripts/sheets_df.py +32 -0
- package/shared/lark-cli/lark-slides/README.md +86 -0
- package/shared/lark-cli/lark-slides/references/lark-slides-history.md +105 -0
- package/shared/lark-cli/lark-slides/references/lark-slides-xml-presentation-slide-get.md +108 -0
- package/shared/lark-cli/lark-slides/references/lark-slides-xml-presentations-get.md +77 -0
- package/shared/lark-cli/lark-task/README.md +93 -0
- package/shared/lark-cli/lark-task/references/lark-task-get-my-tasks.md +57 -0
- package/shared/lark-cli/lark-task/references/lark-task-get-related-tasks.md +49 -0
- package/shared/lark-cli/lark-task/references/lark-task-search.md +36 -0
- package/shared/lark-cli/lark-task/references/lark-task-tasklist-search.md +35 -0
- package/shared/lark-cli/lark-vc/README.md +40 -0
- package/shared/lark-cli/lark-vc/references/lark-vc-recording.md +31 -0
- package/shared/lark-cli/lark-whiteboard/README.md +35 -0
- package/shared/lark-cli/lark-whiteboard/references/lark-whiteboard-export.md +59 -0
- package/shared/lark-cli/lark-wiki/README.md +50 -0
- package/shared/lark-cli/lark-wiki/references/lark-wiki-node-get.md +59 -0
- package/shared/lark-cli/lark-wiki/references/lark-wiki-node-list.md +95 -0
- package/shared/lark-cli/lark-wiki/references/lark-wiki-space-list.md +68 -0
- package/miaoda-design/attachment/SKILL.md +0 -58
- /package/{shared → miaoda}/memory/SKILL.md +0 -0
- /package/{shared → miaoda-modern}/animation-skill/SKILL.md +0 -0
- /package/{shared → miaoda-modern}/charts-skill/SKILL.md +0 -0
- /package/{shared → miaoda-modern}/data-analysis/SKILL.md +0 -0
- /package/{shared → miaoda-modern}/data-analysis/references/json-output-specification.md +0 -0
- /package/{shared → miaoda-modern}/data-analysis/references/post-analysis-guide.md +0 -0
- /package/{shared → miaoda-modern}/data-analysis/references/python-analysis-reference.md +0 -0
- /package/{shared → miaoda-modern}/data-analysis/references/tmp-file-management-guide.md +0 -0
- /package/{shared → miaoda-modern}/extract-json-schema/SKILL.md +0 -0
- /package/{shared → miaoda-modern}/performance-review/SKILL.md +0 -0
- /package/{shared → miaoda-modern}/performance-review/references/business-analyzer.md +0 -0
- /package/{shared → miaoda-modern}/performance-review/references/examples.md +0 -0
- /package/{shared → miaoda-modern}/reviewer-usage/SKILL.md +0 -0
- /package/{shared → miaoda-modern}/testing-guide/SKILL.md +0 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Performance Review Examples
|
|
2
|
+
|
|
3
|
+
> Extracted from stability-check-examples.md. Covers P1, P2, P3, P4, Q1 rules.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## P1 · Data Access Performance
|
|
8
|
+
|
|
9
|
+
**BAD — Unlimited query**:
|
|
10
|
+
```typescript
|
|
11
|
+
const allProducts = await db.query('SELECT * FROM products'); // full table → OOM
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
**GOOD — Specific fields + pagination**:
|
|
15
|
+
```typescript
|
|
16
|
+
const products = await db.query(
|
|
17
|
+
'SELECT id, name, price FROM products WHERE active = true LIMIT 50 OFFSET $1',
|
|
18
|
+
[page * 50]
|
|
19
|
+
);
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## P2 · Memory Usage
|
|
25
|
+
|
|
26
|
+
**BAD — Large file fully read into memory**:
|
|
27
|
+
```typescript
|
|
28
|
+
const file = fs.readFileSync(req.file.path); // 2GB → OOM
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**GOOD — Stream**:
|
|
32
|
+
```typescript
|
|
33
|
+
await pipeline(fs.createReadStream(req.file.path), transform, fs.createWriteStream(out));
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**BAD — Module-level Map growing without bound**:
|
|
37
|
+
```typescript
|
|
38
|
+
const userCache = new Map(); // never evicted → memory leak
|
|
39
|
+
app.get('/user/:id', async (req, res) => {
|
|
40
|
+
if (!userCache.has(req.params.id)) userCache.set(req.params.id, await User.findById(req.params.id));
|
|
41
|
+
res.json(userCache.get(req.params.id));
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**GOOD — LRU cache**:
|
|
46
|
+
```typescript
|
|
47
|
+
import { LRUCache } from 'lru-cache';
|
|
48
|
+
const userCache = new LRUCache<string, User>({ max: 1000, ttl: 300_000 });
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## P3 · Algorithm Complexity
|
|
54
|
+
|
|
55
|
+
**BAD — O(n²)**:
|
|
56
|
+
```typescript
|
|
57
|
+
function findCommon(a: string[], b: string[]) { return a.filter(x => b.includes(x)); }
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**GOOD — Set O(n)**:
|
|
61
|
+
```typescript
|
|
62
|
+
function findCommon(a: string[], b: string[]) { const s = new Set(b); return a.filter(x => s.has(x)); }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## P4 · Concurrency & Backpressure
|
|
68
|
+
|
|
69
|
+
**BAD — Unbounded Promise.all**:
|
|
70
|
+
```typescript
|
|
71
|
+
const results = await Promise.all(records.map(r => fetch(`/api/${r.id}`))); // 10000 concurrent
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**GOOD — p-limit**:
|
|
75
|
+
```typescript
|
|
76
|
+
import pLimit from 'p-limit';
|
|
77
|
+
const limit = pLimit(10);
|
|
78
|
+
const results = await Promise.all(records.map(r => limit(() => fetch(`/api/${r.id}`))));
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**BAD — Stream without backpressure handling**:
|
|
82
|
+
```typescript
|
|
83
|
+
readable.on('data', (chunk) => { writable.write(transform(chunk)); }); // does not check return value
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**GOOD — pipeline**:
|
|
87
|
+
```typescript
|
|
88
|
+
await pipeline(fs.createReadStream('in.csv'), new TransformStream(), fs.createWriteStream('out.csv'));
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Q1 · Anti-pattern Detection
|
|
94
|
+
|
|
95
|
+
**BAD — Deep nesting**:
|
|
96
|
+
```typescript
|
|
97
|
+
if (user) { if (user.isActive) { if (user.hasPermission('edit')) { if (item) { if (item.isEditable) { /* ... */ } } } } }
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**GOOD — Guard Clause**:
|
|
101
|
+
```typescript
|
|
102
|
+
if (!user) return res.status(401).json({ error: 'Unauthorized' });
|
|
103
|
+
if (!user.isActive) return res.status(403).json({ error: 'Disabled' });
|
|
104
|
+
if (!user.hasPermission('edit')) return res.status(403).json({ error: 'No permission' });
|
|
105
|
+
if (!item?.isEditable) return res.status(400).json({ error: 'Not editable' });
|
|
106
|
+
// business logic, no more nesting
|
|
107
|
+
```
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: reviewer-usage
|
|
3
|
+
description: "Reviewer SubAgent dispatch & post-return protocol — required reading BEFORE invoking Reviewer. Covers when you MUST escalate to Reviewer after repeated self-fix failures, how many Reviewers to dispatch, how to split scopes, what the prompt must contain, and how to act on the per-issue policy tags Reviewer returns. 触发词:派 Reviewer、code review、审查、排查、review and fix、反复失败、修不好、repeated-fix"
|
|
4
|
+
available-agents:
|
|
5
|
+
- Code
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Reviewer Usage Guide
|
|
9
|
+
|
|
10
|
+
This skill is the operational manual for dispatching the Reviewer SubAgent and handling its returned report. Reviewer's own `description` only states what Reviewer is for; everything about *how* to use it lives here. **Load this skill before every Reviewer dispatch.**
|
|
11
|
+
|
|
12
|
+
## When NOT to dispatch Reviewer
|
|
13
|
+
|
|
14
|
+
- Pure code-location questions ("where is X implemented", "which file handles Y") → use Explore.
|
|
15
|
+
- Missing-feature requests ("help me implement X", "X is not implemented yet", 帮我实现 / 还没实现) → handle as regular implementation.
|
|
16
|
+
|
|
17
|
+
## When you MUST escalate (repeated-fix)
|
|
18
|
+
|
|
19
|
+
Inline self-fixing has a hard ceiling. The moment ANY of the following is true, **STOP self-fixing and dispatch a Reviewer via `task` instead** — do not attempt a 3rd inline patch of the same problem:
|
|
20
|
+
|
|
21
|
+
- **同一问题失败 ≥2 轮**: you have already attempted to fix the *same* symptom twice (edit → check → still broken → edit again → still broken) and it persists. The 3rd attempt MUST be a Reviewer dispatch, not another inline guess. Two failed self-fixes is direct evidence your hypothesis is wrong — an independent Reviewer with no anchoring bias is more likely to find the true root cause than a 3rd same-direction patch.
|
|
22
|
+
- **用户二次否定**: the user has rejected your fix twice ("还是不对" / "没生效" / "还是这个问题" on the same issue). The second rejection is a mandatory escalation trigger — do not keep iterating inline.
|
|
23
|
+
|
|
24
|
+
Why this is a hard rule, not a suggestion: thrash (repeatedly editing the same code in the same wrong direction) burns tokens and time while convergence probability stays near zero. Escalating to a Reviewer breaks the loop with fresh, unbiased root-cause analysis. When you escalate, follow the normal dispatch protocol below (still pass `<user-original-message>` verbatim; still pass only `scope` + `dimensions`).
|
|
25
|
+
|
|
26
|
+
## Review dimensions
|
|
27
|
+
|
|
28
|
+
Performance, correctness, security, maintainability. Default to **performance + correctness**; include security only if explicitly requested or clearly relevant. User-specified dimensions override the default.
|
|
29
|
+
|
|
30
|
+
## Dispatch count — trade-offs
|
|
31
|
+
|
|
32
|
+
More is NOT always better:
|
|
33
|
+
|
|
34
|
+
- **Single Reviewer overloaded** → on a large project the attention budget gets diluted and critical bugs are missed.
|
|
35
|
+
- **Too many Reviewers** → cross-scope gaps (issues spanning multiple Reviewers' scopes go unreported), and the same files get re-read by multiple Reviewers (token + latency doubled).
|
|
36
|
+
|
|
37
|
+
### Heuristics (not hard rules — judge by the actual situation)
|
|
38
|
+
|
|
39
|
+
- Use `glob` to roughly estimate file count before dispatching.
|
|
40
|
+
- Small / single-module change (< 50 files): **1 Reviewer**.
|
|
41
|
+
- Mid-size full project (50–150 files): **2 Reviewers**, split by scope.
|
|
42
|
+
- Large full project (> 150 files): **3–4 Reviewers**, split by scope.
|
|
43
|
+
- User explicitly limits the scope or asks for a single dimension on a small change: **1 Reviewer** suffices.
|
|
44
|
+
|
|
45
|
+
## Hard constraints when splitting
|
|
46
|
+
|
|
47
|
+
- **Mutually exclusive scopes**: a typical project splits into `server/` (incl. `server/database/`), `client/`, and `shared/`; each scope is owned by exactly ONE Reviewer. Two Reviewers MUST NOT review the same directory (duplicated Read is the most common form of waste).
|
|
48
|
+
- **Each Reviewer covers all requested dimensions within its own scope** (default: performance + correctness). Do NOT make a single Reviewer the sole owner of "shared / cross-boundary consistency" — that locks its attention onto type contracts and lets performance bugs inside its scope slip through. Cross-boundary consistency is a shared check between two adjacent Reviewers (e.g. the server Reviewer audits "do shared types match what the server actually returns", the client Reviewer audits "do shared interfaces match what the frontend actually calls").
|
|
49
|
+
- **Change-type reviews (not full-project audits)**: a Reviewer MUST read every scope the change actually touches. If a commit modifies `server/`, you MUST dispatch a Reviewer for `server/` — you cannot get away with only a `client/` Reviewer.
|
|
50
|
+
- **Multiple Reviewers MUST be dispatched in parallel** (multiple tool calls in a single message). Never serially.
|
|
51
|
+
- **Each Reviewer's prompt** must spell out `scope = <specific directories or file list>` and `dimensions = <performance/correctness/...>`, and explicitly say "do not read code outside this scope". Do not broadcast the full task to every Reviewer.
|
|
52
|
+
|
|
53
|
+
## Other rules for the dispatch
|
|
54
|
+
|
|
55
|
+
- **Wait synchronously** for all Reviewer reports before fixing. No background dispatch.
|
|
56
|
+
- **Do not pre-read code**; pass scope only (git range, directory paths, or file list). Each Reviewer discovers and reads within its scope.
|
|
57
|
+
- **REQUIRED — Reviewer prompt MUST start with** `<user-original-message>{用户原话}</user-original-message>`. Reviewer uses this verbatim text to classify fix-intent vs review-only mode for its mandatory ACTION block; without it Reviewer guesses wrong and the recommended AskUser option is wrong. ❌ FORBIDDEN: paraphrase, summarize, translate, or omit the user's message — pass it character-for-character.
|
|
58
|
+
|
|
59
|
+
## Caller anti-pattern checklist (read before dispatching Reviewer)
|
|
60
|
+
|
|
61
|
+
### ❌ Anti-pattern 1: scope is narrower than where the true root cause may live
|
|
62
|
+
|
|
63
|
+
The caller does not know where the true root cause is — a "suspicious directory" guessed from surface clues (a filename in the stack trace, a module the user named) often excludes the directory the true root cause actually lives in. Phase 1 Discovery is designed for Reviewer to narrow down via glob/grep on its own; when the caller does that work prematurely, it loses the true root cause.
|
|
64
|
+
|
|
65
|
+
**Hard rule**: for bug-investigation tasks, `scope` MUST stay at a directory-tree top-level boundary (`client/` / `server/` / `shared/`). **Drilling down into a subdirectory or a single file is forbidden.**
|
|
66
|
+
|
|
67
|
+
The only exception is a small refactor PR static review where the commit touches a single subdirectory only AND the total file count exceeds 150 requiring 3–4 Reviewers running in parallel (per the Heuristics earlier in this skill).
|
|
68
|
+
|
|
69
|
+
### ❌ Anti-pattern 2: adding "key observations / focus on / suspected files" sections outside `<user-original-message>`
|
|
70
|
+
|
|
71
|
+
If the caller forms its own shallow hypothesis before dispatching Reviewer and injects that as a "clue" into Reviewer's prompt, it violates the core principle of reviewer-usage: Reviewer is an independent sub-agent whose value comes from judging without caller bias. Injecting observations anchors Reviewer to the caller's (usually wrong) direction → the true root cause is never found.
|
|
72
|
+
|
|
73
|
+
**Hard rule**: outside the `<user-original-message>` block, **only `scope = ...` and `dimensions = ...` are allowed**. Any "focus on / key files / suspected paths / investigation direction / key observations" sections must be removed.
|
|
74
|
+
|
|
75
|
+
Exception: if the user's own message already contains these phrasings (e.g. the user said "please focus on X"), keep them inside `<user-original-message>` verbatim — that is the user's real intent, not caller pollution.
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
## Protocol after Reviewer returns
|
|
79
|
+
|
|
80
|
+
Reviewer pre-tags each issue with a `policy` field (`auto-fix` or `AskUser`) and prints an ACTION header. Code agent acts on the tags directly — it does NOT re-classify.
|
|
81
|
+
|
|
82
|
+
### Step 1 — Read the ACTION header
|
|
83
|
+
|
|
84
|
+
It tells you: (a) how many issues are tagged `auto-fix`, (b) how many are tagged `AskUser`, (c) the exact `options` and `recommended` label for the `ask_user_question` call.
|
|
85
|
+
|
|
86
|
+
### Step 2 — Fix every `policy: auto-fix` issue immediately
|
|
87
|
+
|
|
88
|
+
No AskUser, no confirmation, no asking the user.
|
|
89
|
+
|
|
90
|
+
### Step 3 — Handle `policy: AskUser` issues (only if at least one exists)
|
|
91
|
+
|
|
92
|
+
- **STEP 3a (echo)**: emit a short user-facing summary listing the `policy: AskUser` issues, grouped by 🔴 Critical / 🟠 Bug / 🟡 Suggestion, with file:line. ≤25 lines (collapse the rest as `... (其余 N 项见下方表单)`). The user cannot see Reviewer's report directly — without this echo they cannot decide.
|
|
93
|
+
- **STEP 3b (call ask_user_question)**: in the same turn, immediately call `ask_user_question` — `header`: `Review 确认`; `description`: paste the same list as STEP 3a; ONE Radio `question`: "Reviewer 另发现以下超出本次任务范围的问题,是否一并处理?"; use the exact `options` and `recommended` label that the ACTION header specified.
|
|
94
|
+
- No FINAL reply between 3a and 3b.
|
|
95
|
+
|
|
96
|
+
### Step 4 — Act on the user's choice
|
|
97
|
+
|
|
98
|
+
Strip any trailing `(推荐)` from the returned label before matching:
|
|
99
|
+
|
|
100
|
+
- `修复严重问题` → fix the 🔴+🟠 subset of `policy: AskUser` issues, then report.
|
|
101
|
+
- `修复所有问题` → fix every `policy: AskUser` issue, then report.
|
|
102
|
+
- `修复建议项` → fix every `policy: AskUser` 🟡 issue, then report.
|
|
103
|
+
- `不修复` → report with: `policy: auto-fix` fixes done + `policy: AskUser` issues left untouched (preserve original Reviewer `file:line — desc` entries verbatim).
|
|
104
|
+
|
|
105
|
+
## Recursion and edge cases
|
|
106
|
+
|
|
107
|
+
- If fixes trigger a new Reviewer dispatch, recurse through the same protocol, but cap AskUser follow-ups **per original Reviewer batch** at 2. On the 3rd would-be AskUser, fold remaining `policy: AskUser` items into the final report instead. A brand-new Reviewer dispatch resets the counter.
|
|
108
|
+
- `policy: auto-fix` fix failure does NOT skip AskUser — mark failed items as `未处理` inside the AskUser description so the user sees the real state.
|
|
109
|
+
- `Verdict: Looks good` (zero issues) → no AskUser; report directly.
|
|
110
|
+
- Reviewer report missing `policy` tags or unparseable into 🔴/🟠/🟡 → treat all parseable issues as `policy: AskUser` and route through Step 3 so the user decides.
|
|
111
|
+
- Multiple Reviewers dispatched in parallel: each report runs this protocol independently (no cross-report aggregation); the recursion cap applies per batch.
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: testing-guide
|
|
3
|
+
description: 派发 E2E 子 agent(Task subagent_type="E2E")前**必读**——无论是用户主动要求,还是 agent 自行决定要测/复验功能,不能仅凭用户字面要求就直接派发。Also use when user wants to check, verify, or troubleshoot application functionality via browser. 触发词:检查页面, 看看有没有问题, 走一遍流程, 帮我看看, 试一下, 哪里出问题了, XX不好使, 检查一下, 测一下, 派发 E2E, 打开浏览器测, 验收功能
|
|
4
|
+
steering: true
|
|
5
|
+
steering-topic: testing
|
|
6
|
+
gate-tools:
|
|
7
|
+
- tool: task
|
|
8
|
+
when:
|
|
9
|
+
subagent_type: E2E
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# 检查与验证:工具选择指南
|
|
13
|
+
|
|
14
|
+
根据用户意图选择正确的派遣方式:派遣 E2E 子 agent(通过 `Task(subagent_type="E2E")` 打开浏览器操作一遍)或调用 `api_request`(直接请求后端接口)。
|
|
15
|
+
|
|
16
|
+
## 用户沟通规范
|
|
17
|
+
|
|
18
|
+
与用户沟通时,**禁止**出现 "E2E" / "端到端测试" / "E2E agent" 等术语。E2E agent 的定义就是「用浏览器替你实际操作应用,验收功能是否正常、排查页面问题」——对外直接说这个意思即可:
|
|
19
|
+
|
|
20
|
+
| 禁止 | 改用 |
|
|
21
|
+
|------|------|
|
|
22
|
+
| E2E、端到端测试 | 浏览器测试、浏览器操作 |
|
|
23
|
+
| E2E agent、派遣 E2E | 无需提及 agent,直接说"我用浏览器帮你..." |
|
|
24
|
+
|
|
25
|
+
## 决策规则
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
用户想确认应用是否正常
|
|
29
|
+
├─ 明确要求验证「后端接口」「API 返回值」「请求响应」 → api_request
|
|
30
|
+
└─ 其他所有情况 → Task(subagent_type="E2E")(打开浏览器,以用户视角操作应用)
|
|
31
|
+
├─ 只看视觉(白屏/布局/样式/文案)→ agent_options.mode: "lite"
|
|
32
|
+
└─ 涉及交互/业务流程/数据 → 不传或 agent_options.mode: "standard"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
- **模糊需求一律派遣 E2E**:未明确提到「接口」「API」「后端」时必须派遣 E2E,不要主动选择 `api_request`
|
|
36
|
+
- **`api_request` 仅限显式请求**:仅当明确提到接口 / API / 后端 / 请求 / 响应、且意图是验证接口逻辑而非页面功能时才使用
|
|
37
|
+
- **E2E 结束后禁止追加 `api_request`**:浏览器操作的结果即为最终结果,**严禁**再自动补充验证
|
|
38
|
+
|
|
39
|
+
### E2E 的 mode 选择
|
|
40
|
+
|
|
41
|
+
通过 `agent_options.mode` 指定,**可选参数**,不传或非 `lite` 一律按 `standard` 处理:
|
|
42
|
+
|
|
43
|
+
| mode | 适用场景 | 行为 | 总超时 | 录屏 |
|
|
44
|
+
|------|---------|------|-------|------|
|
|
45
|
+
| `standard`(缺省) | 涉及业务流程、数据流、交互后状态变化 | 完整交互(点击/输入/滚动/提交)+ Network 验证 + 录制 | 5 分钟 | ✅ |
|
|
46
|
+
| `lite` | 只看视觉渲染(CSS/布局/文案/图标)或快速冒烟 | 仅 `open` / `goto` / `wait` / `snapshot` / `screenshot`,**禁止** `click` / `fill` / `type` / `scroll` / `select` / `press` / `drag` / `hover` | 2 分钟 | ❌ |
|
|
47
|
+
|
|
48
|
+
**仅改 CSS / 文案 / 图标 / 布局**(无事件处理、无状态、无数据获取)应直接选 `lite`——更快且 token 消耗显著低,不要默认走 standard 浪费配额;但 `lite` 不能触发 popup / toast / 提交后状态切换等需要操作的现象。testRequirements 里出现"点击"、"填写"、"提交"等动词,**禁止** `lite`,必须 `standard`。
|
|
49
|
+
|
|
50
|
+
## 工具选择速查表
|
|
51
|
+
|
|
52
|
+
| 用户表达 | 选择 | 原因 |
|
|
53
|
+
| --- | --- | --- |
|
|
54
|
+
| "检查一下页面" / "看看有没有问题" / "走一遍流程" / "哪里出问题了" / "试试能不能用" / "XX 不好使" | E2E(standard) | 打开浏览器以用户视角操作 / 复现 |
|
|
55
|
+
| "刚改了 CSS,看看样式对不对" | E2E(lite) | 仅视觉巡检,省时省 token |
|
|
56
|
+
| "测试一下这个接口的返回值对不对" / "调一下后端 API 看看响应" | `api_request` | 明确指定接口验证 |
|
|
57
|
+
|
|
58
|
+
## 派遣 E2E 时的 prompt / 用例规范
|
|
59
|
+
|
|
60
|
+
`prompt` 不是一句话需求,而是一份**结构化验收脚本**。Case 越具体结果越可信;含糊需求只会让 agent 瞎点一通。
|
|
61
|
+
|
|
62
|
+
> **核心原则:agent 只「机械执行 + 报判断」,不做推理。** 判定标准全写死在断言里——别让它自己推断"该测什么"或定义"什么算正常 / 好看"。它的活只有:执行动作 → 看现象 → 报通过 / 不通过。
|
|
63
|
+
|
|
64
|
+
### 调用结构
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
task({
|
|
68
|
+
subagent_type: "E2E",
|
|
69
|
+
agent_options: { mode: "standard" }, // standard=可点击/输入,lite=只截图
|
|
70
|
+
description: "验收创作工具", // 一句话任务名
|
|
71
|
+
prompt: `
|
|
72
|
+
对<被测应用一句话描述>进行端到端验收测试。
|
|
73
|
+
|
|
74
|
+
## 应用结构
|
|
75
|
+
- <页面名> (<路由>) — <布局/职责>
|
|
76
|
+
- ...
|
|
77
|
+
|
|
78
|
+
## 测试用例
|
|
79
|
+
### Case 1: <页面/模块> - <场景>
|
|
80
|
+
1. <动作步>
|
|
81
|
+
2. 断言:<可观察现象>
|
|
82
|
+
...
|
|
83
|
+
`,
|
|
84
|
+
// ...其他参数:按 Task 工具的实际签名如实补全,别只填上面示例里的字段
|
|
85
|
+
})
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### prompt 三段式
|
|
89
|
+
|
|
90
|
+
| 段落 | 内容 | 作用 |
|
|
91
|
+
|------|------|------|
|
|
92
|
+
| 概述 | 一句话说明被测应用是什么 | 让 agent 建立全局认知 |
|
|
93
|
+
| `## 应用结构` | 每个页面的路由 + 布局/职责 | 告诉 agent 去哪、看什么 |
|
|
94
|
+
| `## 测试用例` | 多个 Case,每个含编号步骤 | agent 逐条执行并断言 |
|
|
95
|
+
|
|
96
|
+
### Case 编写规则
|
|
97
|
+
|
|
98
|
+
- **标题**:`### Case N: <模块> - <场景>`,一个 Case 一个独立场景
|
|
99
|
+
- **动作步 / 断言步交替**:动作步动词开头(访问 / 点击 / 输入 / 切换);断言步以「断言:」开头
|
|
100
|
+
- **可定位 + 二元判定**:动作指到具体对象(可见文本,如「发布新帖」按钮);断言给非黑即白判据(出现 / 消失 / 等于 / ≥N / 含某文案),不写"正常""是否合理 / 美观"(见下方对照)
|
|
101
|
+
- **独立可重入**:删除 / 提交等副作用操作走「取消」或验证后还原,不污染后续 Case
|
|
102
|
+
|
|
103
|
+
### Case 复杂度约束(必跑到终态)
|
|
104
|
+
|
|
105
|
+
每个 Case 必须**跑到最终可观测结果**,「打开弹窗 / 看到字段 / 按钮存在」都只是中间态,不算验证。
|
|
106
|
+
|
|
107
|
+
- **跑到终态**:提交后出现在列表 / 跳转后内容正确 / 删除后从列表消失
|
|
108
|
+
- **AI 功能看到输出**:翻译 / 摘要 / 生成等核心卖点,须断言到 AI 产出的内容,不停在"AI 弹窗打开"
|
|
109
|
+
- **主链路 + AI 都覆盖**,不因"非主链路"遗漏
|
|
110
|
+
- **Case ≤ 10**:过多会 token 膨胀、超时
|
|
111
|
+
- **不碰登录 / 认证**:应用无登录逻辑,禁止登录 / 注册 / OAuth / CAPTCHA 相关 Case
|
|
112
|
+
|
|
113
|
+
| ❌ 停在中间状态 | ✅ 跑到最终结果 |
|
|
114
|
+
|------|------|
|
|
115
|
+
| 打开预约弹窗,验证表单字段 | 填写表单全部字段并提交,预约出现在管理列表中 |
|
|
116
|
+
| 验证翻译弹窗是否正常打开 | 点翻译选目标语言确认,内容区域显示翻译后的文本 |
|
|
117
|
+
| 删除确认对话框是否出现 | 点确认后,记录从列表中消失 |
|
|
118
|
+
| 验证课程信息"完整"展示 | 详情页显示课程名、章节列表、≥1 条学员案例 |
|
|
119
|
+
|
|
120
|
+
### 断言可观察化对照
|
|
121
|
+
|
|
122
|
+
| ❌ 含糊(agent 无法核对) | ✅ 可观察 |
|
|
123
|
+
|------|------|
|
|
124
|
+
| "页面正常加载" | "页面包含「创作配置」标题" |
|
|
125
|
+
| "按钮可用" | "「一键生成」按钮处于可点击态" |
|
|
126
|
+
| "跳转成功" | "URL 变为 /materials" |
|
|
127
|
+
| "有数据" | "表格中至少展示 3 行数据" |
|
|
128
|
+
| "弹窗出现" | "弹出详情弹窗,展示标题、正文、配图" |
|
|
129
|
+
| "样式好看" | "卡片使用圆角 + 微投影,整体为暖色调" |
|
|
130
|
+
|
|
131
|
+
### 断言要查到信号层(最易漏检,必读)
|
|
132
|
+
|
|
133
|
+
UI 快照「看起来正常」是最大假阴来源——接口 500、图片 404、失败 toast 都不一定改变页面结构。功能 / 资源类 Case 的断言**必须落到 network / console**,不能只靠无障碍快照或截图:
|
|
134
|
+
|
|
135
|
+
| 漏检模式 | 错误做法 | 正确断言 |
|
|
136
|
+
|------|------|------|
|
|
137
|
+
| 接口报错(提交 / 生成 / 翻译失败) | 看到表单还在、按钮在就判过 | 触发后断言关键接口(尤其 `/api/capability/*` 等业务 / 能力接口)响应码,**非 2xx(4xx/5xx)即 failed** |
|
|
138
|
+
| 图片 / 静态资源 404 | 无障碍快照有 `image` 节点就判过 | 404 的 `<img>` 仍是 image 节点——**必须查 network 该资源非 404,或截图确认像素真渲染** |
|
|
139
|
+
| 失败 toast / 空结果 / 错误兜底 | 没撞见失败 toast 就判过 | 空结果 / 错误兜底 UI / 白屏是**常驻态**,出现即判 failed;失败 toast 瞬时易漏,**撞见可判挂、漏看≠通过**——失败的权威判据是上一行的 network 响应码(非 2xx 即 failed) |
|
|
140
|
+
|
|
141
|
+
**核心动作必须真正触发到终态**:验证某功能 = 实际点击触发按钮(提交 / 生成 / 翻译 / 上传)并等待结果;只验「表单能填 / 按钮存在 / 弹窗打开」就判过 = 根本没测到该功能,必然漏报。
|
|
142
|
+
|
|
143
|
+
### 禁止编写工具能力外的 Case(否则只会产生「假失败」)
|
|
144
|
+
|
|
145
|
+
E2E agent 只在离散时刻抓快照 / 截图,**看不到瞬时过程、不逐帧解析动画、不能在导航前改写流量**。下列现象超出工具能力,写成断言只会被报成"失败(工具能力限制)"——属于无效 Case,**从源头就不要写**:
|
|
146
|
+
|
|
147
|
+
| ❌ 工具看不到的现象 | 为什么看不到 | ✅ 改成可观察的终态断言 |
|
|
148
|
+
|------|------|------|
|
|
149
|
+
| 骨架屏 / loading 占位符 | 它是过场态,本就不该当验证目标——数据回来就消失,根本不要去看它 | 直接断言加载完成后的真实内容出现(内容在 = 加载链路通) |
|
|
150
|
+
| toast / 轻提示一闪而过("提交成功""已复制") | 几秒自动消失,离散快照常错过 | 改断它代表的**真实结果**(记录进列表 / 状态切换),权威判据是 network 响应码(非 2xx 即 failed);无明显终态时用 network 调用或重载后持久态代替,**绝不把 toast 当断言对象** |
|
|
151
|
+
| CSS 动画 / 过渡 / 滚动是否"流畅""有动效" | 截图是静态帧,不逐帧评估动画播放 | 断言动画**结束后的状态**(元素已展开 / 已隐藏 / 已就位) |
|
|
152
|
+
| 靠拦截 / mock 网络返回来造错误(如"让接口返回 500 看兜底") | 工具不能在页面加载前注入拦截或改写响应 | 只验真实响应;要看错误兜底需后端真异常或用真实异常数据,不靠伪造流量 |
|
|
153
|
+
|
|
154
|
+
断言对象若是瞬时中间态 / toast 本身 / 动效本身 / 需伪造网络的分支——改写成稳定终态断言,或直接删掉。
|
|
155
|
+
|
|
156
|
+
### 建议覆盖维度
|
|
157
|
+
|
|
158
|
+
覆盖维度(按实际功能裁剪):
|
|
159
|
+
|
|
160
|
+
| 维度 | 典型 Case |
|
|
161
|
+
|------|-----------|
|
|
162
|
+
| 页面加载 / 初始空状态 | 打开后标题、表单、空状态引导文案是否就位 |
|
|
163
|
+
| 表单交互 / 输入校验 | 输入前按钮禁用 → 输入后变可点击;选择器值更新 |
|
|
164
|
+
| 导航切换 | 点击 tab → URL 变化 → 内容正确 → 可返回 |
|
|
165
|
+
| 详情查看 | 点击查看 → 弹窗展示内容 → 关闭 → 回到列表 |
|
|
166
|
+
| 危险操作确认 | 点击删除 → 确认弹窗 → 点取消 → 记录未删除 |
|
|
167
|
+
| AI 功能(核心卖点) | 触发翻译 / 摘要 / 智能生成 → 断言 AI 实际输出的内容出现 |
|
|
168
|
+
| 视觉一致性 | 配色、圆角/投影、响应式单列堆叠 |
|
|
169
|
+
|
|
170
|
+
## E2E 轮数与复测策略
|
|
171
|
+
|
|
172
|
+
E2E 派遣是**昂贵操作**(每次消耗大量 token + 时间)。E2E agent 只负责暴露问题,**不负责定位根因**。
|
|
173
|
+
|
|
174
|
+
**每次任务执行**的 E2E 总派遣上限 **3 轮**(同一应用内多次任务分别计算):
|
|
175
|
+
|
|
176
|
+
| 轮次 | testRequirements 内容 | 说明 |
|
|
177
|
+
|------|----------------------|------|
|
|
178
|
+
| 第 1 轮 | spec 验收任务的全量 Case(≤5 个) | 首次全面验收 |
|
|
179
|
+
| 第 2 轮 | 上一轮 failed + 未完成的 Case | 定向复测,**不要重新生成全量 testRequirements** |
|
|
180
|
+
| 第 3 轮 | 上一轮仍 failed 的 Case | 最后一次机会 |
|
|
181
|
+
| 第 4 轮起 | 禁止再派遣 E2E | 转为根因分析模式 |
|
|
182
|
+
|
|
183
|
+
**定向复测规则**:
|
|
184
|
+
- 已通过的 Case 最多复测 1 次:担心修复引入回归时可纳入复测,同一 Case 累计通过 2 次后不再纳入
|
|
185
|
+
- 如果上一轮因超时中断,E2E 会返回"已测通过/已测失败/未测"三组——已测通过的结果可信不需重测,只测"失败"和"未测"的
|
|
186
|
+
|
|
187
|
+
**白屏 / 整页打不开 → 复测前先重启 devServer**:白屏多为 **devServer 编译挂死 / HMR 卡住**,非代码 bug,直接再派只会重复白屏、白吃一轮配额。顺序:**① 重启 devServer → ② 查编译输出 / runtime-log 确认无报错(不派 E2E)→ ③ 再正常复测**;真要肉眼确认用 `lite` 截图,别用 standard 探活。
|
|
188
|
+
|
|
189
|
+
**测试范围**:首轮(spec 验收)总 Case **≤ 5**(单次派发上限 ≤10 见 Case 复杂度约束),一行一个 Case,必须含主链路流程测试。禁止测试有真实副作用的功能(发送飞书消息、飞书建群)。
|
|
190
|
+
|
|
191
|
+
**停止派遣 E2E 的触发条件**(满足任一即停止):
|
|
192
|
+
|
|
193
|
+
| 条件 | 说明 |
|
|
194
|
+
|------|------|
|
|
195
|
+
| 已派遣 ≥ 3 轮 | 硬上限 |
|
|
196
|
+
| 同一 Case **未经代码修改**连续失败 ≥ 2 次 | 修复后重试不算连续 |
|
|
197
|
+
| 本次错误信息与上次完全一致 | 说明修复未命中根因 |
|
|
198
|
+
|
|
199
|
+
达到上限后仍有 failed:在 commit_task 结果中标注未通过的 Case,继续推进后续任务。
|
|
200
|
+
|
|
201
|
+
**停止后的行动**(按优先级执行):
|
|
202
|
+
|
|
203
|
+
1. **查后端日志**:若涉及数据/接口错误,用日志查询工具排查 traceid / 服务端日志
|
|
204
|
+
2. **直接读代码**:根据 E2E 报告的 URL 和 problem 定位源文件,人工分析根因
|
|
205
|
+
3. **重启 dev server**:白屏 / 打不开时按上方「白屏 → 复测前先重启 devServer」流程处理
|
|
206
|
+
4. **告知用户**:列出已尝试的修复 + 失败现象,请求补充上下文
|
|
207
|
+
|
|
208
|
+
## Common Mistakes
|
|
209
|
+
|
|
210
|
+
| 错误 | 正确做法 |
|
|
211
|
+
| ------------------------------------- | ------------------------------------- |
|
|
212
|
+
| 用户说"测一下"就调 `api_request` | 默认派遣 E2E(打开浏览器操作) |
|
|
213
|
+
| E2E 完成后又调 `api_request` 补充验证 | 浏览器操作结果即为最终结果,不追加 |
|
|
214
|
+
| 用户说"看看有没有 bug"就同时调两个 | 只派遣 E2E |
|
|
215
|
+
| 用户说"检查接口"时派遣 E2E | 明确提到接口时用 `api_request` |
|
|
216
|
+
| 仅改 CSS / 文案,仍走 `standard` | 优先用 `lite`,速度快、token 消耗低 |
|
|
217
|
+
| 达到停止条件(≥3 轮 / 同一错误未改代码连续失败)仍继续派 E2E | 停止派遣,转为根因分析(读代码 / 查日志) |
|
|
218
|
+
| 复测时全量重测 / 白屏直接再派一轮 | 只传 failed + 未完成的 Case;白屏先重启 devServer 再复测 |
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lark-apps-comment
|
|
3
|
+
description: 当需要查看当前妙搭应用收到的评论、或把某条评论标记为已解决时使用。评论是用户在应用预览页对页面 / 功能留下的反馈;Agent 可据此定位待改的问题,改完再把对应评论 resolve 掉。
|
|
4
|
+
metadata:
|
|
5
|
+
requires:
|
|
6
|
+
bins: ["lark-cli"]
|
|
7
|
+
cliHelp: "lark-cli drive file.comments list --help; lark-cli drive file.comments patch --help"
|
|
8
|
+
control-by-feature-ab: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# lark-apps-comment
|
|
12
|
+
|
|
13
|
+
查看 / 处理**当前应用**的评论。评论上下文来自应用 ID(环境变量 `$app_id`),先经 `lark-cli apps +get` 换取 `meta_token`,再按 `file_type=apps` + `file_token=<meta_token>` 调 `drive file.comments`。
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# 取 meta_token(先执行一次,后续命令复用)
|
|
17
|
+
lark-cli apps +get --app-id "$app_id" -q '.data.app.meta_token'
|
|
18
|
+
|
|
19
|
+
# 仅未解决评论(默认口径)
|
|
20
|
+
lark-cli drive file.comments list \
|
|
21
|
+
--params '{"file_token":"<meta_token>","file_type":"apps","is_solved":false}' \
|
|
22
|
+
--format json
|
|
23
|
+
|
|
24
|
+
# 标记已解决
|
|
25
|
+
lark-cli drive file.comments patch \
|
|
26
|
+
--params '{"file_token":"<meta_token>","file_type":"apps","comment_id":"<commentID>","is_solved":true}' \
|
|
27
|
+
--format json
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
> 参数结构以 `lark-cli schema drive.file.comments.list` / `lark-cli schema drive.file.comments.patch` 为准。
|
|
31
|
+
|
|
32
|
+
## 何时使用
|
|
33
|
+
|
|
34
|
+
✅ 用户说"看看有哪些评论 / 反馈没处理"
|
|
35
|
+
✅ 想按用户反馈列一个待办清单再逐条改
|
|
36
|
+
✅ 某条反馈已经改完,把它标记为已解决
|
|
37
|
+
|
|
38
|
+
❌ 想给评论**回复文字**(沙箱内回复写 API 不可用,只支持看列表和 resolve)
|
|
39
|
+
❌ 修改代码 / 页面本身(用代码编辑工具)
|
|
40
|
+
|
|
41
|
+
## 子命令
|
|
42
|
+
|
|
43
|
+
### `drive file.comments list` —— 查看评论列表
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# 仅未解决评论(默认口径,对齐原 miaoda comment list --only-unresolved)
|
|
47
|
+
lark-cli drive file.comments list \
|
|
48
|
+
--params '{"file_token":"<meta_token>","file_type":"apps","is_solved":false}' \
|
|
49
|
+
--format json
|
|
50
|
+
|
|
51
|
+
# 全部评论(用户明确要求"全部"时省略 is_solved)
|
|
52
|
+
lark-cli drive file.comments list \
|
|
53
|
+
--params '{"file_token":"<meta_token>","file_type":"apps"}' \
|
|
54
|
+
--format json
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
- 分页返回;`has_more=true` 时把返回的 `page_token` 填入 `--params` 的 `"page_token"` 续拉。
|
|
58
|
+
- 评论正文在 `items[].reply_list.replies[].content.elements[]` 里;`is_solved` 标记是否已解决;另有 `quote`(划词引用)等字段。
|
|
59
|
+
|
|
60
|
+
JSON(`--format json`,节选):
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"items": [
|
|
65
|
+
{
|
|
66
|
+
"comment_id": "6916106822734512356",
|
|
67
|
+
"is_solved": false,
|
|
68
|
+
"is_whole": true,
|
|
69
|
+
"quote": "划词评论引用内容",
|
|
70
|
+
"reply_list": {
|
|
71
|
+
"replies": [
|
|
72
|
+
{
|
|
73
|
+
"reply_id": "6916106822734512357",
|
|
74
|
+
"user_id": "ou_demo_xxx",
|
|
75
|
+
"content": {
|
|
76
|
+
"elements": [{ "type": "text_run", "text_run": { "text": "首页标题有个错别字" } }]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
],
|
|
83
|
+
"has_more": false
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### `drive file.comments patch` —— 标记已解决
|
|
88
|
+
|
|
89
|
+
把一条评论标记为已解决,`commentID` 从 list 的 `comment_id` 字段拿:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
lark-cli drive file.comments patch \
|
|
93
|
+
--params '{"file_token":"<meta_token>","file_type":"apps","comment_id":"1703677660120110076","is_solved":true}' \
|
|
94
|
+
--format json
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
写操作,可能触发 exit-10 高风险审批(见 lark-cli skill 的沙箱约定):按提示显式确认后重试。
|
|
98
|
+
|
|
99
|
+
## 典型流程
|
|
100
|
+
|
|
101
|
+
1. `lark-cli apps +get --app-id "$app_id" -q '.data.app.meta_token'` 取 meta_token
|
|
102
|
+
2. `drive file.comments list`(`is_solved:false`)拿到待处理评论
|
|
103
|
+
3. 按评论正文逐条改代码(正文在 `items[].reply_list.replies[].content.elements[].text_run.text`)
|
|
104
|
+
4. 改完对应项后用 `drive file.comments patch` 逐条 `resolve` 关掉
|
|
105
|
+
|
|
106
|
+
## 失败处理
|
|
107
|
+
|
|
108
|
+
- 命令失败时把 `error.hint` 转述给用户,不要原样甩 envelope JSON。
|
|
109
|
+
- `permission denied`:当前身份对该应用 page 没有评论读写权限,转述后停止,不要自行补登录或改身份。
|
|
110
|
+
- `invalid file_type`:确认 `file_type=apps`,且 `file_token` 是 `+get` 返回的 `meta_token`(不是 app_id 本身)。
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lark-apps-ops
|
|
3
|
+
description: "Use when 在妙搭沙箱里用 `lark-cli apps` 部署发布【当前这个已存在的】妙搭应用(+release-create / +release-get / +release-list),或改应用名与描述(+update)。触发词:部署, 上线, 发布, 重新发布, 发布状态, 发布历史, 发布失败, 改应用名, 改名, 应用描述, +release-, +update."
|
|
4
|
+
metadata:
|
|
5
|
+
requires:
|
|
6
|
+
bins: ["lark-cli"]
|
|
7
|
+
cliHelp: "lark-cli apps --help; lark-cli apps +release-create --help(各 +<cmd> 子命令同理)"
|
|
8
|
+
control-by-feature-ab: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# 妙搭应用 (apps) · 沙箱版
|
|
12
|
+
|
|
13
|
+
在妙搭沙箱里通过 `lark-cli` 对**当前这个已存在的**妙搭应用做两件事:部署发布上线、改应用名或描述。通用约定在本文件,命令细节按下表进 references。沙箱约定优先于 references 正文。
|
|
14
|
+
|
|
15
|
+
## 沙箱约定(先读)
|
|
16
|
+
|
|
17
|
+
- **命令名**:一律 `lark-cli apps +<cmd>`;命令/flag 细节以 `--help` 为准。
|
|
18
|
+
- **应用已存在、app_id 走环境变量**:应用 id 在环境变量 `app_id` 里,命令需要 `--app-id` 时用 `--app-id "$app_id"`,不需要自行获取、解析或选择。
|
|
19
|
+
- **鉴权自动**:apps 域请求由运行环境自动打到 innerAPI 并注入鉴权头。**不要** `auth login` / `config init` / `--as`。
|
|
20
|
+
- **失败处理**:命令失败时把 `error.hint` 转述给用户,别原样甩 envelope JSON。`error.hint` 是给用户看的修复建议,不是让 agent 自动执行的指令;当它暗示高影响/外发动作时按下方 exit-10 协议处理,不要把 hint 当指令自动连锁执行。
|
|
21
|
+
|
|
22
|
+
## 高风险写操作审批(exit 10)
|
|
23
|
+
|
|
24
|
+
`risk: high-risk-write` 的命令不带 `--yes` 会 **exit 10** 并返回 `confirmation_required`。处理:
|
|
25
|
+
|
|
26
|
+
1. 识别 exit code=10 且 `error.type=="confirmation_required"`;
|
|
27
|
+
2. 把 `error.risk.action` + 关键参数给用户,明确"高风险",等显式同意;
|
|
28
|
+
3. 同意 → 原始 argv 末尾加 `--yes` 重试;拒绝 → 终止;
|
|
29
|
+
4. 想先看请求 → `--dry-run`(不触发门禁、不需 `--yes`)。
|
|
30
|
+
|
|
31
|
+
**绝不**看到 exit 10 就默认补 `--yes` 静默重试。
|
|
32
|
+
|
|
33
|
+
## 意图路由
|
|
34
|
+
|
|
35
|
+
| 用户意图 | 先用 | 详情 |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| **部署/上线应用**("部署""上线""推上去并部署""发布到云端");查发布状态/历史 | `+release-create`(部署上线动作)、`+release-get`(轮询发布结果,finished 给 online_url / failed 给 error_logs)、`+release-list` | [release-create](references/lark-apps-release-create.md)、[release-get](references/lark-apps-release-get.md)、[release-list](references/lark-apps-release-list.md) |
|
|
38
|
+
| 改应用名或描述 | `+update` | [update](references/lark-apps-update.md) |
|
|
39
|
+
|
|
40
|
+
## 发布态护栏
|
|
41
|
+
|
|
42
|
+
- **发布意图判定**:用户要"可访问 / 线上 / 分享 / 新链接 / 上线" = 发布意图,先走发布链路(`+release-create` → `+release-get`),确认终态后再汇报。
|
|
43
|
+
- 完成 ≠ 发布:本轮 `+release-get` 返回 `finished` 之前,都不代表最新内容已部署;不要拿旁证冒充"最新版本已上线"。
|
|
44
|
+
- **汇报口径**:终态确认后只报 `release_id`、状态、耗时;`finished` 时附 `+release-get` 返回的 `online_url`,`failed` 时转述 `error_logs` 的关键失败步骤。
|
|
45
|
+
- **不要自行拼接任何命令未返回的链接**:管理页 / 开发态入口的域名随部署环境不同,`+release-*` 输出里没有该字段,没有可靠来源就不给。
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# apps +release-create
|
|
2
|
+
|
|
3
|
+
触发当前妙搭应用的一次发布。运行时命令事实以 `lark-cli apps +release-create --help` 为准。
|
|
4
|
+
|
|
5
|
+
## 何时使用
|
|
6
|
+
|
|
7
|
+
✅ 用户说"上线 / 发布 / 部署一下"
|
|
8
|
+
✅ 改完代码想看线上效果
|
|
9
|
+
✅ 需要应用的访问 URL
|
|
10
|
+
|
|
11
|
+
❌ 改代码 / 改配置(用代码编辑工具)
|
|
12
|
+
❌ 已有 `release_id` 只想查状态 → 用 [`+release-get`](lark-apps-release-get.md)
|
|
13
|
+
❌ 没有 `release_id` 想找历史发布 → 用 [`+release-list`](lark-apps-release-list.md)
|
|
14
|
+
|
|
15
|
+
## 前置要求
|
|
16
|
+
|
|
17
|
+
- **本次要发布的改动已提交并推送到远端发布分支。** `+release-create` 发布的是远端分支上已 push 的代码,不是本地工作区——未 commit / 未 push 的改动不会进入这次发布。
|
|
18
|
+
- 发布分支由服务端选定:`--branch` 省略时用应用的默认发布分支。不确定分支名时不要自己拼,先看 `--help`。
|
|
19
|
+
|
|
20
|
+
## 命令骨架
|
|
21
|
+
|
|
22
|
+
- 必填:`--app-id`。
|
|
23
|
+
- 可选:`--branch`;省略时服务端使用默认发布分支。
|
|
24
|
+
- 返回 `release_id` 和 `status`,后续用 `+release-get` 轮询。
|
|
25
|
+
|
|
26
|
+
## 示例
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
lark-cli apps +release-create --app-id "$app_id"
|
|
30
|
+
lark-cli apps +release-create --app-id "$app_id" --dry-run
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 输出契约
|
|
34
|
+
|
|
35
|
+
- 成功读取 `data.release_id` 和 `data.status`;`release_id` 是后续 `+release-get` 的入参。
|
|
36
|
+
- `status=publishing` 表示发布仍在进行;继续用 `+release-get` 轮询,轮询间隔应该为 20s。应用发布平均耗时大约 2min,整体超时时间大约 5min。
|
|
37
|
+
- `+release-create` 返回 release 只代表发布已发起。只有 `+release-get` 对同一个 `release_id` 返回 `finished` 后,才能说本轮最新版本已部署。
|
|
38
|
+
|
|
39
|
+
## Agent 规则
|
|
40
|
+
|
|
41
|
+
**命令是异步的**:`+release-create` 返回只代表发布已发起,不代表已上线。必须用 [`+release-get`](lark-apps-release-get.md) 对同一个 `release_id` 轮询到 `finished`,才能把 `online_url` 当作本轮发布的访问链接。不要加 `&` / `nohup` / 后台 task 让调用提前返回。
|
|
42
|
+
|
|
43
|
+
`+release-create` 部署上线属高影响动作——作为别的命令的连带前置时,按 SKILL.md「发布态护栏」先征得用户同意再发布。
|
|
44
|
+
|
|
45
|
+
## 失败处理
|
|
46
|
+
|
|
47
|
+
轮询到 `status=failed` 时,`+release-get` 的输出已含 `error_logs`(`step` / `error_log`),直接据此向用户转述关键失败步骤,不需要再查别的命令。
|
|
48
|
+
|
|
49
|
+
- 错误信息基本能定位——改完代码重新 commit + push,再跑一次 `+release-create` 即可,不需要清理中间态。
|
|
50
|
+
- 同一类错误改 3 次还修不掉,**停下来告诉用户**当前错误信息和你怀疑的方向,让用户介入。
|
|
51
|
+
- 不要把上一轮的 `release_id` 当成新发布——重发后用新返回的 `release_id` 查状态。
|