@unifan/pi-unifan-zh 1.0.0

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.
Files changed (42) hide show
  1. package/README.md +111 -0
  2. package/extensions/review/CHANGELOG.md +540 -0
  3. package/extensions/review/LICENSE +15 -0
  4. package/extensions/review/README.md +55 -0
  5. package/extensions/review/agents/bugbot.md +46 -0
  6. package/extensions/review/agents/claude-md-compliance.md +46 -0
  7. package/extensions/review/agents/code-comments.md +43 -0
  8. package/extensions/review/agents/conventions.md +41 -0
  9. package/extensions/review/agents/gate.md +70 -0
  10. package/extensions/review/agents/history-context.md +45 -0
  11. package/extensions/review/agents/lite-review.md +51 -0
  12. package/extensions/review/agents/security-review.md +45 -0
  13. package/extensions/review/index.ts +205 -0
  14. package/extensions/review/package.json +38 -0
  15. package/extensions/review/reference/README.md +20 -0
  16. package/extensions/review/reference/claude-code-review.md +133 -0
  17. package/extensions/review/reference/cursor-review-skills.md +72 -0
  18. package/extensions/review/reference/pi-review-roadmap.md +183 -0
  19. package/extensions/review/reference/structured-output.md +26 -0
  20. package/extensions/review/reference/v0.2-plan.md +268 -0
  21. package/extensions/review/src/cli-args.ts +105 -0
  22. package/extensions/review/src/config.ts +340 -0
  23. package/extensions/review/src/directive.ts +481 -0
  24. package/extensions/review/src/gate-enforce.ts +151 -0
  25. package/extensions/review/src/lean-agents.ts +105 -0
  26. package/extensions/review/src/pr-ref.ts +39 -0
  27. package/extensions/review/src/report-tool.ts +394 -0
  28. package/extensions/review/src/report.ts +399 -0
  29. package/extensions/review/src/review-report.ts +279 -0
  30. package/extensions/review/src/review-run.ts +568 -0
  31. package/extensions/review/src/target-workspace.ts +239 -0
  32. package/extensions/review/src/tool-wrapper.ts +75 -0
  33. package/extensions/review/src/tui-renderer.ts +92 -0
  34. package/extensions/review/src/types.ts +207 -0
  35. package/extensions/review/src/workflow-schemas.ts +172 -0
  36. package/extensions/sessions/README.md +41 -0
  37. package/extensions/sessions/index.ts +862 -0
  38. package/extensions/sessions/package.json +21 -0
  39. package/extensions/sessions/sessions.ts +264 -0
  40. package/package.json +36 -0
  41. package/skills/README.md +29 -0
  42. package/tsconfig.json +14 -0
@@ -0,0 +1,268 @@
1
+ # v0.2.0 implementation plan
2
+
3
+ > **Goal:** Skills MVP — user runs `/review` locally and gets a Claude-shaped pipeline report.
4
+ > **Baseline:** v0.1.0 (core libs + tests; no `index.ts`, no E2E).
5
+ > **Design refs:** [pi-review-roadmap.md](./pi-review-roadmap.md), [claude-code-review.md](./claude-code-review.md)
6
+
7
+ Target release: `@georgedong32/pi-review@0.2.0`
8
+
9
+ ---
10
+
11
+ ## Goals
12
+
13
+ - [x] Extension loads via `pi -e .` and registers `/review`, `/review-config`, `/review-agents`
14
+ - [x] `/review` runs full pipeline: **eligibility → prep → reviewers → gate → report**
15
+ - [x] Five default content reviewers with bundled prompts wired as system prompts
16
+ - [~] Subagent spawn + structured JSON capture works on real `pi` child processes (unit + args tests pass; live spawn E2E pending API key)
17
+ - [x] Default confidence threshold **8/10** (Claude 80/100 equivalent)
18
+ - [ ] Publish to npm
19
+
20
+ ## Non-goals (v0.2)
21
+
22
+ - GitHub / `gh` integration (`pr-context` reviewer)
23
+ - Per-issue Haiku scorers (`--score-per-issue`)
24
+ - `registerTool` / agent auto-invoke
25
+ - Worktree isolation, auto-fix, retry loops
26
+ - Custom TUI message renderer (collapsible sections)
27
+
28
+ ---
29
+
30
+ ## Task list
31
+
32
+ Status key: `[ ]` todo · `[~]` in progress · `[x]` done
33
+
34
+ ### Track A — Extension entry (P0)
35
+
36
+ | ID | Task | Depends | Status |
37
+ |----|------|---------|--------|
38
+ | A1 | Create `index.ts` — default export `ExtensionAPI` factory | — | [x] |
39
+ | A2 | Register `/review` command with arg string passthrough | A1 | [x] |
40
+ | A3 | Register `/review-config` — ensure config dir, open editor, re-validate on save | A1 | [x] |
41
+ | A4 | Register `/review-agents` — list reviewers with resolved model/thinking/tools | A1 | [x] |
42
+ | A5 | Implement `src/cli-args.ts` — parse flags + path/`@file` from `/review` args | A1 | [x] |
43
+ | A6 | Wire orchestration in `index.ts`: load config → eligibility → diff → prep → review → gate → output | A2, A5, B*, C*, D* | [x] |
44
+ | A7 | Output: `renderReport` via `pi.sendMessage` (assistant-visible markdown) | A6 | [x] |
45
+ | A8 | Output: `pi.appendEntry("pi-review", report)` machine-readable payload | A6 | [x] |
46
+ | A9 | Long-run UX: `ctx.ui.setStatus("pi-review", …)` during spawn phases | A6 | [x] |
47
+ | A10 | Add `index.ts` to `package.json` `files`; verify `tsc` includes it | A1 | [x] |
48
+
49
+ **A3 notes:** Prefer `ctx.ui.editor()` with JSON text for in-TUI edit; fall back to `pi.exec($EDITOR, [configPath])` when `ctx.hasUI` and editor env set.
50
+
51
+ **A5 flags to parse:**
52
+
53
+ ```text
54
+ --threshold N
55
+ --reviewer <id> (repeatable)
56
+ --no-gate
57
+ --gate-model <id>
58
+ --no-spawn
59
+ [path | @path]
60
+ ```
61
+
62
+ ---
63
+
64
+ ### Track B — Structured output / spawn (P0)
65
+
66
+ | ID | Task | Depends | Status |
67
+ |----|------|---------|--------|
68
+ | B1 | Add `src/structured-output-capture.ts` — minimal pi extension: register `structured_output` tool; read schema from env; write capture file; `terminate: true` | — | [x] |
69
+ | B2 | Document env contract in `reference/structured-output.md` (or inline in spawn.ts header) | B1 | [x] |
70
+ | B3 | Update `src/args.ts` — append `-e <capture-ext>` to child args (resolve path via `import.meta.url`) | B1 | [x] |
71
+ | B4 | Verify child still uses `--no-session --no-extensions --no-skills` **except** capture extension | B3 | [x] |
72
+ | B5 | Manual E2E: one reviewer spawn writes valid `output.json` | B3, C2 | [ ] |
73
+ | B6 | Integration test with fake spawn (existing pattern) updated for `-e` arg | B3 | [x] |
74
+
75
+ **B1 contract (unchanged env vars):**
76
+
77
+ - `PI_SUBAGENT_STRUCTURED_OUTPUT_SCHEMA` → JSON Schema file path
78
+ - `PI_SUBAGENT_STRUCTURED_OUTPUT_CAPTURE` → output JSON path
79
+
80
+ ---
81
+
82
+ ### Track C — Pipeline phases (P0–P1)
83
+
84
+ | ID | Task | Depends | Status |
85
+ |----|------|---------|--------|
86
+ | C1 | Add `src/eligibility.ts` — `checkEligibility(input): { ok, reason? }` | — | [x] |
87
+ | C2 | Eligibility rules: empty diff → skip; non-git without path → skip; optional trivial diff heuristic | C1 | [x] |
88
+ | C3 | Add `tests/eligibility.test.ts` | C1 | [x] |
89
+ | C4 | Add `src/prep.ts` — `prepareContext(cwd, diff): { rulePaths, summary }` | — | [x] |
90
+ | C5 | Rule discovery: `AGENTS.md`, `CLAUDE.md`, `.pi/rules`, `.pi/conventions.md` (paths only, like Claude step 2) | C4 | [x] |
91
+ | C6 | Diff summary: first N lines / hunk count / files touched (sync, no LLM required for v0.2) | C4 | [x] |
92
+ | C7 | Inject prep block into reviewer task preamble in `review.ts` | C4, D6 | [x] |
93
+ | C8 | Add `tests/prep.test.ts` | C4 | [x] |
94
+ | C9 | Light re-check before render: diff still non-empty (Claude phase 6 lite) | C1, A6 | [x] |
95
+
96
+ **Trivial diff heuristic (v0.2):** only lockfile / only formatting-only / &lt; 3 lines — configurable `skipTrivial: true` in config later; hardcode simple rules OK for v0.2.
97
+
98
+ ---
99
+
100
+ ### Track D — Reviewers & prompts (P1)
101
+
102
+ | ID | Task | Depends | Status |
103
+ |----|------|---------|--------|
104
+ | D1 | Add `src/paths.ts` — `packageRoot()` via `import.meta.url` | — | [x] |
105
+ | D2 | `resolveAgentPrompt(id)` → `agents/<id>.md` (strip YAML frontmatter body for system prompt) | D1 | [x] |
106
+ | D3 | `resolveGatePrompt()` → `prompts/gate.md` | D1 | [x] |
107
+ | D4 | Refactor `review.ts`: use bundled agent md as `--system-prompt`; task = prep + diff | D2, C7 | [x] |
108
+ | D5 | Refactor `gate.ts`: use `prompts/gate.md` as gate system prompt | D3 | [x] |
109
+ | D6 | Rename `agents/bug-detector.md` → `agents/bugbot.md`; update id in config defaults | — | [x] |
110
+ | D7 | Tighten `bugbot.md` prompt per [cursor-review-skills.md](./cursor-review-skills.md) | D6 | [x] |
111
+ | D8 | Add `agents/security-review.md` | — | [x] |
112
+ | D9 | Add `agents/code-comments.md` (Claude agent #5) | — | [x] |
113
+ | D10 | Update `src/config.ts` `DEFAULT_CONFIG.reviewers` roster (5 enabled, conventions disabled) | D6–D9 | [x] |
114
+ | D11 | Update `prompts/gate.md` — embed Claude 0–100 rubric mapped to 1–10; re-score not just filter | D5 | [x] |
115
+ | D12 | Change default `gate.threshold` from 3 → **8** in config + README | D10 | [x] |
116
+ | D13 | Keep `agents/conventions.md`; `enabled: false` in defaults | D10 | [x] |
117
+
118
+ **Default enabled reviewers (v0.2):**
119
+
120
+ 1. `claude-md-compliance`
121
+ 2. `bugbot`
122
+ 3. `history-context`
123
+ 4. `security-review`
124
+ 5. `code-comments`
125
+
126
+ ---
127
+
128
+ ### Track E — Types, schema, report (P1)
129
+
130
+ | ID | Task | Depends | Status |
131
+ |----|------|---------|--------|
132
+ | E1 | Extend `ResolvedInput` / report if needed for prep metadata (`rulePaths`, `summary`) | C4 | [x] |
133
+ | E2 | `buildReport` — handle eligibility skip / no high-confidence issues messaging | A6 | [x] |
134
+ | E3 | `renderReport` — “No high-confidence issues” path (Claude: no comment posted) | E2 | [x] |
135
+ | E4 | Update `tests/report.test.ts` for new messages | E3 | [x] |
136
+ | E5 | Update `tests/config.test.ts` for new defaults + bugbot id | D10 | [x] |
137
+
138
+ ---
139
+
140
+ ### Track F — Tests & docs (P1)
141
+
142
+ | ID | Task | Depends | Status |
143
+ |----|------|---------|--------|
144
+ | F1 | Add `tests/cli-args.test.ts` | A5 | [x] |
145
+ | F2 | Update `tests/args.test.ts` if child argv shape changes (`-e`) | B3 | [x] |
146
+ | F3 | Update `tests/review.test.ts` for bundled prompt resolution (mock fs or inject paths) | D4 | [x] |
147
+ | F4 | Update README — pipeline diagram, 5 reviewers, threshold 8, reference links | * | [x] |
148
+ | F5 | CHANGELOG `[0.2.0]` section | * | [x] |
149
+ | F6 | Bump `package.json` version → `0.2.0` | * | [x] |
150
+ | F7 | `bun test` + `bun run check` green | * | [x] |
151
+
152
+ ---
153
+
154
+ ### Track G — Release (P1)
155
+
156
+ | ID | Task | Depends | Status |
157
+ |----|------|---------|--------|
158
+ | G1 | Manual smoke: `pi -e .` → `/review` on dirty repo | A6, B5 | [ ] |
159
+ | G2 | Manual smoke: `/review --no-gate`, `--reviewer bugbot`, `--no-spawn` | A5, A6 | [ ] |
160
+ | G3 | Manual smoke: `/review-config` round-trip | A3 | [ ] |
161
+ | G4 | `npm publish` (user-triggered) | G1–G3, F7 | [ ] |
162
+
163
+ ---
164
+
165
+ ## Suggested implementation order
166
+
167
+ ```text
168
+ Week 1 — unblock E2E
169
+ D1 → B1 → B3 → D2/D3 → D4/D5 → A1 → A5 → C1/C4 → A6 (no-gate path first)
170
+
171
+ Week 2 — full pipeline
172
+ D6–D13 → C7 → D11/D12 → A7/A8/A9 → A3/A4 → tests (F*) → docs (F4/F5)
173
+
174
+ Week 3 — polish & release
175
+ C2/C9 trivial + re-check → G* smoke → version bump → publish
176
+ ```
177
+
178
+ **Critical path:** `B1 → B3 → D4 → A6 → G1`
179
+
180
+ ---
181
+
182
+ ## Acceptance criteria (release gate)
183
+
184
+ 1. **Load:** `pi -e /path/to/pi-review` lists `/review` in commands.
185
+ 2. **Happy path:** Dirty git repo → `/review` → markdown report with verdict + per-reviewer sections + gate section.
186
+ 3. **Empty:** Clean repo, no commits ahead → eligibility message, no spawn storm.
187
+ 4. **Filter:** Reviewer returns low-confidence issue → gate drops it; report says no high-confidence issues if all dropped.
188
+ 5. **Flags:** `--no-gate` shows raw reviewer JSON sections; `--no-spawn` prints resolved plan; `--reviewer bugbot` runs one agent.
189
+ 6. **Config:** `/review-config` edit + save → `/review-agents` reflects changes.
190
+ 7. **CI:** `bun test` (≥ current count, new tests for eligibility/cli-args/prep) + `tsc --noEmit` pass.
191
+
192
+ ---
193
+
194
+ ## File manifest (expected diff)
195
+
196
+ ### New files
197
+
198
+ ```text
199
+ index.ts
200
+ src/cli-args.ts
201
+ src/eligibility.ts
202
+ src/prep.ts
203
+ src/paths.ts
204
+ src/structured-output-capture.ts
205
+ agents/bugbot.md (from bug-detector)
206
+ agents/security-review.md
207
+ agents/code-comments.md
208
+ tests/cli-args.test.ts
209
+ tests/eligibility.test.ts
210
+ tests/prep.test.ts
211
+ reference/v0.2-plan.md (this file)
212
+ ```
213
+
214
+ ### Modified files
215
+
216
+ ```text
217
+ src/review.ts
218
+ src/gate.ts
219
+ src/args.ts
220
+ src/config.ts
221
+ src/report.ts
222
+ src/types.ts (if prep metadata)
223
+ prompts/gate.md
224
+ README.md
225
+ CHANGELOG.md
226
+ package.json
227
+ reference/README.md
228
+ tests/args.test.ts
229
+ tests/config.test.ts
230
+ tests/report.test.ts
231
+ tests/review.test.ts
232
+ ```
233
+
234
+ ### Removed / renamed
235
+
236
+ ```text
237
+ agents/bug-detector.md → agents/bugbot.md
238
+ ```
239
+
240
+ ---
241
+
242
+ ## Risk register
243
+
244
+ | Risk | Mitigation |
245
+ |------|------------|
246
+ | Stock `pi` rejects `-e` with `--no-extensions` | B4: confirm CLI allows single extension override; else use minimal inline prompt + `--tools` only |
247
+ | Long diff exceeds argv limits | Pass `@file` temp path for task text (already noted in args.ts) |
248
+ | 5 reviewers × spawn cost | Document expected latency; `--reviewer` subset; concurrency cap 4 |
249
+ | Gate re-score drift vs per-issue scorers | Document in reference; v0.3 adds `--score-per-issue` |
250
+
251
+ ---
252
+
253
+ ## Progress summary
254
+
255
+ | Track | Tasks | Done |
256
+ |-------|-------|------|
257
+ | A Extension | 10 | 10 |
258
+ | B Spawn | 6 | 5 |
259
+ | C Pipeline | 9 | 9 |
260
+ | D Reviewers | 13 | 13 |
261
+ | E Types/report | 5 | 5 |
262
+ | F Tests/docs | 7 | 7 |
263
+ | G Release | 4 | 0 |
264
+ | **Total** | **54** | **49** |
265
+
266
+ **Remaining:** B5 live spawn E2E; G1–G3 manual `pi` smoke; G4 `npm publish` (user-triggered).
267
+
268
+ Update the **Progress summary** table as tasks complete.
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Parse `/review` command arguments.
3
+ *
4
+ * Surface is intentionally minimal:
5
+ * - `--lite` fast single-agent review (no fan-out, no gate)
6
+ * - `--no-spawn` hidden dry-run (prints the resolved plan, no subprocess)
7
+ * - trailing freeform text → user review request (focus / requirements /
8
+ * PR url / context), injected into reviewers and gate via target.userContext
9
+ * (see src/prep.ts and src/git-input.ts)
10
+ *
11
+ * Removed flags (--threshold / --reviewer / --score-per-issue / --diff) are
12
+ * accepted-but-ignored for graceful degradation of old invocations: a valued
13
+ * legacy flag also consumes its next token so its value does not leak into
14
+ * `input`. Those capabilities now live in config.json (`/review-config`).
15
+ * `--gate-model <id>` remains an active per-run override.
16
+ */
17
+
18
+ export interface ParsedReviewArgs {
19
+ /** Freeform user request: review focus, PR url, or context. */
20
+ input?: string;
21
+ /** Dry-run: print resolved plan without spawning. */
22
+ noSpawn: boolean;
23
+ /** Single-agent fast mode: one reviewer, no gate. */
24
+ lite: boolean;
25
+ /** Override the gate model for this run (otherwise config.gate.model). */
26
+ gateModel?: string;
27
+ }
28
+
29
+ /** Removed valued flags — silently skip flag + value to keep input clean. */
30
+ const LEGACY_VALUED_FLAGS = new Set([
31
+ "--threshold",
32
+ "--reviewer",
33
+ "--score-per-issue",
34
+ "--diff",
35
+ ]);
36
+
37
+ export function parseReviewArgs(raw: string): ParsedReviewArgs {
38
+ const tokens = tokenize(raw);
39
+ const result: ParsedReviewArgs = { noSpawn: false, lite: false };
40
+ const inputParts: string[] = [];
41
+
42
+ for (let i = 0; i < tokens.length; i++) {
43
+ const t = tokens[i];
44
+ if (LEGACY_VALUED_FLAGS.has(t)) {
45
+ i++; // consume the value too
46
+ continue;
47
+ }
48
+ if (t === "--no-spawn") {
49
+ result.noSpawn = true;
50
+ continue;
51
+ }
52
+ if (t === "--lite") {
53
+ result.lite = true;
54
+ continue;
55
+ }
56
+ if (t === "--gate-model") {
57
+ const id = tokens[++i];
58
+ if (id) result.gateModel = id;
59
+ continue;
60
+ }
61
+ if (t.startsWith("-")) {
62
+ continue; // ignore other legacy / unknown flags
63
+ }
64
+ inputParts.push(t);
65
+ }
66
+
67
+ const input = inputParts.join(" ").trim();
68
+ if (input.length > 0) {
69
+ result.input = input;
70
+ }
71
+
72
+ return result;
73
+ }
74
+
75
+ /** Split on whitespace preserving quoted segments. */
76
+ function tokenize(raw: string): string[] {
77
+ const out: string[] = [];
78
+ let cur = "";
79
+ let quote: "'" | '"' | null = null;
80
+ for (let i = 0; i < raw.length; i++) {
81
+ const c = raw[i];
82
+ if (quote) {
83
+ if (c === quote) {
84
+ quote = null;
85
+ } else {
86
+ cur += c;
87
+ }
88
+ continue;
89
+ }
90
+ if (c === "'" || c === '"') {
91
+ quote = c;
92
+ continue;
93
+ }
94
+ if (/\s/.test(c)) {
95
+ if (cur.length > 0) {
96
+ out.push(cur);
97
+ cur = "";
98
+ }
99
+ continue;
100
+ }
101
+ cur += c;
102
+ }
103
+ if (cur.length > 0) out.push(cur);
104
+ return out;
105
+ }