@ghyper9023/pi-dev-workflow 0.2.0 → 0.3.1
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/.github/workflows/npm-publish.yml +29 -0
- package/README.md +101 -2
- package/agents/git-agent.md +16 -25
- package/agents/review-agent.md +5 -3
- package/extensions/dev-prompts.ts +320 -26
- package/extensions/git-commands.ts +5 -2
- package/extensions/grill-me-agent.ts +687 -0
- package/extensions/sub-agents.ts +54 -33
- package/package.json +1 -1
- package/skills/grill-with-docs/ADR-FORMAT.md +47 -0
- package/skills/grill-with-docs/CONTEXT-FORMAT.md +77 -0
- package/skills/grill-with-docs/SKILL.md +88 -0
- package/skills/review-html/SKILL.md +36 -25
- package/skills/to-prd/SKILL.md +74 -0
- package/ai/346/217/220/347/244/272/350/257/215/344/274/230/345/214/226.md +0 -341
package/extensions/sub-agents.ts
CHANGED
|
@@ -35,53 +35,69 @@ const PROGRESS_INTERVAL_MS = 1_500;
|
|
|
35
35
|
/** Hard limit on accumulated output per subagent (prevents OOM on runaway). */
|
|
36
36
|
const MAX_BUFFER_BYTES = 500_000;
|
|
37
37
|
|
|
38
|
-
/**
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
]
|
|
38
|
+
/**
|
|
39
|
+
* Locations to auto-load APPEND_SYSTEM.md / append.system.md from (checked in order).
|
|
40
|
+
* Defined as a getter so that osHomedir() is called lazily rather than at module init,
|
|
41
|
+
* avoiding a potential crash when the module is loaded in restricted environments.
|
|
42
|
+
*/
|
|
43
|
+
function getAppendSystemPaths(): string[] {
|
|
44
|
+
return [
|
|
45
|
+
path.join(osHomedir(), ".pi", "agent", "append.system.md"),
|
|
46
|
+
".pi/append.system.md",
|
|
47
|
+
"APPEND_SYSTEM.md",
|
|
48
|
+
];
|
|
49
|
+
}
|
|
44
50
|
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
/** Cache for append.system.md content, keyed by cwd to support multi-project isolation. */
|
|
52
|
+
const _appendSystemCache = new Map<string, string | null>();
|
|
47
53
|
|
|
48
54
|
function loadAppendSystem(cwd: string): string | null {
|
|
49
|
-
|
|
50
|
-
|
|
55
|
+
const cached = _appendSystemCache.get(cwd);
|
|
56
|
+
if (cached !== undefined) return cached;
|
|
57
|
+
for (const loc of getAppendSystemPaths()) {
|
|
51
58
|
const abs = path.isAbsolute(loc) ? loc : path.join(cwd, loc);
|
|
52
59
|
try {
|
|
53
60
|
const content = fs.readFileSync(abs, "utf-8").trim();
|
|
54
61
|
if (content) {
|
|
55
|
-
|
|
62
|
+
_appendSystemCache.set(cwd, content);
|
|
56
63
|
return content;
|
|
57
64
|
}
|
|
58
65
|
} catch {
|
|
59
66
|
// file not found or unreadable, try next
|
|
60
67
|
}
|
|
61
68
|
}
|
|
62
|
-
|
|
69
|
+
_appendSystemCache.set(cwd, null);
|
|
63
70
|
return null;
|
|
64
71
|
}
|
|
65
72
|
|
|
66
|
-
/** Find the newest HTML review file in pi-review/ directory. */
|
|
73
|
+
/** Find the newest HTML review file in pi-review/ or pi-dev-output/pi-review/ directory. */
|
|
67
74
|
function findNewestReviewHtml(cwd: string): string {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
const candidates = [
|
|
76
|
+
path.join(cwd, "pi-review"),
|
|
77
|
+
path.join(cwd, "pi-dev-output", "pi-review"),
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
for (const reviewDir of candidates) {
|
|
81
|
+
try {
|
|
82
|
+
if (fs.existsSync(reviewDir)) {
|
|
83
|
+
const files = fs.readdirSync(reviewDir)
|
|
84
|
+
.filter(f => f.endsWith(".html"))
|
|
85
|
+
.map(f => ({
|
|
86
|
+
name: f,
|
|
87
|
+
mtime: fs.statSync(path.join(reviewDir, f)).mtimeMs,
|
|
88
|
+
}))
|
|
89
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
90
|
+
if (files.length > 0) {
|
|
91
|
+
// Return relative path from cwd
|
|
92
|
+
const rel = path.relative(cwd, reviewDir);
|
|
93
|
+
return rel + "/" + files[0].name;
|
|
94
|
+
}
|
|
80
95
|
}
|
|
96
|
+
} catch {
|
|
97
|
+
// ignore fs errors
|
|
81
98
|
}
|
|
82
|
-
} catch {
|
|
83
|
-
// ignore fs errors
|
|
84
99
|
}
|
|
100
|
+
|
|
85
101
|
return "";
|
|
86
102
|
}
|
|
87
103
|
|
|
@@ -108,7 +124,10 @@ function osHomedir(): string {
|
|
|
108
124
|
const activeChildren = new Set<import("node:child_process").ChildProcess>();
|
|
109
125
|
|
|
110
126
|
function killAllChildren(): void {
|
|
111
|
-
|
|
127
|
+
// Snapshot the Set to avoid potential iteration issues if exit callbacks
|
|
128
|
+
// modify activeChildren during the loop.
|
|
129
|
+
const children = [...activeChildren];
|
|
130
|
+
for (const proc of children) {
|
|
112
131
|
try {
|
|
113
132
|
if (proc.pid !== undefined && !proc.killed) {
|
|
114
133
|
proc.kill("SIGTERM");
|
|
@@ -337,9 +356,7 @@ export async function spawnSubagent(
|
|
|
337
356
|
onProgress(`[${agent.name}] (${elapsed}s) ⏳ 处理中...`);
|
|
338
357
|
}
|
|
339
358
|
}, PROGRESS_INTERVAL_MS);
|
|
340
|
-
|
|
341
|
-
progressTimer.unref();
|
|
342
|
-
}
|
|
359
|
+
progressTimer.unref();
|
|
343
360
|
|
|
344
361
|
const settle = (result: SubagentResult) => {
|
|
345
362
|
if (settled) return;
|
|
@@ -402,7 +419,7 @@ export async function spawnSubagent(
|
|
|
402
419
|
durationMs: 0,
|
|
403
420
|
});
|
|
404
421
|
}, effectiveTimeout);
|
|
405
|
-
|
|
422
|
+
timer.unref();
|
|
406
423
|
|
|
407
424
|
// ── Abort signal wiring ─────────────────────────────
|
|
408
425
|
if (signal) {
|
|
@@ -422,6 +439,7 @@ export function extractFinalOutput(jsonOutput: string): string {
|
|
|
422
439
|
// Parse JSON lines from --mode json output
|
|
423
440
|
// Try multiple event formats to find the final assistant response
|
|
424
441
|
let result = "";
|
|
442
|
+
let textEndSeen = false;
|
|
425
443
|
|
|
426
444
|
for (const line of jsonOutput.split("\n")) {
|
|
427
445
|
if (!line.trim()) continue;
|
|
@@ -430,7 +448,9 @@ export function extractFinalOutput(jsonOutput: string): string {
|
|
|
430
448
|
|
|
431
449
|
// Format 1: pi's --mode json message_update with text_delta (streaming)
|
|
432
450
|
// {"type":"message_update","assistantMessageEvent":{"type":"text_delta","delta":"..."}}
|
|
433
|
-
|
|
451
|
+
// Once text_end has been seen, skip subsequent text_delta events to
|
|
452
|
+
// avoid appending stale deltas that arrive out of order.
|
|
453
|
+
if (!textEndSeen && event.type === "message_update" &&
|
|
434
454
|
event.assistantMessageEvent?.type === "text_delta") {
|
|
435
455
|
result += event.assistantMessageEvent.delta || "";
|
|
436
456
|
}
|
|
@@ -441,6 +461,7 @@ export function extractFinalOutput(jsonOutput: string): string {
|
|
|
441
461
|
event.assistantMessageEvent?.type === "text_end" &&
|
|
442
462
|
event.assistantMessageEvent.content) {
|
|
443
463
|
result = event.assistantMessageEvent.content;
|
|
464
|
+
textEndSeen = true;
|
|
444
465
|
}
|
|
445
466
|
|
|
446
467
|
// Format 2: Anthropic-style message events
|
package/package.json
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# ADR Format
|
|
2
|
+
|
|
3
|
+
ADRs live in `docs/adr/` and use sequential numbering: `0001-slug.md`, `0002-slug.md`, etc.
|
|
4
|
+
|
|
5
|
+
Create the `docs/adr/` directory lazily — only when the first ADR is needed.
|
|
6
|
+
|
|
7
|
+
## Template
|
|
8
|
+
|
|
9
|
+
```md
|
|
10
|
+
# {Short title of the decision}
|
|
11
|
+
|
|
12
|
+
{1-3 sentences: what's the context, what did we decide, and why.}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
That's it. An ADR can be a single paragraph. The value is in recording *that* a decision was made and *why* — not in filling out sections.
|
|
16
|
+
|
|
17
|
+
## Optional sections
|
|
18
|
+
|
|
19
|
+
Only include these when they add genuine value. Most ADRs won't need them.
|
|
20
|
+
|
|
21
|
+
- **Status** frontmatter (`proposed | accepted | deprecated | superseded by ADR-NNNN`) — useful when decisions are revisited
|
|
22
|
+
- **Considered Options** — only when the rejected alternatives are worth remembering
|
|
23
|
+
- **Consequences** — only when non-obvious downstream effects need to be called out
|
|
24
|
+
|
|
25
|
+
## Numbering
|
|
26
|
+
|
|
27
|
+
Scan `docs/adr/` for the highest existing number and increment by one.
|
|
28
|
+
|
|
29
|
+
## When to offer an ADR
|
|
30
|
+
|
|
31
|
+
All three of these must be true:
|
|
32
|
+
|
|
33
|
+
1. **Hard to reverse** — the cost of changing your mind later is meaningful
|
|
34
|
+
2. **Surprising without context** — a future reader will look at the code and wonder "why on earth did they do it this way?"
|
|
35
|
+
3. **The result of a real trade-off** — there were genuine alternatives and you picked one for specific reasons
|
|
36
|
+
|
|
37
|
+
If a decision is easy to reverse, skip it — you'll just reverse it. If it's not surprising, nobody will wonder why. If there was no real alternative, there's nothing to record beyond "we did the obvious thing."
|
|
38
|
+
|
|
39
|
+
### What qualifies
|
|
40
|
+
|
|
41
|
+
- **Architectural shape.** "We're using a monorepo." "The write model is event-sourced, the read model is projected into Postgres."
|
|
42
|
+
- **Integration patterns between contexts.** "Ordering and Billing communicate via domain events, not synchronous HTTP."
|
|
43
|
+
- **Technology choices that carry lock-in.** Database, message bus, auth provider, deployment target. Not every library — just the ones that would take a quarter to swap out.
|
|
44
|
+
- **Boundary and scope decisions.** "Customer data is owned by the Customer context; other contexts reference it by ID only." The explicit no-s are as valuable as the yes-s.
|
|
45
|
+
- **Deliberate deviations from the obvious path.** "We're using manual SQL instead of an ORM because X." Anything where a reasonable reader would assume the opposite. These stop the next engineer from "fixing" something that was deliberate.
|
|
46
|
+
- **Constraints not visible in the code.** "We can't use AWS because of compliance requirements." "Response times must be under 200ms because of the partner API contract."
|
|
47
|
+
- **Rejected alternatives when the rejection is non-obvious.** If you considered GraphQL and picked REST for subtle reasons, record it — otherwise someone will suggest GraphQL again in six months.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# CONTEXT.md Format
|
|
2
|
+
|
|
3
|
+
## Structure
|
|
4
|
+
|
|
5
|
+
```md
|
|
6
|
+
# {Context Name}
|
|
7
|
+
|
|
8
|
+
{One or two sentence description of what this context is and why it exists.}
|
|
9
|
+
|
|
10
|
+
## Language
|
|
11
|
+
|
|
12
|
+
**Order**:
|
|
13
|
+
{A concise description of the term}
|
|
14
|
+
_Avoid_: Purchase, transaction
|
|
15
|
+
|
|
16
|
+
**Invoice**:
|
|
17
|
+
A request for payment sent to a customer after delivery.
|
|
18
|
+
_Avoid_: Bill, payment request
|
|
19
|
+
|
|
20
|
+
**Customer**:
|
|
21
|
+
A person or organization that places orders.
|
|
22
|
+
_Avoid_: Client, buyer, account
|
|
23
|
+
|
|
24
|
+
## Relationships
|
|
25
|
+
|
|
26
|
+
- An **Order** produces one or more **Invoices**
|
|
27
|
+
- An **Invoice** belongs to exactly one **Customer**
|
|
28
|
+
|
|
29
|
+
## Example dialogue
|
|
30
|
+
|
|
31
|
+
> **Dev:** "When a **Customer** places an **Order**, do we create the **Invoice** immediately?"
|
|
32
|
+
> **Domain expert:** "No — an **Invoice** is only generated once a **Fulfillment** is confirmed."
|
|
33
|
+
|
|
34
|
+
## Flagged ambiguities
|
|
35
|
+
|
|
36
|
+
- "account" was used to mean both **Customer** and **User** — resolved: these are distinct concepts.
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Rules
|
|
40
|
+
|
|
41
|
+
- **Be opinionated.** When multiple words exist for the same concept, pick the best one and list the others as aliases to avoid.
|
|
42
|
+
- **Flag conflicts explicitly.** If a term is used ambiguously, call it out in "Flagged ambiguities" with a clear resolution.
|
|
43
|
+
- **Keep definitions tight.** One sentence max. Define what it IS, not what it does.
|
|
44
|
+
- **Show relationships.** Use bold term names and express cardinality where obvious.
|
|
45
|
+
- **Only include terms specific to this project's context.** General programming concepts (timeouts, error types, utility patterns) don't belong even if the project uses them extensively. Before adding a term, ask: is this a concept unique to this context, or a general programming concept? Only the former belongs.
|
|
46
|
+
- **Group terms under subheadings** when natural clusters emerge. If all terms belong to a single cohesive area, a flat list is fine.
|
|
47
|
+
- **Write an example dialogue.** A conversation between a dev and a domain expert that demonstrates how the terms interact naturally and clarifies boundaries between related concepts.
|
|
48
|
+
|
|
49
|
+
## Single vs multi-context repos
|
|
50
|
+
|
|
51
|
+
**Single context (most repos):** One `CONTEXT.md` at the repo root.
|
|
52
|
+
|
|
53
|
+
**Multiple contexts:** A `CONTEXT-MAP.md` at the repo root lists the contexts, where they live, and how they relate to each other:
|
|
54
|
+
|
|
55
|
+
```md
|
|
56
|
+
# Context Map
|
|
57
|
+
|
|
58
|
+
## Contexts
|
|
59
|
+
|
|
60
|
+
- [Ordering](./src/ordering/CONTEXT.md) — receives and tracks customer orders
|
|
61
|
+
- [Billing](./src/billing/CONTEXT.md) — generates invoices and processes payments
|
|
62
|
+
- [Fulfillment](./src/fulfillment/CONTEXT.md) — manages warehouse picking and shipping
|
|
63
|
+
|
|
64
|
+
## Relationships
|
|
65
|
+
|
|
66
|
+
- **Ordering → Fulfillment**: Ordering emits `OrderPlaced` events; Fulfillment consumes them to start picking
|
|
67
|
+
- **Fulfillment → Billing**: Fulfillment emits `ShipmentDispatched` events; Billing consumes them to generate invoices
|
|
68
|
+
- **Ordering ↔ Billing**: Shared types for `CustomerId` and `Money`
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The skill infers which structure applies:
|
|
72
|
+
|
|
73
|
+
- If `CONTEXT-MAP.md` exists, read it to find contexts
|
|
74
|
+
- If only a root `CONTEXT.md` exists, single context
|
|
75
|
+
- If neither exists, create a root `CONTEXT.md` lazily when the first term is resolved
|
|
76
|
+
|
|
77
|
+
When multiple contexts exist, infer which one the current topic relates to. If unclear, ask.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: grill-with-docs
|
|
3
|
+
description: Grilling session that challenges your plan against the existing domain model, sharpens terminology, and updates documentation (CONTEXT.md, ADRs) inline as decisions crystallise. Use when user wants to stress-test a plan against their project's language and documented decisions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<what-to-do>
|
|
7
|
+
|
|
8
|
+
Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer.
|
|
9
|
+
|
|
10
|
+
Ask the questions one at a time, waiting for feedback on each question before continuing.
|
|
11
|
+
|
|
12
|
+
If a question can be answered by exploring the codebase, explore the codebase instead.
|
|
13
|
+
|
|
14
|
+
</what-to-do>
|
|
15
|
+
|
|
16
|
+
<supporting-info>
|
|
17
|
+
|
|
18
|
+
## Domain awareness
|
|
19
|
+
|
|
20
|
+
During codebase exploration, also look for existing documentation:
|
|
21
|
+
|
|
22
|
+
### File structure
|
|
23
|
+
|
|
24
|
+
Most repos have a single context:
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
/
|
|
28
|
+
├── CONTEXT.md
|
|
29
|
+
├── docs/
|
|
30
|
+
│ └── adr/
|
|
31
|
+
│ ├── 0001-event-sourced-orders.md
|
|
32
|
+
│ └── 0002-postgres-for-write-model.md
|
|
33
|
+
└── src/
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
If a `CONTEXT-MAP.md` exists at the root, the repo has multiple contexts. The map points to where each one lives:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
/
|
|
40
|
+
├── CONTEXT-MAP.md
|
|
41
|
+
├── docs/
|
|
42
|
+
│ └── adr/ ← system-wide decisions
|
|
43
|
+
├── src/
|
|
44
|
+
│ ├── ordering/
|
|
45
|
+
│ │ ├── CONTEXT.md
|
|
46
|
+
│ │ └── docs/adr/ ← context-specific decisions
|
|
47
|
+
│ └── billing/
|
|
48
|
+
│ ├── CONTEXT.md
|
|
49
|
+
│ └── docs/adr/
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Create files lazily — only when you have something to write. If no `CONTEXT.md` exists, create one when the first term is resolved. If no `docs/adr/` exists, create it when the first ADR is needed.
|
|
53
|
+
|
|
54
|
+
## During the session
|
|
55
|
+
|
|
56
|
+
### Challenge against the glossary
|
|
57
|
+
|
|
58
|
+
When the user uses a term that conflicts with the existing language in `CONTEXT.md`, call it out immediately. "Your glossary defines 'cancellation' as X, but you seem to mean Y — which is it?"
|
|
59
|
+
|
|
60
|
+
### Sharpen fuzzy language
|
|
61
|
+
|
|
62
|
+
When the user uses vague or overloaded terms, propose a precise canonical term. "You're saying 'account' — do you mean the Customer or the User? Those are different things."
|
|
63
|
+
|
|
64
|
+
### Discuss concrete scenarios
|
|
65
|
+
|
|
66
|
+
When domain relationships are being discussed, stress-test them with specific scenarios. Invent scenarios that probe edge cases and force the user to be precise about the boundaries between concepts.
|
|
67
|
+
|
|
68
|
+
### Cross-reference with code
|
|
69
|
+
|
|
70
|
+
When the user states how something works, check whether the code agrees. If you find a contradiction, surface it: "Your code cancels entire Orders, but you just said partial cancellation is possible — which is right?"
|
|
71
|
+
|
|
72
|
+
### Update CONTEXT.md inline
|
|
73
|
+
|
|
74
|
+
When a term is resolved, update `CONTEXT.md` right there. Don't batch these up — capture them as they happen. Use the format in [CONTEXT-FORMAT.md](./CONTEXT-FORMAT.md).
|
|
75
|
+
|
|
76
|
+
`CONTEXT.md` should be totally devoid of implementation details. Do not treat `CONTEXT.md` as a spec, a scratch pad, or a repository for implementation decisions. It is a glossary and nothing else.
|
|
77
|
+
|
|
78
|
+
### Offer ADRs sparingly
|
|
79
|
+
|
|
80
|
+
Only offer to create an ADR when all three are true:
|
|
81
|
+
|
|
82
|
+
1. **Hard to reverse** — the cost of changing your mind later is meaningful
|
|
83
|
+
2. **Surprising without context** — a future reader will wonder "why did they do it this way?"
|
|
84
|
+
3. **The result of a real trade-off** — there were genuine alternatives and you picked one for specific reasons
|
|
85
|
+
|
|
86
|
+
If any of the three is missing, skip the ADR. Use the format in [ADR-FORMAT.md](./ADR-FORMAT.md).
|
|
87
|
+
|
|
88
|
+
</supporting-info>
|
|
@@ -4,9 +4,9 @@ description: review 代码并输出交互式 HTML 报告。适用于代码审查
|
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
你是一个代码审查助手。用户要求你审查**当前代码库**的改动,具体包括:
|
|
7
|
-
- `git diff` 相对于 HEAD
|
|
8
|
-
- 最近 **2
|
|
9
|
-
-
|
|
7
|
+
- `git diff HEAD` 相对于 HEAD 的所有未提交改动(如果无输出,则默认使用最近 1 次 commit 的改动 `git log -p -n 1`)。默认不允许探索整个代码库除非用户明确要求。
|
|
8
|
+
- 最近 **2(或指定个数)个 commit** 的完整改动(使用 `git log -p -n <N>`)
|
|
9
|
+
- 完整的整个代码库(需用户明确说明)
|
|
10
10
|
|
|
11
11
|
## 硬性输出要求
|
|
12
12
|
|
|
@@ -14,32 +14,43 @@ description: review 代码并输出交互式 HTML 报告。适用于代码审查
|
|
|
14
14
|
**直接从 `<!DOCTYPE html>` 开始输出一个完整的、自包含的 HTML 文档。**
|
|
15
15
|
**使用中文+英文专业名词**
|
|
16
16
|
|
|
17
|
-
###
|
|
17
|
+
### 审查问题分类与重要程度
|
|
18
18
|
|
|
19
|
-
1. **BUG
|
|
20
|
-
2.
|
|
21
|
-
3.
|
|
22
|
-
4.
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
1. **BUG**:潜在 bug,最高优先级。
|
|
20
|
+
2. **敏感信息**:敏感信息泄露、敏感文件未加入 `.gitignore`,高优先级。
|
|
21
|
+
3. **可维护性**:代码解耦、结构清晰、冗余代码优化,中优先级。
|
|
22
|
+
4. **规范**:代码规范、代码风格,低优先级。
|
|
23
|
+
5. **语法糖**:适合当前语言的高阶语法优化,维持原逻辑和无 bug > 性能提升大 > 可读性 > 性能提升可忽略 > 缩短代码行数,低优先级。
|
|
24
|
+
6. **其他**:其他问题。
|
|
25
25
|
|
|
26
|
-
### HTML
|
|
26
|
+
### HTML 内容约束
|
|
27
27
|
|
|
28
|
-
1.
|
|
29
|
-
2.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
1. **外观**:简单的现代 CSS(白/灰背景,清晰字体)。全部内联,不引用外部 CDN。
|
|
29
|
+
2. **交互**:提供折叠/展开功能,默认只展示文件名称和问题数量,点击文件名展开详细审查意见。
|
|
30
|
+
3. **内容**:每个改动文件至少包含:文件路径、改动摘要(+/- 行数)、具体审查意见(问题分类及描述)。
|
|
31
|
+
4. **轻量**:总 HTML 大小控制如下——审查整个代码库时上限为 2000 行(若代码库内容较少则仍遵循 700 行限制以保持简洁);其他情况(diff / commit)严格控制在 700 行以内。CSS 和 JS 均为少量内联。
|
|
32
|
+
|
|
33
|
+
### 特殊场景:简洁总结与评分
|
|
34
|
+
|
|
35
|
+
当审查结果**没有任何重要程度为“高”或“最高”的问题**(即仅包含中、低或无问题)时,使用简洁 HTML 输出,不需要交互式折叠,仅展示:
|
|
36
|
+
- 改动摘要
|
|
37
|
+
- 总体评分(满分 100)及简短理由
|
|
38
|
+
- 如果审查对象是**未提交的改动**,额外提供一条符合 Conventional Commits 规范的 commit message 建议(例如 `fix: 修复xxx`、`feat: 新增xxx`),从改动内容智能生成;若审查对象是已提交的 commit 或整个代码库,则只展示评分与总结,不提供 commit message。
|
|
39
|
+
|
|
40
|
+
评分参考标准(严格、公正):
|
|
41
|
+
- **60 分(及格)**:存在少量中等问题,代码可运行但需改进。
|
|
42
|
+
- **80 分(良好)**:仅有轻微(低)问题,整体质量较好。
|
|
43
|
+
- **95 分(优秀)**:几乎无问题,设计清晰。
|
|
44
|
+
- **99 分(完美)**:无可挑剔,代码典范。
|
|
45
|
+
(实际得分根据问题数量与严重性严格判定)
|
|
36
46
|
|
|
37
47
|
## 执行步骤
|
|
38
48
|
|
|
39
|
-
1.
|
|
40
|
-
2.
|
|
41
|
-
3.
|
|
49
|
+
1. 根据用户指令运行 `git diff HEAD` 或 `git log -p -n <N>` 获取改动,或遍历代码库。
|
|
50
|
+
2. 合并改动,按文件分组。
|
|
51
|
+
3. 对每个文件进行审查,并生成符合上述要求的 HTML。
|
|
52
|
+
4. 自动确保 `pi-dev-output/pi-review/` 文件夹存在于项目根目录,若不存在则创建;并确保 `pi-dev-output/` 下的 `.gitignore` 包含 `*`(忽略所有内容但保留目录)。
|
|
53
|
+
5. HTML 文件命名格式:`年月日时分-任务简述(极简10词以内)-index.html`,若同名文件已存在则编号递增(如 `index1.html`)。
|
|
54
|
+
6. 直接输出 HTML 文件到 `pi-dev-output/pi-review/` 目录,**不要添加任何解释性文字**,仅简短说明工作完成和输出文件路径即可。
|
|
42
55
|
|
|
43
|
-
|
|
44
|
-
HTML文件名称格式:年月日时分-任务简述(极简10词以内)-index.html,有同名则index+1。
|
|
45
|
-
如果review未发现必须需要修改(重要程度>=中)的问题,如果改动未提交,则html简约输出只说明改动总结即可,无需交互,并在开头附带规范的git-commit信息便于用户提交。
|
|
56
|
+
请严格遵循以上规则。
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: to-prd
|
|
3
|
+
description: Turn the current conversation context into a PRD document and save it locally. Use when user wants to create a PRD from the current context.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
This skill takes the current conversation context and codebase understanding and produces a PRD. Do NOT interview the user — just synthesize what you already know.
|
|
7
|
+
|
|
8
|
+
## Process
|
|
9
|
+
|
|
10
|
+
1. Explore the repo to understand the current state of the codebase, if you haven't already. Use the project's domain glossary vocabulary throughout the PRD, and respect any ADRs in the area you're touching.
|
|
11
|
+
|
|
12
|
+
2. Sketch out the major modules you will need to build or modify to complete the implementation. Actively look for opportunities to extract deep modules that can be tested in isolation.
|
|
13
|
+
|
|
14
|
+
A deep module (as opposed to a shallow module) is one which encapsulates a lot of functionality in a simple, testable interface which rarely changes.
|
|
15
|
+
|
|
16
|
+
Check with the user that these modules match their expectations. Check with the user which modules they want tests written for.
|
|
17
|
+
|
|
18
|
+
3. Write the PRD using the template below, then save it to `pi-dev-output/pi-prd/` directory.
|
|
19
|
+
|
|
20
|
+
<prd-template>
|
|
21
|
+
|
|
22
|
+
## Problem Statement
|
|
23
|
+
|
|
24
|
+
The problem that the user is facing, from the user's perspective.
|
|
25
|
+
|
|
26
|
+
## Solution
|
|
27
|
+
|
|
28
|
+
The solution to the problem, from the user's perspective.
|
|
29
|
+
|
|
30
|
+
## User Stories
|
|
31
|
+
|
|
32
|
+
A LONG, numbered list of user stories. Each user story should be in the format of:
|
|
33
|
+
|
|
34
|
+
1. As an <actor>, I want a <feature>, so that <benefit>
|
|
35
|
+
|
|
36
|
+
<user-story-example>
|
|
37
|
+
1. As a mobile bank customer, I want to see balance on my accounts, so that I can make better informed decisions about my spending
|
|
38
|
+
</user-story-example>
|
|
39
|
+
|
|
40
|
+
This list of user stories should be extremely extensive and cover all aspects of the feature.
|
|
41
|
+
|
|
42
|
+
## Implementation Decisions
|
|
43
|
+
|
|
44
|
+
A list of implementation decisions that were made. This can include:
|
|
45
|
+
|
|
46
|
+
- The modules that will be built/modified
|
|
47
|
+
- The interfaces of those modules that will be modified
|
|
48
|
+
- Technical clarifications from the developer
|
|
49
|
+
- Architectural decisions
|
|
50
|
+
- Schema changes
|
|
51
|
+
- API contracts
|
|
52
|
+
- Specific interactions
|
|
53
|
+
|
|
54
|
+
Do NOT include specific file paths or code snippets. They may end up being outdated very quickly.
|
|
55
|
+
|
|
56
|
+
Exception: if a prototype produced a snippet that encodes a decision more precisely than prose can (state machine, reducer, schema, type shape), inline it within the relevant decision and note briefly that it came from a prototype. Trim to the decision-rich parts — not a working demo, just the important bits.
|
|
57
|
+
|
|
58
|
+
## Testing Decisions
|
|
59
|
+
|
|
60
|
+
A list of testing decisions that were made. Include:
|
|
61
|
+
|
|
62
|
+
- A description of what makes a good test (only test external behavior, not implementation details)
|
|
63
|
+
- Which modules will be tested
|
|
64
|
+
- Prior art for the tests (i.e. similar types of tests in the codebase)
|
|
65
|
+
|
|
66
|
+
## Out of Scope
|
|
67
|
+
|
|
68
|
+
A description of the things that are out of scope for this PRD.
|
|
69
|
+
|
|
70
|
+
## Further Notes
|
|
71
|
+
|
|
72
|
+
Any further notes about the feature.
|
|
73
|
+
|
|
74
|
+
</prd-template>
|