@plaited/acp-harness 0.2.6 → 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/LICENSE +1 -1
- package/README.md +120 -16
- package/bin/cli.ts +105 -636
- package/bin/tests/cli.spec.ts +218 -51
- package/package.json +20 -4
- package/src/acp-client.ts +5 -4
- package/src/acp-transport.ts +14 -7
- package/src/adapter-check.ts +542 -0
- package/src/adapter-scaffold.ts +934 -0
- package/src/balance.ts +232 -0
- package/src/calibrate.ts +300 -0
- package/src/capture.ts +457 -0
- package/src/constants.ts +94 -0
- package/src/grader-loader.ts +174 -0
- package/src/harness.ts +35 -0
- package/src/schemas-cli.ts +239 -0
- package/src/schemas.ts +567 -0
- package/src/summarize.ts +245 -0
- package/src/tests/adapter-check.spec.ts +70 -0
- package/src/tests/adapter-scaffold.spec.ts +112 -0
- package/src/tests/fixtures/grader-bad-module.ts +5 -0
- package/src/tests/fixtures/grader-exec-fail.py +9 -0
- package/src/tests/fixtures/grader-exec-invalid.py +6 -0
- package/src/tests/fixtures/grader-exec.py +29 -0
- package/src/tests/fixtures/grader-module.ts +14 -0
- package/src/tests/grader-loader.spec.ts +153 -0
- package/src/trials.ts +395 -0
- package/src/validate-refs.ts +188 -0
- package/.claude/rules/accuracy.md +0 -43
- package/.claude/rules/bun-apis.md +0 -80
- package/.claude/rules/code-review.md +0 -254
- package/.claude/rules/git-workflow.md +0 -37
- package/.claude/rules/github.md +0 -154
- package/.claude/rules/testing.md +0 -172
- package/.claude/skills/acp-harness/SKILL.md +0 -310
- package/.claude/skills/acp-harness/assets/Dockerfile.acp +0 -25
- package/.claude/skills/acp-harness/assets/docker-compose.acp.yml +0 -19
- package/.claude/skills/acp-harness/references/downstream.md +0 -288
- package/.claude/skills/acp-harness/references/output-formats.md +0 -221
- package/.claude-plugin/marketplace.json +0 -15
- package/.claude-plugin/plugin.json +0 -16
- package/.github/CODEOWNERS +0 -6
- package/.github/workflows/ci.yml +0 -63
- package/.github/workflows/publish.yml +0 -146
- package/.mcp.json +0 -20
- package/CLAUDE.md +0 -92
- package/Dockerfile.test +0 -23
- package/biome.json +0 -96
- package/bun.lock +0 -513
- package/docker-compose.test.yml +0 -21
- package/scripts/bun-test-wrapper.sh +0 -46
- package/src/acp.constants.ts +0 -56
- package/src/acp.schemas.ts +0 -161
- package/src/acp.types.ts +0 -28
- package/src/tests/fixtures/.claude/settings.local.json +0 -8
- package/src/tests/fixtures/.claude/skills/greeting/SKILL.md +0 -17
- package/tsconfig.json +0 -32
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
# Code Review Standards
|
|
2
|
-
|
|
3
|
-
The following standards are not automatically enforced by Biome but should be checked during code review.
|
|
4
|
-
|
|
5
|
-
## Automated Validation
|
|
6
|
-
|
|
7
|
-
Before completing a code review, run these validation scripts:
|
|
8
|
-
|
|
9
|
-
### Plugin Skills Validation
|
|
10
|
-
|
|
11
|
-
When changes touch `.claude/skills/`, validate against the AgentSkills spec by running:
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
/validate-skill
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
This checks:
|
|
18
|
-
- SKILL.md exists and has required frontmatter
|
|
19
|
-
- Scripts have proper structure
|
|
20
|
-
- References are valid markdown files
|
|
21
|
-
|
|
22
|
-
## TypeScript Style Conventions
|
|
23
|
-
|
|
24
|
-
### Prefer `type` Over `interface`
|
|
25
|
-
|
|
26
|
-
Use type aliases instead of interfaces for better consistency and flexibility:
|
|
27
|
-
|
|
28
|
-
```typescript
|
|
29
|
-
// ✅ Good
|
|
30
|
-
type User = {
|
|
31
|
-
name: string
|
|
32
|
-
email: string
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// ❌ Avoid
|
|
36
|
-
interface User {
|
|
37
|
-
name: string
|
|
38
|
-
email: string
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
**Rationale:** Type aliases are more flexible (unions, intersections, mapped types) and provide consistent syntax across the codebase.
|
|
43
|
-
|
|
44
|
-
### No `any` Types
|
|
45
|
-
|
|
46
|
-
Always use proper types; use `unknown` if type is truly unknown and add type guards:
|
|
47
|
-
|
|
48
|
-
```typescript
|
|
49
|
-
// ✅ Good
|
|
50
|
-
const process = (data: unknown) => {
|
|
51
|
-
if (typeof data === 'string') {
|
|
52
|
-
return data.toUpperCase()
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// ❌ Avoid
|
|
57
|
-
const process = (data: any) => {
|
|
58
|
-
return data.toUpperCase()
|
|
59
|
-
}
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### PascalCase for Types and Schemas
|
|
63
|
-
|
|
64
|
-
All type names use PascalCase. Zod schema names use `PascalCaseSchema` suffix:
|
|
65
|
-
|
|
66
|
-
```typescript
|
|
67
|
-
// ✅ Good
|
|
68
|
-
type UserConfig = { /* ... */ }
|
|
69
|
-
const UserConfigSchema = z.object({ /* ... */ })
|
|
70
|
-
|
|
71
|
-
// ❌ Avoid
|
|
72
|
-
type userConfig = { /* ... */ }
|
|
73
|
-
const zUserConfig = z.object({ /* ... */ }) // Don't use z-prefix
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### Arrow Functions Preferred
|
|
77
|
-
|
|
78
|
-
```typescript
|
|
79
|
-
// ✅ Good
|
|
80
|
-
const greet = (name: string) => `Hello, ${name}!`
|
|
81
|
-
|
|
82
|
-
// ❌ Avoid
|
|
83
|
-
function greet(name: string) {
|
|
84
|
-
return `Hello, ${name}!`
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Object Parameter Pattern
|
|
89
|
-
|
|
90
|
-
For functions with more than two parameters, use a single object parameter:
|
|
91
|
-
|
|
92
|
-
```typescript
|
|
93
|
-
// ✅ Good: Object parameter pattern
|
|
94
|
-
const createClient = ({
|
|
95
|
-
command,
|
|
96
|
-
timeout,
|
|
97
|
-
cwd,
|
|
98
|
-
}: {
|
|
99
|
-
command: string[]
|
|
100
|
-
timeout: number
|
|
101
|
-
cwd?: string
|
|
102
|
-
}): ACPClient => { /* ... */ }
|
|
103
|
-
|
|
104
|
-
// ❌ Avoid: Multiple positional parameters
|
|
105
|
-
const createClient = (
|
|
106
|
-
command: string[],
|
|
107
|
-
timeout: number,
|
|
108
|
-
cwd?: string
|
|
109
|
-
): ACPClient => { /* ... */ }
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
## TypeScript Comment Directives
|
|
113
|
-
|
|
114
|
-
### `@ts-ignore` Requires Description
|
|
115
|
-
|
|
116
|
-
- When using `@ts-ignore`, always include a description explaining why the type error is being suppressed
|
|
117
|
-
- This helps future maintainers understand the reasoning
|
|
118
|
-
- Example:
|
|
119
|
-
```typescript
|
|
120
|
-
// @ts-ignore - TypeScript incorrectly infers this as string when it's actually a number from the API
|
|
121
|
-
const value = response.data
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
**Rationale:** Lost TypeScript-ESLint rule `ban-ts-comment` with `allow-with-description` option during Biome migration
|
|
125
|
-
|
|
126
|
-
## Expression Statements
|
|
127
|
-
|
|
128
|
-
### Allow Short-Circuit and Ternary Expressions
|
|
129
|
-
|
|
130
|
-
- Short-circuit evaluation is acceptable: `condition && doSomething()`
|
|
131
|
-
- Ternary expressions are acceptable: `condition ? doThis() : doThat()`
|
|
132
|
-
- These patterns are idiomatic and improve code readability
|
|
133
|
-
|
|
134
|
-
**Rationale:** Lost TypeScript-ESLint rule `no-unused-expressions` with `allowShortCircuit` and `allowTernary` options during Biome migration
|
|
135
|
-
|
|
136
|
-
## Empty Object Types
|
|
137
|
-
|
|
138
|
-
### Allow Empty Object Types When Extending a Single Interface
|
|
139
|
-
|
|
140
|
-
- Empty object types are acceptable when they extend exactly one other interface
|
|
141
|
-
- This pattern is useful for creating branded types or extending third-party interfaces
|
|
142
|
-
- Example:
|
|
143
|
-
```typescript
|
|
144
|
-
// ✅ Acceptable: Extends single interface
|
|
145
|
-
interface CustomElement extends HTMLElement {}
|
|
146
|
-
|
|
147
|
-
// ❌ Avoid: Empty with no extends or multiple extends
|
|
148
|
-
interface Empty {}
|
|
149
|
-
interface Multi extends Foo, Bar {}
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
**Rationale:** Lost TypeScript-ESLint rule `no-empty-object-type` with `allowInterfaces: 'with-single-extends'` option during Biome migration
|
|
153
|
-
|
|
154
|
-
## Modern JavaScript Standards
|
|
155
|
-
|
|
156
|
-
### Prefer Private Fields Over `private` Keyword
|
|
157
|
-
|
|
158
|
-
Use JavaScript private fields (`#field`) instead of TypeScript's `private` keyword:
|
|
159
|
-
|
|
160
|
-
```typescript
|
|
161
|
-
// ✅ Good: JavaScript private fields (ES2022+)
|
|
162
|
-
class EventBus {
|
|
163
|
-
#listeners = new Map<string, Set<Function>>()
|
|
164
|
-
#count = 0
|
|
165
|
-
|
|
166
|
-
#emit(event: string) {
|
|
167
|
-
this.#count++
|
|
168
|
-
this.#listeners.get(event)?.forEach(fn => fn())
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// ❌ Avoid: TypeScript private keyword
|
|
173
|
-
class EventBus {
|
|
174
|
-
private listeners = new Map<string, Set<Function>>()
|
|
175
|
-
private count = 0
|
|
176
|
-
|
|
177
|
-
private emit(event: string) {
|
|
178
|
-
this.count++
|
|
179
|
-
this.listeners.get(event)?.forEach(fn => fn())
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
**Rationale:** JavaScript private fields are a runtime feature (ES2022) providing true encapsulation. TypeScript's `private` is erased at compile time and can be bypassed. Prefer platform standards over TypeScript-only features
|
|
185
|
-
|
|
186
|
-
### JSON Import Attributes
|
|
187
|
-
|
|
188
|
-
Use import attributes when importing JSON files. This is required because the tsconfig uses `verbatimModuleSyntax: true` without `resolveJsonModule`:
|
|
189
|
-
|
|
190
|
-
```typescript
|
|
191
|
-
// ✅ Good: Import attribute for JSON
|
|
192
|
-
import { version } from '../package.json' with { type: 'json' }
|
|
193
|
-
import config from './config.json' with { type: 'json' }
|
|
194
|
-
|
|
195
|
-
// ❌ Avoid: Missing import attribute
|
|
196
|
-
import { version } from '../package.json'
|
|
197
|
-
import config from './config.json'
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
**Rationale:** Import attributes (ES2025) explicitly declare module types to the runtime. The `with { type: 'json' }` syntax is the standard (replacing the deprecated `assert` keyword). This provides runtime enforcement—if the file isn't valid JSON, the import fails.
|
|
201
|
-
|
|
202
|
-
## Module Organization
|
|
203
|
-
|
|
204
|
-
Organize module exports into separate files by category:
|
|
205
|
-
|
|
206
|
-
```
|
|
207
|
-
module/
|
|
208
|
-
├── module.types.ts # Type definitions only
|
|
209
|
-
├── module.schemas.ts # Zod schemas and schema-inferred types
|
|
210
|
-
├── module.constants.ts # Constants and enum-like objects
|
|
211
|
-
├── module-client.ts # Implementation
|
|
212
|
-
└── index.ts # Public API exports (barrel file)
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### Key Principles
|
|
216
|
-
|
|
217
|
-
- **Types file**: Contains only type definitions, does NOT re-export from sibling files
|
|
218
|
-
- **Schemas file**: Contains Zod schemas and their inferred types, does NOT export constants
|
|
219
|
-
- **Constants file**: Contains all constant values (error codes, method names, defaults)
|
|
220
|
-
- **Barrel file**: Uses wildcard exports; non-public files are simply not included
|
|
221
|
-
|
|
222
|
-
```typescript
|
|
223
|
-
// ✅ Good: Direct imports from specific files
|
|
224
|
-
import type { Config } from './module.types.ts'
|
|
225
|
-
import { ConfigSchema } from './module.schemas.ts'
|
|
226
|
-
import { METHODS, ERROR_CODES } from './module.constants.ts'
|
|
227
|
-
|
|
228
|
-
// ❌ Avoid: Expecting types file to re-export everything
|
|
229
|
-
import { Config, ConfigSchema, METHODS } from './module.types.ts'
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
**Rationale:** Prevents circular dependencies, makes dependencies explicit, improves tree-shaking.
|
|
233
|
-
|
|
234
|
-
## Documentation Standards
|
|
235
|
-
|
|
236
|
-
### Mermaid Diagrams Only
|
|
237
|
-
|
|
238
|
-
Use [mermaid](https://mermaid.js.org/) syntax for all diagrams in markdown files:
|
|
239
|
-
|
|
240
|
-
```markdown
|
|
241
|
-
\```mermaid
|
|
242
|
-
flowchart TD
|
|
243
|
-
A[Start] --> B[Process]
|
|
244
|
-
B --> C[End]
|
|
245
|
-
\```
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
**Avoid**: ASCII box-drawing characters (`┌`, `│`, `└`, `─`, etc.)
|
|
249
|
-
|
|
250
|
-
**Rationale:** Token efficiency, clearer semantic meaning, easier maintenance.
|
|
251
|
-
|
|
252
|
-
### No `@example` Sections in TSDoc
|
|
253
|
-
|
|
254
|
-
Tests serve as living examples. Do not add `@example` sections to TSDoc comments.
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# Git Workflow
|
|
2
|
-
|
|
3
|
-
## Commit Message Format
|
|
4
|
-
|
|
5
|
-
When creating commits with multi-line messages, use single-quoted strings instead of heredocs. The sandbox environment restricts temp file creation needed for heredocs.
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
# ✅ CORRECT: Single-quoted multi-line string
|
|
9
|
-
git commit -m 'refactor: description here
|
|
10
|
-
|
|
11
|
-
Additional context on second line.
|
|
12
|
-
|
|
13
|
-
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
|
14
|
-
|
|
15
|
-
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>'
|
|
16
|
-
|
|
17
|
-
# ❌ WRONG: Heredoc syntax (fails in sandbox)
|
|
18
|
-
git commit -m "$(cat <<'EOF'
|
|
19
|
-
refactor: description here
|
|
20
|
-
EOF
|
|
21
|
-
)"
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
The heredoc approach fails with:
|
|
25
|
-
```
|
|
26
|
-
(eval):1: can't create temp file for here document: operation not permitted
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Commit Conventions
|
|
30
|
-
|
|
31
|
-
This project follows conventional commits:
|
|
32
|
-
- `feat:` - New features
|
|
33
|
-
- `fix:` - Bug fixes
|
|
34
|
-
- `refactor:` - Code changes that neither fix bugs nor add features
|
|
35
|
-
- `docs:` - Documentation only changes
|
|
36
|
-
- `chore:` - Maintenance tasks
|
|
37
|
-
- `test:` - Adding or updating tests
|
package/.claude/rules/github.md
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
# GitHub Integration
|
|
2
|
-
|
|
3
|
-
## Prefer GitHub CLI Over Web Fetch
|
|
4
|
-
|
|
5
|
-
When given GitHub URLs (PRs, issues, repos), use the `gh` CLI instead of WebFetch for more reliable and complete data access.
|
|
6
|
-
|
|
7
|
-
### PR Information
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
# Get PR details with comments and reviews (comprehensive)
|
|
11
|
-
gh pr view <number> --repo <owner>/<repo> --json title,body,comments,reviews,reviewRequests,state,author,additions,deletions,changedFiles
|
|
12
|
-
|
|
13
|
-
# Get PR diff
|
|
14
|
-
gh pr diff <number> --repo <owner>/<repo>
|
|
15
|
-
|
|
16
|
-
# Get PR files changed
|
|
17
|
-
gh pr view <number> --repo <owner>/<repo> --json files
|
|
18
|
-
|
|
19
|
-
# Get PR checks status
|
|
20
|
-
gh pr checks <number> --repo <owner>/<repo>
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
### Complete PR Evaluation Workflow
|
|
24
|
-
|
|
25
|
-
When asked to evaluate PR feedback, you MUST fetch **all** feedback sources. Do not just fetch comments/reviews - also check security alerts and inline code comments.
|
|
26
|
-
|
|
27
|
-
**Step 1: Fetch PR comments and reviews**
|
|
28
|
-
```bash
|
|
29
|
-
gh pr view <number> --repo <owner>/<repo> --json title,body,comments,reviews,state
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
**Step 2: Fetch code scanning alerts (security vulnerabilities)**
|
|
33
|
-
```bash
|
|
34
|
-
gh api repos/<owner>/<repo>/code-scanning/alerts --jq '
|
|
35
|
-
.[] | select(.state == "open") | {
|
|
36
|
-
number: .number,
|
|
37
|
-
rule: .rule.description,
|
|
38
|
-
severity: .rule.severity,
|
|
39
|
-
file: .most_recent_instance.location.path,
|
|
40
|
-
line: .most_recent_instance.location.start_line
|
|
41
|
-
}
|
|
42
|
-
'
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
**Step 3: Fetch inline review comments (code quality, suggestions)**
|
|
46
|
-
```bash
|
|
47
|
-
gh api repos/<owner>/<repo>/pulls/<number>/comments --jq '
|
|
48
|
-
.[] | {
|
|
49
|
-
id: .id,
|
|
50
|
-
user: .user.login,
|
|
51
|
-
file: .path,
|
|
52
|
-
line: .line,
|
|
53
|
-
body: .body
|
|
54
|
-
}
|
|
55
|
-
'
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
**Step 4: Address ALL feedback**
|
|
59
|
-
Create a checklist and address each item:
|
|
60
|
-
- [ ] Human reviewer comments
|
|
61
|
-
- [ ] Claude Code review comments
|
|
62
|
-
- [ ] GitHub Advanced Security alerts (ReDoS, injection, etc.)
|
|
63
|
-
- [ ] GitHub Code Quality comments (dead code, useless assignments)
|
|
64
|
-
- [ ] Inline review suggestions
|
|
65
|
-
|
|
66
|
-
### Comment Sources
|
|
67
|
-
|
|
68
|
-
| Source | API/Location | Description |
|
|
69
|
-
|--------|--------------|-------------|
|
|
70
|
-
| Human reviewers | `gh pr view --json reviews` | Code owners, team members |
|
|
71
|
-
| Claude Code | `gh pr view --json comments` | AI-generated review (login: `claude`) |
|
|
72
|
-
| GitHub Advanced Security | `gh api .../code-scanning/alerts` | Security vulnerabilities (ReDoS, injection) |
|
|
73
|
-
| GitHub Code Quality | `gh api .../pulls/.../comments` | Code quality issues (login: `github-code-quality[bot]`) |
|
|
74
|
-
| Inline suggestions | `gh api .../pulls/.../comments` | Line-specific review comments |
|
|
75
|
-
|
|
76
|
-
### Filtering by Author
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
# Get all automated reviews from PR
|
|
80
|
-
gh pr view <number> --repo <owner>/<repo> --json reviews --jq '
|
|
81
|
-
.reviews[] | select(.author.login | test("github-|claude")) | {author: .author.login, state: .state}
|
|
82
|
-
'
|
|
83
|
-
|
|
84
|
-
# Get specific inline comment by ID
|
|
85
|
-
gh api repos/<owner>/<repo>/pulls/<number>/comments --jq '
|
|
86
|
-
.[] | select(.id == <comment_id>)
|
|
87
|
-
'
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### URL Patterns for Specific Feedback
|
|
91
|
-
|
|
92
|
-
| URL Pattern | How to Fetch |
|
|
93
|
-
|-------------|--------------|
|
|
94
|
-
| `.../pull/<n>#issuecomment-<id>` | `gh pr view <n> --json comments` |
|
|
95
|
-
| `.../pull/<n>#discussion_r<id>` | `gh api repos/.../pulls/<n>/comments` |
|
|
96
|
-
| `.../security/code-scanning/<id>` | `gh api repos/.../code-scanning/alerts/<id>` |
|
|
97
|
-
|
|
98
|
-
### Review States
|
|
99
|
-
- `APPROVED` - Reviewer approved changes
|
|
100
|
-
- `CHANGES_REQUESTED` - Reviewer requested changes
|
|
101
|
-
- `COMMENTED` - Review with comments only
|
|
102
|
-
- `PENDING` - Review not yet submitted
|
|
103
|
-
|
|
104
|
-
### Issue Information
|
|
105
|
-
|
|
106
|
-
```bash
|
|
107
|
-
# Get issue details
|
|
108
|
-
gh issue view <number> --repo <owner>/<repo> --json title,body,comments,state,author
|
|
109
|
-
|
|
110
|
-
# List issues
|
|
111
|
-
gh issue list --repo <owner>/<repo> --json number,title,state
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### Repository Information
|
|
115
|
-
|
|
116
|
-
```bash
|
|
117
|
-
# Get repo info
|
|
118
|
-
gh repo view <owner>/<repo> --json name,description,url
|
|
119
|
-
|
|
120
|
-
# List workflows
|
|
121
|
-
gh workflow list --repo <owner>/<repo>
|
|
122
|
-
|
|
123
|
-
# View run logs
|
|
124
|
-
gh run view <run-id> --repo <owner>/<repo> --log
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
### URL Parsing
|
|
128
|
-
|
|
129
|
-
When given a GitHub URL, extract the components:
|
|
130
|
-
|
|
131
|
-
| URL Pattern | Command |
|
|
132
|
-
|-------------|---------|
|
|
133
|
-
| `github.com/<owner>/<repo>/pull/<number>` | `gh pr view <number> --repo <owner>/<repo>` |
|
|
134
|
-
| `github.com/<owner>/<repo>/issues/<number>` | `gh issue view <number> --repo <owner>/<repo>` |
|
|
135
|
-
| `github.com/<owner>/<repo>` | `gh repo view <owner>/<repo>` |
|
|
136
|
-
| `github.com/<owner>/<repo>/actions/runs/<id>` | `gh run view <id> --repo <owner>/<repo>` |
|
|
137
|
-
|
|
138
|
-
### JSON Output Fields
|
|
139
|
-
|
|
140
|
-
Common useful JSON fields for PRs:
|
|
141
|
-
- `title`, `body`, `state`, `author`
|
|
142
|
-
- `comments` - PR comments
|
|
143
|
-
- `reviews` - Review comments and approvals
|
|
144
|
-
- `additions`, `deletions`, `changedFiles`
|
|
145
|
-
- `files` - List of changed files
|
|
146
|
-
- `commits` - Commit history
|
|
147
|
-
|
|
148
|
-
### Benefits Over WebFetch
|
|
149
|
-
|
|
150
|
-
1. **Complete data** - Access to all comments, reviews, and metadata
|
|
151
|
-
2. **Authentication** - Uses configured GitHub credentials
|
|
152
|
-
3. **Structured output** - JSON format for reliable parsing
|
|
153
|
-
4. **No rate limiting issues** - Authenticated requests have higher limits
|
|
154
|
-
5. **Access to private repos** - Works with repos you have access to
|
package/.claude/rules/testing.md
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
# Testing
|
|
2
|
-
|
|
3
|
-
This project uses Bun's built-in test runner for unit and integration tests.
|
|
4
|
-
|
|
5
|
-
## Test Types
|
|
6
|
-
|
|
7
|
-
### Unit/Integration Tests (`*.spec.ts`)
|
|
8
|
-
|
|
9
|
-
- Standard Bun tests using `*.spec.ts` extension
|
|
10
|
-
- Run with `bun test` command
|
|
11
|
-
- Used for testing business logic, utilities, and non-visual functionality
|
|
12
|
-
|
|
13
|
-
### Docker Integration Tests (`*.docker.ts`)
|
|
14
|
-
|
|
15
|
-
- Tests that require external services or API keys run in Docker containers
|
|
16
|
-
- Use `*.docker.ts` extension
|
|
17
|
-
- Run with `bun run test:docker`
|
|
18
|
-
|
|
19
|
-
## Running Tests
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
# Run all unit tests
|
|
23
|
-
bun test
|
|
24
|
-
|
|
25
|
-
# Run a specific spec test file
|
|
26
|
-
bun test path/to/file.spec.ts
|
|
27
|
-
|
|
28
|
-
# Run tests matching a pattern
|
|
29
|
-
bun test pattern
|
|
30
|
-
|
|
31
|
-
# Run Docker integration tests (requires ANTHROPIC_API_KEY)
|
|
32
|
-
ANTHROPIC_API_KEY=sk-... bun run test:docker
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Test Style Conventions
|
|
36
|
-
|
|
37
|
-
### Use `test` Instead of `it`
|
|
38
|
-
|
|
39
|
-
Use `test` instead of `it` in test files for consistency:
|
|
40
|
-
|
|
41
|
-
```typescript
|
|
42
|
-
// ✅ Good
|
|
43
|
-
test('should create ACP client correctly', () => {
|
|
44
|
-
// ...
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
// ❌ Avoid
|
|
48
|
-
it('should create ACP client correctly', () => {
|
|
49
|
-
// ...
|
|
50
|
-
})
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## Skill Script Tests
|
|
54
|
-
|
|
55
|
-
Claude Code skills in `.claude/skills/` may include executable scripts. Tests for these scripts follow a specific structure:
|
|
56
|
-
|
|
57
|
-
### Directory Structure
|
|
58
|
-
|
|
59
|
-
```
|
|
60
|
-
.claude/skills/<skill-name>/
|
|
61
|
-
├── SKILL.md
|
|
62
|
-
├── scripts/
|
|
63
|
-
│ ├── script-name.ts # Executable script
|
|
64
|
-
│ └── tests/
|
|
65
|
-
│ └── script-name.spec.ts # Tests for the script
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### Running Skill Script Tests
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
# From skill directory
|
|
72
|
-
bun test scripts/tests/
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### Test Pattern
|
|
76
|
-
|
|
77
|
-
Scripts that output JSON can be tested using Bun's shell API:
|
|
78
|
-
|
|
79
|
-
```typescript
|
|
80
|
-
import { describe, test, expect } from 'bun:test'
|
|
81
|
-
import { join } from 'node:path'
|
|
82
|
-
import { $ } from 'bun'
|
|
83
|
-
|
|
84
|
-
const scriptsDir = join(import.meta.dir, '..')
|
|
85
|
-
|
|
86
|
-
describe('script-name', () => {
|
|
87
|
-
test('outputs expected JSON', async () => {
|
|
88
|
-
const result = await $`bun ${scriptsDir}/script-name.ts arg1 arg2`.json()
|
|
89
|
-
expect(result.filePath).toEndWith('expected.ts')
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
test('exits with error on invalid input', async () => {
|
|
93
|
-
const proc = Bun.spawn(['bun', `${scriptsDir}/script-name.ts`], {
|
|
94
|
-
stderr: 'pipe',
|
|
95
|
-
})
|
|
96
|
-
const exitCode = await proc.exited
|
|
97
|
-
expect(exitCode).toBe(1)
|
|
98
|
-
})
|
|
99
|
-
})
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## Docker Integration Tests
|
|
103
|
-
|
|
104
|
-
Tests that require the Anthropic API run in Docker containers for consistent, isolated execution.
|
|
105
|
-
|
|
106
|
-
### ACP Integration Tests
|
|
107
|
-
|
|
108
|
-
The ACP client integration tests require the Anthropic API and run in a Docker container:
|
|
109
|
-
|
|
110
|
-
```bash
|
|
111
|
-
# Run locally with Docker (requires ANTHROPIC_API_KEY)
|
|
112
|
-
ANTHROPIC_API_KEY=sk-... docker compose -f docker-compose.test.yml run --rm acp-test
|
|
113
|
-
|
|
114
|
-
# Or using the npm script (still requires Docker)
|
|
115
|
-
ANTHROPIC_API_KEY=sk-... bun run test:docker
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### File Naming
|
|
119
|
-
|
|
120
|
-
- **`*.docker.ts`**: Tests that run in Docker containers
|
|
121
|
-
- These are excluded from `bun test` and run separately in CI
|
|
122
|
-
|
|
123
|
-
### CI Workflow
|
|
124
|
-
|
|
125
|
-
Docker tests use path filtering to reduce API costs:
|
|
126
|
-
|
|
127
|
-
```yaml
|
|
128
|
-
# .github/workflows/ci.yml
|
|
129
|
-
jobs:
|
|
130
|
-
changes:
|
|
131
|
-
# Detects which paths changed
|
|
132
|
-
steps:
|
|
133
|
-
- uses: dorny/paths-filter@v3
|
|
134
|
-
with:
|
|
135
|
-
filters: |
|
|
136
|
-
acp:
|
|
137
|
-
- 'src/**'
|
|
138
|
-
|
|
139
|
-
test-acp-integration:
|
|
140
|
-
needs: changes
|
|
141
|
-
if: ${{ needs.changes.outputs.acp == 'true' }}
|
|
142
|
-
# Only runs when src/ files change
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
## Anti-Patterns
|
|
146
|
-
|
|
147
|
-
### No Conditionals Around Assertions
|
|
148
|
-
|
|
149
|
-
Never wrap assertions in conditionals. Tests should fail explicitly, not silently skip assertions.
|
|
150
|
-
|
|
151
|
-
```typescript
|
|
152
|
-
// ❌ WRONG: Conditional assertion
|
|
153
|
-
if (result) {
|
|
154
|
-
expect(result.value).toBe(expected)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// ❌ WRONG: Optional chaining with assertion
|
|
158
|
-
result?.value && expect(result.value).toBe(expected)
|
|
159
|
-
|
|
160
|
-
// ✅ CORRECT: Assert the condition, then assert the value
|
|
161
|
-
expect(result).toBeDefined()
|
|
162
|
-
expect(result.value).toBe(expected)
|
|
163
|
-
|
|
164
|
-
// ✅ CORRECT: Use type narrowing assertion
|
|
165
|
-
expect(result).not.toBeNull()
|
|
166
|
-
expect(result!.value).toBe(expected)
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
If a value might not exist, the test should either:
|
|
170
|
-
1. Assert that it exists first, then check its value
|
|
171
|
-
2. Assert that it doesn't exist (if that's the expected behavior)
|
|
172
|
-
3. Restructure the test to ensure the value is always present
|