@simplysm/sd-claude 13.0.72 → 13.0.75
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/README.md +286 -13
- package/claude/refs/sd-code-conventions.md +11 -0
- package/claude/rules/sd-claude-rules.md +13 -2
- package/claude/skills/sd-brainstorm/SKILL.md +1 -1
- package/claude/skills/sd-check/SKILL.md +15 -6
- package/claude/skills/sd-commit/SKILL.md +2 -0
- package/claude/skills/sd-debug/find-polluter.sh +8 -2
- package/claude/skills/sd-debug/root-cause-tracing.md +2 -2
- package/claude/skills/sd-plan/SKILL.md +11 -2
- package/claude/skills/sd-plan-dev/SKILL.md +5 -3
- package/claude/skills/sd-plan-dev/final-review-prompt.md +3 -3
- package/claude/skills/sd-readme/SKILL.md +86 -106
- package/claude/skills/sd-review/SKILL.md +58 -62
- package/claude/skills/sd-review/api-reviewer-prompt.md +90 -0
- package/claude/skills/sd-review/code-reviewer-prompt.md +85 -0
- package/claude/skills/sd-review/code-simplifier-prompt.md +88 -0
- package/dist/commands/auth-list.d.ts +1 -1
- package/dist/commands/auth-list.d.ts.map +1 -1
- package/dist/commands/auth-list.js +79 -21
- package/dist/commands/auth-list.js.map +1 -1
- package/dist/sd-claude.js +2 -2
- package/dist/sd-claude.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/auth-list.ts +110 -24
- package/src/sd-claude.ts +2 -2
- package/tests/auth-list.spec.ts +42 -19
- package/claude/agents/sd-api-reviewer.md +0 -81
- package/claude/agents/sd-code-reviewer.md +0 -48
- package/claude/agents/sd-code-simplifier.md +0 -47
- package/claude/agents/sd-security-reviewer.md +0 -92
package/README.md
CHANGED
|
@@ -1,24 +1,297 @@
|
|
|
1
1
|
# @simplysm/sd-claude
|
|
2
2
|
|
|
3
|
-
Simplysm Claude Code CLI — asset installer
|
|
3
|
+
Simplysm Claude Code CLI — asset installer and Claude account profile manager.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
+
```bash
|
|
7
8
|
pnpm add @simplysm/sd-claude
|
|
9
|
+
```
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
On install, the `postinstall` script automatically copies Claude Code assets (`sd-*` entries) from the package's `claude/` directory into the project's `.claude/` directory and configures the status line in `.claude/settings.json`.
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
## CLI
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|--------|---------|-------------|------|
|
|
15
|
-
| `src/commands/install.ts` | `runInstall` | Copies sd-* Claude Code assets into the project's `.claude/` directory | `-` |
|
|
16
|
-
| `src/commands/auth-utils.ts` | `validateName`, `getProfileDir`, `profileExists`, `listProfiles`, `readCurrentAuth`, `readCurrentCredentials`, `getCurrentUserID` | Shared helpers for reading and locating Claude auth profile data | `auth-utils.spec.ts` |
|
|
17
|
-
| `src/commands/auth-add.ts` | `runAuthAdd` | Saves the current Claude login session as a named auth profile | `auth-add.spec.ts` |
|
|
18
|
-
| `src/commands/auth-use.ts` | `runAuthUse` | Switches the active Claude login to a saved named profile | `auth-use.spec.ts` |
|
|
19
|
-
| `src/commands/auth-list.ts` | `runAuthList` | Lists all saved auth profiles with email and token expiry info | `auth-list.spec.ts` |
|
|
20
|
-
| `src/commands/auth-remove.ts` | `runAuthRemove` | Deletes a saved auth profile from the local profile store | `auth-remove.spec.ts` |
|
|
15
|
+
The package provides the `sd-claude` binary.
|
|
21
16
|
|
|
22
|
-
|
|
17
|
+
```
|
|
18
|
+
sd-claude <command> [options]
|
|
19
|
+
sd-claude --help
|
|
20
|
+
```
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
### `install`
|
|
23
|
+
|
|
24
|
+
Installs Claude Code assets to the project's `.claude/` directory. This is also run automatically via the `postinstall` script.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
sd-claude install
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Behavior:**
|
|
31
|
+
|
|
32
|
+
- Locates the project root via `INIT_CWD` environment variable or by finding `node_modules` in the path.
|
|
33
|
+
- Copies all `sd-*` entries from the package's `claude/` directory to the project's `.claude/` directory.
|
|
34
|
+
- Removes any previously installed `sd-*` entries before copying (clean install).
|
|
35
|
+
- Adds a `statusLine` entry to `.claude/settings.json` if one is not already configured:
|
|
36
|
+
```json
|
|
37
|
+
{ "type": "command", "command": "node .claude/sd-statusline.js" }
|
|
38
|
+
```
|
|
39
|
+
- Skips installation when running inside the simplysm monorepo at the same major version.
|
|
40
|
+
- Errors during installation are suppressed (logged as warnings) to avoid blocking `pnpm install`.
|
|
41
|
+
|
|
42
|
+
### `auth`
|
|
43
|
+
|
|
44
|
+
Manages Claude account profiles. Profiles are stored in `~/.sd-claude/auth/<name>/`.
|
|
45
|
+
|
|
46
|
+
Each profile stores:
|
|
47
|
+
- `auth.json` — `oauthAccount` and `userID` from `~/.claude.json`
|
|
48
|
+
- `credentials.json` — full contents of `~/.claude/.credentials.json`
|
|
49
|
+
|
|
50
|
+
#### `auth add <name>`
|
|
51
|
+
|
|
52
|
+
Saves the currently logged-in Claude account as a named profile.
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
sd-claude auth add <name>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- `<name>`: Profile name. Must match `[a-z0-9_-]+`.
|
|
59
|
+
- Reads the current auth state from `~/.claude.json` and `~/.claude/.credentials.json`.
|
|
60
|
+
- Fails if the profile name already exists. Remove it first with `auth remove`.
|
|
61
|
+
- Requires an active Claude login. Run `/login` in Claude Code before saving.
|
|
62
|
+
|
|
63
|
+
**Example:**
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
sd-claude auth add personal
|
|
67
|
+
sd-claude auth add work
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
#### `auth use <name>`
|
|
71
|
+
|
|
72
|
+
Switches to a saved Claude account profile.
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
sd-claude auth use <name>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
- Reads the saved `auth.json` and `credentials.json` from `~/.sd-claude/auth/<name>/`.
|
|
79
|
+
- Updates `~/.claude.json` (only `oauthAccount` and `userID` fields; other fields are preserved).
|
|
80
|
+
- Replaces `~/.claude/.credentials.json` entirely with the saved credentials.
|
|
81
|
+
- Warns if the saved token has expired (run `/login` after switching to refresh).
|
|
82
|
+
|
|
83
|
+
**Example:**
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
sd-claude auth use work
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### `auth list`
|
|
90
|
+
|
|
91
|
+
Displays all saved profiles with their active status, email, token expiry, and usage.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
sd-claude auth list
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Output format per profile:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
* <name> (<email>) expires: YYYY-MM-DD │ 5h: <pct>(<remaining>) │ 7d: <pct>(<remaining>)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
- `*` marks the currently active profile (matched by `userID`); inactive profiles show a space.
|
|
104
|
+
- Usage is fetched live from `https://api.anthropic.com/api/oauth/usage` using the profile's OAuth token (5-second timeout). Shows `?` when unavailable or when the token is expired.
|
|
105
|
+
- Usage shows the `daily` window (falling back to `five_hour`) as the `5h` column, and `seven_day` as the `7d` column.
|
|
106
|
+
- Profiles are sorted alphabetically.
|
|
107
|
+
|
|
108
|
+
**Example output:**
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
* work (work@company.com) expires: 2025-12-31 │ 5h: 42%(3h15m) │ 7d: 18%(2d4h)
|
|
112
|
+
personal (personal@gmail.com) expires: 2025-11-01 │ 5h: ? │ 7d: ?
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### `auth remove <name>`
|
|
116
|
+
|
|
117
|
+
Removes a saved Claude account profile.
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
sd-claude auth remove <name>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
- Deletes `~/.sd-claude/auth/<name>/` and all its contents.
|
|
124
|
+
- Warns if the profile being removed is the currently active account (the active session in Claude Code is not affected).
|
|
125
|
+
|
|
126
|
+
**Example:**
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
sd-claude auth remove personal
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Programmatic API
|
|
133
|
+
|
|
134
|
+
All commands are also exported as functions for use in Node.js scripts.
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
import {
|
|
138
|
+
runInstall,
|
|
139
|
+
runAuthAdd,
|
|
140
|
+
runAuthUse,
|
|
141
|
+
runAuthList,
|
|
142
|
+
runAuthRemove,
|
|
143
|
+
validateName,
|
|
144
|
+
getProfileDir,
|
|
145
|
+
profileExists,
|
|
146
|
+
listProfiles,
|
|
147
|
+
readCurrentAuth,
|
|
148
|
+
readCurrentCredentials,
|
|
149
|
+
getCurrentUserID,
|
|
150
|
+
} from "@simplysm/sd-claude";
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### `runInstall(): void`
|
|
154
|
+
|
|
155
|
+
Runs the install command programmatically. See [`install`](#install) for behavior details.
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
import { runInstall } from "@simplysm/sd-claude";
|
|
159
|
+
|
|
160
|
+
runInstall();
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### `runAuthAdd(name: string, homeDir?: string): void`
|
|
164
|
+
|
|
165
|
+
Saves the currently logged-in Claude account as a named profile.
|
|
166
|
+
|
|
167
|
+
- `name`: Profile name (validated against `[a-z0-9_-]+`).
|
|
168
|
+
- `homeDir`: Override for the home directory (defaults to `os.homedir()`). Primarily used in tests.
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
import { runAuthAdd } from "@simplysm/sd-claude";
|
|
172
|
+
|
|
173
|
+
runAuthAdd("work");
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### `runAuthUse(name: string, homeDir?: string): void`
|
|
177
|
+
|
|
178
|
+
Switches to a saved Claude account profile.
|
|
179
|
+
|
|
180
|
+
- `name`: Profile name to switch to.
|
|
181
|
+
- `homeDir`: Override for the home directory.
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
import { runAuthUse } from "@simplysm/sd-claude";
|
|
185
|
+
|
|
186
|
+
runAuthUse("work");
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### `runAuthList(homeDir?: string): Promise<void>`
|
|
190
|
+
|
|
191
|
+
Prints all saved profiles to stdout with status, expiry, and live usage data.
|
|
192
|
+
|
|
193
|
+
- `homeDir`: Override for the home directory.
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
import { runAuthList } from "@simplysm/sd-claude";
|
|
197
|
+
|
|
198
|
+
await runAuthList();
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### `runAuthRemove(name: string, homeDir?: string): void`
|
|
202
|
+
|
|
203
|
+
Removes a saved Claude account profile.
|
|
204
|
+
|
|
205
|
+
- `name`: Profile name to remove.
|
|
206
|
+
- `homeDir`: Override for the home directory.
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
import { runAuthRemove } from "@simplysm/sd-claude";
|
|
210
|
+
|
|
211
|
+
runAuthRemove("personal");
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### `validateName(name: string): void`
|
|
215
|
+
|
|
216
|
+
Validates that a profile name matches `[a-z0-9_-]+`. Throws an `Error` if invalid.
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
import { validateName } from "@simplysm/sd-claude";
|
|
220
|
+
|
|
221
|
+
validateName("my-profile"); // OK
|
|
222
|
+
validateName("My Profile"); // throws Error
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### `getProfileDir(name: string, homeDir?: string): string`
|
|
226
|
+
|
|
227
|
+
Returns the absolute path to the profile directory: `<homeDir>/.sd-claude/auth/<name>`.
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
import { getProfileDir } from "@simplysm/sd-claude";
|
|
231
|
+
|
|
232
|
+
const dir = getProfileDir("work");
|
|
233
|
+
// e.g. "/home/user/.sd-claude/auth/work"
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### `profileExists(name: string, homeDir?: string): boolean`
|
|
237
|
+
|
|
238
|
+
Returns `true` if the profile directory exists.
|
|
239
|
+
|
|
240
|
+
```ts
|
|
241
|
+
import { profileExists } from "@simplysm/sd-claude";
|
|
242
|
+
|
|
243
|
+
if (profileExists("work")) {
|
|
244
|
+
console.log("Profile work exists");
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### `listProfiles(homeDir?: string): string[]`
|
|
249
|
+
|
|
250
|
+
Returns an array of all saved profile names (directory names under `~/.sd-claude/auth/`). Returns an empty array if no profiles exist.
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
import { listProfiles } from "@simplysm/sd-claude";
|
|
254
|
+
|
|
255
|
+
const profiles = listProfiles();
|
|
256
|
+
// e.g. ["personal", "work"]
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### `readCurrentAuth(homeDir?: string): { oauthAccount: Record<string, unknown>; userID: string }`
|
|
260
|
+
|
|
261
|
+
Reads `oauthAccount` and `userID` from `~/.claude.json`. Throws if not logged in.
|
|
262
|
+
|
|
263
|
+
```ts
|
|
264
|
+
import { readCurrentAuth } from "@simplysm/sd-claude";
|
|
265
|
+
|
|
266
|
+
const { oauthAccount, userID } = readCurrentAuth();
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### `readCurrentCredentials(homeDir?: string): Record<string, unknown>`
|
|
270
|
+
|
|
271
|
+
Reads and returns the full contents of `~/.claude/.credentials.json`.
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
import { readCurrentCredentials } from "@simplysm/sd-claude";
|
|
275
|
+
|
|
276
|
+
const credentials = readCurrentCredentials();
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### `getCurrentUserID(homeDir?: string): string | undefined`
|
|
280
|
+
|
|
281
|
+
Returns the `userID` from `~/.claude.json`, or `undefined` if the file does not exist or cannot be read.
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
import { getCurrentUserID } from "@simplysm/sd-claude";
|
|
285
|
+
|
|
286
|
+
const userID = getCurrentUserID();
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Profile Storage Layout
|
|
290
|
+
|
|
291
|
+
```
|
|
292
|
+
~/.sd-claude/
|
|
293
|
+
auth/
|
|
294
|
+
<name>/
|
|
295
|
+
auth.json # { oauthAccount, userID }
|
|
296
|
+
credentials.json # full ~/.claude/.credentials.json snapshot
|
|
297
|
+
```
|
|
@@ -39,8 +39,19 @@ async function readFileAsync() { ... } // Async suffix prohibited
|
|
|
39
39
|
- Not enforced — omit when code is self-explanatory
|
|
40
40
|
- When written, use Korean
|
|
41
41
|
|
|
42
|
+
## Re-export Restriction
|
|
43
|
+
|
|
44
|
+
- Re-export (`export * from`, `export { } from`) is **only allowed in `src/index.ts`**
|
|
45
|
+
- All other files must not re-export — duplicated re-exports make code harder to find and maintain
|
|
46
|
+
|
|
42
47
|
## index.ts Export Pattern
|
|
43
48
|
|
|
44
49
|
- Large packages: `#region`/`#endregion` for sections + `//` for sub-groups
|
|
45
50
|
- Small packages (≤10 exports): `//` comments only
|
|
46
51
|
- Always `export *` (wildcard), never explicit `export type { ... } from "..."`
|
|
52
|
+
|
|
53
|
+
## Type Safety for Public APIs
|
|
54
|
+
|
|
55
|
+
- API changes must be detectable via **typecheck alone** — all affected usage sites must show compile errors
|
|
56
|
+
- Public component props must support **IDE intellisense** (autocomplete, type hints)
|
|
57
|
+
- Avoid `any` in public-facing types; use generics or specific union types instead
|
|
@@ -32,7 +32,18 @@ If a referenced file or document cannot be found, **stop immediately and ask the
|
|
|
32
32
|
- Do NOT add features, refactoring, improvements, or documentation beyond the requested scope.
|
|
33
33
|
- When in doubt, **ask first** before proceeding.
|
|
34
34
|
- Responses like "I'll create it myself" or "I'll add that as well" are strictly prohibited.
|
|
35
|
+
- **Do NOT comment on code outside the requested change.** This includes:
|
|
36
|
+
- Listing issues you noticed but did not fix
|
|
37
|
+
- Describing what you "left alone" or "did not change"
|
|
38
|
+
- "참고", "suggestions", "by the way", "note", "what I left alone"
|
|
39
|
+
- Any unsolicited observations about surrounding code quality
|
|
40
|
+
- Only describe **what you changed** — nothing else
|
|
35
41
|
|
|
36
|
-
##
|
|
42
|
+
## Asking Clarifying Questions
|
|
37
43
|
|
|
38
|
-
|
|
44
|
+
When you need to ask the user a question, you MUST use the `AskUserQuestion` tool. Do NOT ask questions in plain text.
|
|
45
|
+
|
|
46
|
+
- **Wrong:** Writing questions as text in your response
|
|
47
|
+
- **Right:** Calling the `AskUserQuestion` tool
|
|
48
|
+
|
|
49
|
+
**Before EVERY `AskUserQuestion` call, output `---` as the last line.** The widget clips text above it. No exceptions.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sd-brainstorm
|
|
3
|
-
description: "
|
|
3
|
+
description: "You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Brainstorming Ideas Into Designs
|
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sd-check
|
|
3
3
|
description: "Typecheck, lint, test verification (explicit invocation only)"
|
|
4
|
-
allowed-tools: Bash(npm run check), Bash(npm run typecheck), Bash(npm run lint
|
|
4
|
+
allowed-tools: Bash(npm run check:*), Bash(pnpm run check:*), Bash(yarn run check:*), Bash(npm run typecheck:*), Bash(pnpm run typecheck:*), Bash(yarn run typecheck:*), Bash(npm run lint:*), Bash(pnpm run lint:*), Bash(yarn run lint:*), Bash(npm run vitest:*), Bash(pnpm run vitest:*), Bash(yarn run vitest:*)
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# sd-check
|
|
8
8
|
|
|
9
|
-
Run
|
|
9
|
+
Run `$PM run check`, fix errors, repeat until clean.
|
|
10
|
+
|
|
11
|
+
## Package Manager Detection
|
|
12
|
+
|
|
13
|
+
Before running any commands, detect the package manager:
|
|
14
|
+
- If `pnpm-lock.yaml` exists in project root → use `pnpm`
|
|
15
|
+
- If `yarn.lock` exists in project root → use `yarn`
|
|
16
|
+
- Otherwise → use `npm`
|
|
17
|
+
|
|
18
|
+
`$PM` in all commands below refers to the detected package manager.
|
|
10
19
|
|
|
11
20
|
## Usage
|
|
12
21
|
|
|
13
22
|
```
|
|
14
|
-
|
|
23
|
+
$PM run check [path] [--type typecheck|lint|test]
|
|
15
24
|
```
|
|
16
25
|
|
|
17
26
|
| Example | Effect |
|
|
@@ -25,11 +34,11 @@ Multiple types: `--type typecheck,lint`. No path = full project. No type = all c
|
|
|
25
34
|
|
|
26
35
|
## Workflow
|
|
27
36
|
|
|
28
|
-
1. **Run**
|
|
37
|
+
1. **Run** `$PM run check [path] [--type type]` (timeout: 600000)
|
|
29
38
|
2. **All passed?** Report with actual output numbers → done
|
|
30
39
|
3. **Errors?** Fix in priority order: typecheck → lint → test (fixes cascade)
|
|
31
|
-
- Test failures: run `git
|
|
32
|
-
- **E2E test failures
|
|
40
|
+
- Test failures: **MUST** run `git log` to decide — update test or fix source
|
|
41
|
+
- **E2E test failures**: use Playwright MCP to investigate before fixing
|
|
33
42
|
1. `browser_navigate` to the target URL
|
|
34
43
|
2. `browser_snapshot` / `browser_take_screenshot` (save to `.tmp/playwright/`) to see page state
|
|
35
44
|
3. `browser_console_messages` for JS errors
|
|
@@ -58,6 +58,8 @@ Examples:
|
|
|
58
58
|
- `fix(orm-node): handle null values in bulk insert`
|
|
59
59
|
- `docs: update README with new API examples`
|
|
60
60
|
|
|
61
|
+
> **Note:** The examples above are in English for reference only. The actual description MUST be written in the system's configured language.
|
|
62
|
+
|
|
61
63
|
Use a HEREDOC for multi-line messages when needed.
|
|
62
64
|
|
|
63
65
|
## Execution
|
|
@@ -14,6 +14,12 @@ fi
|
|
|
14
14
|
CHECK_PATH="$1"
|
|
15
15
|
TEST_PATTERN="$2"
|
|
16
16
|
|
|
17
|
+
# Detect package manager: pnpm -> yarn -> npm (default)
|
|
18
|
+
if [ -f "pnpm-lock.yaml" ]; then PM="pnpm"
|
|
19
|
+
elif [ -f "yarn.lock" ]; then PM="yarn"
|
|
20
|
+
else PM="npm"
|
|
21
|
+
fi
|
|
22
|
+
|
|
17
23
|
# Find all test files matching pattern
|
|
18
24
|
readarray -t TEST_FILES < <(find . -path "$TEST_PATTERN" -type f)
|
|
19
25
|
|
|
@@ -37,7 +43,7 @@ for test_file in "${TEST_FILES[@]}"; do
|
|
|
37
43
|
echo "Testing: $test_file"
|
|
38
44
|
|
|
39
45
|
# Run the test
|
|
40
|
-
|
|
46
|
+
$PM test "$test_file" > /dev/null 2>&1 || true
|
|
41
47
|
|
|
42
48
|
# Check if pollution appeared
|
|
43
49
|
if [ -e "$CHECK_PATH" ]; then
|
|
@@ -48,7 +54,7 @@ for test_file in "${TEST_FILES[@]}"; do
|
|
|
48
54
|
ls -la "$CHECK_PATH" 2>/dev/null || echo "(path exists but can't stat)"
|
|
49
55
|
echo ""
|
|
50
56
|
echo "Investigate with:"
|
|
51
|
-
echo "
|
|
57
|
+
echo " $PM test '$test_file' -- --reporter=verbose"
|
|
52
58
|
echo " git diff"
|
|
53
59
|
exit 0
|
|
54
60
|
fi
|
|
@@ -93,10 +93,10 @@ async function gitInit(directory: string) {
|
|
|
93
93
|
|
|
94
94
|
**Critical:** Use `console.error()` in tests (not logger - may not show)
|
|
95
95
|
|
|
96
|
-
**Run and capture
|
|
96
|
+
**Run and capture** (detect PM: `pnpm-lock.yaml` → pnpm, `yarn.lock` → yarn, otherwise → npm):
|
|
97
97
|
|
|
98
98
|
```bash
|
|
99
|
-
|
|
99
|
+
$PM test 2>&1 | grep 'DEBUG git init'
|
|
100
100
|
```
|
|
101
101
|
|
|
102
102
|
**Analyze stack traces:**
|
|
@@ -49,6 +49,15 @@ Assume they are a skilled developer, but know almost nothing about our toolset o
|
|
|
49
49
|
---
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
+
## Package Manager Detection
|
|
53
|
+
|
|
54
|
+
When writing run commands in the plan, detect the package manager:
|
|
55
|
+
- If `pnpm-lock.yaml` exists in project root → use `pnpm`
|
|
56
|
+
- If `yarn.lock` exists in project root → use `yarn`
|
|
57
|
+
- Otherwise → use `npm`
|
|
58
|
+
|
|
59
|
+
`$PM` in the task template below refers to the detected package manager.
|
|
60
|
+
|
|
52
61
|
## Task Structure
|
|
53
62
|
|
|
54
63
|
```markdown
|
|
@@ -70,7 +79,7 @@ test("specific behavior", () => {
|
|
|
70
79
|
|
|
71
80
|
**Step 2: Run test to verify it fails**
|
|
72
81
|
|
|
73
|
-
Run:
|
|
82
|
+
Run: `$PM run vitest exact/path/to/tests/file.spec.ts --run`
|
|
74
83
|
Expected: FAIL with "functionUnderTest is not defined"
|
|
75
84
|
|
|
76
85
|
**Step 3: Write minimal implementation**
|
|
@@ -83,7 +92,7 @@ function functionUnderTest(input: InputType): OutputType {
|
|
|
83
92
|
|
|
84
93
|
**Step 4: Run test to verify it passes**
|
|
85
94
|
|
|
86
|
-
Run:
|
|
95
|
+
Run: `$PM run vitest exact/path/to/tests/file.spec.ts --run`
|
|
87
96
|
Expected: PASS
|
|
88
97
|
|
|
89
98
|
**Step 5: Commit**
|
|
@@ -221,11 +221,13 @@ Done!
|
|
|
221
221
|
|
|
222
222
|
## Batch Integration Check
|
|
223
223
|
|
|
224
|
-
Between batches, run targeted verification on affected packages before starting the next batch
|
|
224
|
+
Between batches, run targeted verification on affected packages before starting the next batch.
|
|
225
|
+
|
|
226
|
+
Detect the package manager first (`pnpm-lock.yaml` → pnpm, `yarn.lock` → yarn, otherwise → npm):
|
|
225
227
|
|
|
226
228
|
```bash
|
|
227
|
-
|
|
228
|
-
|
|
229
|
+
$PM run typecheck [affected packages]
|
|
230
|
+
$PM run lint [affected packages]
|
|
229
231
|
```
|
|
230
232
|
|
|
231
233
|
This catches cross-task integration issues early — especially when the next batch depends on the current batch's output. Do NOT skip this even if individual task reviews passed.
|
|
@@ -37,9 +37,9 @@ Individual tasks already passed spec and quality reviews. Focus on cross-task in
|
|
|
37
37
|
|
|
38
38
|
### Verification
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
40
|
+
Detect the package manager (`pnpm-lock.yaml` → pnpm, `yarn.lock` → yarn, otherwise → npm), then run and report results:
|
|
41
|
+
- `$PM run typecheck [affected packages]`
|
|
42
|
+
- `$PM run lint [affected packages]`
|
|
43
43
|
|
|
44
44
|
### Report
|
|
45
45
|
|