sequant 2.7.0 → 2.8.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +9 -1
- package/dist/bin/cli.d.ts +1 -1
- package/dist/bin/cli.js +10 -1
- package/dist/bin/preflight.d.ts +21 -0
- package/dist/bin/preflight.js +45 -0
- package/dist/marketplace/external_plugins/sequant/.claude-plugin/plugin.json +1 -1
- package/dist/marketplace/external_plugins/sequant/skills/_shared/references/force-push.md +34 -0
- package/dist/marketplace/external_plugins/sequant/skills/assess/SKILL.md +24 -7
- package/dist/marketplace/external_plugins/sequant/skills/exec/SKILL.md +29 -0
- package/dist/marketplace/external_plugins/sequant/skills/loop/SKILL.md +100 -2
- package/dist/marketplace/external_plugins/sequant/skills/qa/SKILL.md +24 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/anti-pattern-detection.md +285 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/call-site-review.md +202 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/quality-gates.md +287 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/test-quality-checklist.md +272 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/references/testing-requirements.md +40 -0
- package/dist/marketplace/external_plugins/sequant/skills/qa/scripts/quality-checks.sh +95 -11
- package/dist/marketplace/external_plugins/sequant/skills/references/shared/framework-gotchas.md +186 -0
- package/dist/marketplace/external_plugins/sequant/skills/release/SKILL.md +661 -0
- package/dist/marketplace/external_plugins/sequant/skills/test/references/browser-testing-patterns.md +423 -0
- package/dist/marketplace/external_plugins/sequant/skills/upstream/SKILL.md +419 -0
- package/dist/src/lib/errors.d.ts +85 -0
- package/dist/src/lib/errors.js +111 -0
- package/dist/src/lib/version-check.d.ts +19 -0
- package/dist/src/lib/version-check.js +44 -0
- package/dist/src/lib/workflow/batch-executor.js +61 -6
- package/dist/src/lib/workflow/drivers/agent-driver.d.ts +17 -0
- package/dist/src/lib/workflow/drivers/claude-code.d.ts +22 -0
- package/dist/src/lib/workflow/drivers/claude-code.js +111 -7
- package/dist/src/lib/workflow/log-writer.d.ts +1 -1
- package/dist/src/lib/workflow/phase-executor.d.ts +18 -0
- package/dist/src/lib/workflow/phase-executor.js +76 -14
- package/dist/src/lib/workflow/run-log-schema.d.ts +3 -0
- package/dist/src/lib/workflow/run-log-schema.js +7 -0
- package/dist/src/lib/workflow/state-manager.d.ts +1 -0
- package/dist/src/lib/workflow/state-manager.js +6 -0
- package/dist/src/lib/workflow/state-schema.d.ts +3 -0
- package/dist/src/lib/workflow/state-schema.js +7 -0
- package/dist/src/lib/workflow/types.d.ts +17 -0
- package/dist/src/ui/tui/theme.d.ts +18 -4
- package/dist/src/ui/tui/theme.js +18 -4
- package/package.json +4 -3
- package/templates/skills/_shared/references/force-push.md +34 -0
- package/templates/skills/assess/SKILL.md +24 -7
- package/templates/skills/exec/SKILL.md +29 -0
- package/templates/skills/loop/SKILL.md +100 -2
- package/templates/skills/qa/SKILL.md +24 -0
- package/templates/skills/qa/references/anti-pattern-detection.md +285 -0
- package/templates/skills/qa/references/call-site-review.md +202 -0
- package/templates/skills/qa/references/quality-gates.md +287 -0
- package/templates/skills/qa/references/test-quality-checklist.md +272 -0
- package/templates/skills/qa/references/testing-requirements.md +40 -0
- package/templates/skills/qa/scripts/quality-checks.sh +95 -11
- package/templates/skills/references/shared/framework-gotchas.md +186 -0
- package/templates/skills/release/SKILL.md +661 -0
- package/templates/skills/test/references/browser-testing-patterns.md +423 -0
- package/templates/skills/upstream/SKILL.md +419 -0
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: upstream
|
|
3
|
+
description: "Monitor Claude Code releases, assess compatibility with sequant, and create issues for breaking changes and deprecations. Opportunities are noted in assessment reports for human triage."
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
author: sequant
|
|
7
|
+
version: "1.0"
|
|
8
|
+
allowed-tools:
|
|
9
|
+
- Read
|
|
10
|
+
- Write
|
|
11
|
+
- Glob
|
|
12
|
+
- Grep
|
|
13
|
+
- Bash(gh *)
|
|
14
|
+
- Bash(git *)
|
|
15
|
+
- Bash(jq *)
|
|
16
|
+
- Bash(base64 *)
|
|
17
|
+
- Bash(npx tsx *)
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
<!-- sequant:local-override -->
|
|
21
|
+
> **Local overrides (read this first).** Before following any instruction below, check whether `.claude/.local/skills/upstream/overrides.md` exists. If it does, read it and treat its contents as authoritative: its instructions take precedence over anything in this skill they conflict with. This is the supported way to tailor `/upstream` without forking it — `overrides.md` lives under `.claude/.local/`, which `sequant update` and `sync` never overwrite.
|
|
22
|
+
|
|
23
|
+
# Upstream: Claude Code Release Tracking
|
|
24
|
+
|
|
25
|
+
You are the "Upstream Assessment Agent" for the sequant repository.
|
|
26
|
+
|
|
27
|
+
## Purpose
|
|
28
|
+
|
|
29
|
+
When invoked as `/upstream`, your job is to:
|
|
30
|
+
|
|
31
|
+
1. Fetch Claude Code release information from the public GitHub repo
|
|
32
|
+
2. Analyze changes against sequant's current capabilities baseline
|
|
33
|
+
3. Detect relevant changes using keyword matching and regex patterns
|
|
34
|
+
4. Skip out-of-scope changes (configured in baseline.json `outOfScope`)
|
|
35
|
+
5. Generate a structured compatibility assessment report with Actionable and Informational sections
|
|
36
|
+
6. Auto-create GitHub issues for breaking changes, deprecations, new tools, and hook changes
|
|
37
|
+
7. List opportunities in the assessment report for human triage (no individual issues created)
|
|
38
|
+
|
|
39
|
+
## Invocation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Analyze latest release
|
|
43
|
+
/upstream
|
|
44
|
+
|
|
45
|
+
# Analyze specific version
|
|
46
|
+
/upstream v2.1.29
|
|
47
|
+
|
|
48
|
+
# Analyze all releases since version
|
|
49
|
+
/upstream --since v2.1.25
|
|
50
|
+
|
|
51
|
+
# Dry-run mode (no issues created)
|
|
52
|
+
/upstream --dry-run
|
|
53
|
+
|
|
54
|
+
# Help
|
|
55
|
+
/upstream --help
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Assessment Process
|
|
59
|
+
|
|
60
|
+
### 1. Parse Arguments
|
|
61
|
+
|
|
62
|
+
Parse the command arguments to determine:
|
|
63
|
+
|
|
64
|
+
- **Target version**: Specific version (e.g., `v2.1.29`) or `latest`
|
|
65
|
+
- **Since version**: If `--since` flag provided, assess all versions since that release
|
|
66
|
+
- **Dry-run mode**: If `--dry-run` flag, generate report but skip issue creation
|
|
67
|
+
- **Help**: If `--help` flag, show usage instructions
|
|
68
|
+
|
|
69
|
+
### 2. Fetch Release Data
|
|
70
|
+
|
|
71
|
+
Fetch release information from the public Claude Code repository:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Get latest release
|
|
75
|
+
gh release view --repo anthropics/claude-code --json tagName,name,body,publishedAt
|
|
76
|
+
|
|
77
|
+
# Get specific version
|
|
78
|
+
gh release view v2.1.29 --repo anthropics/claude-code --json tagName,name,body,publishedAt
|
|
79
|
+
|
|
80
|
+
# List releases for --since support
|
|
81
|
+
gh release list --repo anthropics/claude-code --limit 50 --json tagName,publishedAt
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 3. Load Baseline
|
|
85
|
+
|
|
86
|
+
Load the sequant capabilities baseline from `.sequant/upstream/baseline.json`:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"lastAssessedVersion": "v2.1.25",
|
|
91
|
+
"tools": {
|
|
92
|
+
"core": ["Task", "Bash", "Read", "Write", "Edit", "Glob", "Grep"],
|
|
93
|
+
"optional": ["WebFetch", "WebSearch", "NotebookEdit"]
|
|
94
|
+
},
|
|
95
|
+
"hooks": {
|
|
96
|
+
"used": ["PreToolUse"],
|
|
97
|
+
"files": ["src/hooks/pre-tool-hook.ts"]
|
|
98
|
+
},
|
|
99
|
+
"mcpServers": {
|
|
100
|
+
"required": [],
|
|
101
|
+
"optional": ["chrome-devtools", "context7", "sequential-thinking"]
|
|
102
|
+
},
|
|
103
|
+
"keywords": [
|
|
104
|
+
"Task", "Bash", "hook", "PreToolUse", "PostToolUse",
|
|
105
|
+
"MCP", "permission", "allow", "deny", "tool",
|
|
106
|
+
"background", "parallel", "agent", "subagent",
|
|
107
|
+
"settings", "config", "plugin"
|
|
108
|
+
],
|
|
109
|
+
"dependencyMap": {
|
|
110
|
+
"permission": ["src/hooks/pre-tool-hook.ts", ".claude/settings.json"],
|
|
111
|
+
"hook": ["src/hooks/pre-tool-hook.ts"],
|
|
112
|
+
"Task": [".claude/skills/**/*.md", "src/lib/workflow/*.ts"],
|
|
113
|
+
"MCP": ["docs/mcp-integrations.md", ".claude/settings.json"]
|
|
114
|
+
},
|
|
115
|
+
"outOfScope": [
|
|
116
|
+
"PDF/document processing - users work with code and GitHub issues",
|
|
117
|
+
"Slack/OAuth integrations - workflow is GitHub-centric",
|
|
118
|
+
"Notebook editing - not a data science tool",
|
|
119
|
+
"IDE-specific features (VSCode, JetBrains) - sequant is CLI/terminal focused",
|
|
120
|
+
"Windows-specific fixes - sequant targets macOS/Linux"
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 4. Analyze Changes
|
|
126
|
+
|
|
127
|
+
For each release, analyze the changelog/release body:
|
|
128
|
+
|
|
129
|
+
**Step 1: Extract Changes**
|
|
130
|
+
|
|
131
|
+
Parse the release body to extract individual change items. Common formats:
|
|
132
|
+
- Bullet points: `- Added new feature X`
|
|
133
|
+
- "What's changed" sections
|
|
134
|
+
- BREAKING CHANGE markers
|
|
135
|
+
|
|
136
|
+
**Step 2: Relevance Detection**
|
|
137
|
+
|
|
138
|
+
For each change, check if it's relevant to sequant:
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
// Keyword matching
|
|
142
|
+
const isRelevant = baseline.keywords.some(kw =>
|
|
143
|
+
change.toLowerCase().includes(kw.toLowerCase())
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
// Pattern matching
|
|
147
|
+
const patterns = {
|
|
148
|
+
newTool: /added.*tool|new.*tool|introducing/i,
|
|
149
|
+
deprecation: /deprecat|remov|no longer support/i,
|
|
150
|
+
breaking: /breaking|incompatible|must update/i,
|
|
151
|
+
hook: /hook|PreToolUse|PostToolUse/i,
|
|
152
|
+
permission: /permission|allow|deny|ask/i,
|
|
153
|
+
};
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Step 3: Categorize**
|
|
157
|
+
|
|
158
|
+
Categorize each relevant change:
|
|
159
|
+
|
|
160
|
+
| Category | Detection Pattern | Issue Labels |
|
|
161
|
+
|----------|------------------|--------------|
|
|
162
|
+
| `breaking` | Breaking, incompatible, must update | `upstream`, `bug`, `priority:high` |
|
|
163
|
+
| `deprecation` | Deprecated, removed, no longer supported | `upstream`, `bug` |
|
|
164
|
+
| `new-tool` | Added tool, new tool, introducing | `upstream`, `enhancement` |
|
|
165
|
+
| `hook-change` | Hook, PreToolUse, PostToolUse | `upstream`, `enhancement` |
|
|
166
|
+
| `opportunity` | Keywords match but not above categories | (no issue — noted in assessment for human triage) |
|
|
167
|
+
| `no-action` | Doesn't match patterns or keywords | (no issue) |
|
|
168
|
+
|
|
169
|
+
**Step 4: Impact Mapping**
|
|
170
|
+
|
|
171
|
+
For relevant changes, map to affected sequant files using `dependencyMap`:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
const impactFiles = baseline.dependencyMap[matchedKeyword] || [];
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### 5. Check for Duplicates
|
|
178
|
+
|
|
179
|
+
Before creating issues, check for existing upstream issues:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# Search for similar issues
|
|
183
|
+
gh issue list --label upstream --search "<finding-title>" --json number,title
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
If a similar issue exists:
|
|
187
|
+
- Add a comment linking to the new assessment
|
|
188
|
+
- Skip creating a duplicate
|
|
189
|
+
|
|
190
|
+
### 6. Generate Outputs
|
|
191
|
+
|
|
192
|
+
**Output 1: Assessment Report (GitHub Issue)**
|
|
193
|
+
|
|
194
|
+
Create a summary issue with the full assessment:
|
|
195
|
+
|
|
196
|
+
```markdown
|
|
197
|
+
## Upstream: Claude Code <version> Assessment
|
|
198
|
+
|
|
199
|
+
**Release:** [<version>](https://github.com/anthropics/claude-code/releases/tag/<version>)
|
|
200
|
+
**Released:** <date>
|
|
201
|
+
**Assessed:** <today>
|
|
202
|
+
|
|
203
|
+
### Summary
|
|
204
|
+
|
|
205
|
+
| Category | Count | Action Required |
|
|
206
|
+
|----------|-------|-----------------|
|
|
207
|
+
| Breaking Changes | N | [status] |
|
|
208
|
+
| New Tools | N | [status] |
|
|
209
|
+
| Deprecations | N | [status] |
|
|
210
|
+
| Opportunities | N | [status] |
|
|
211
|
+
|
|
212
|
+
### Actionable
|
|
213
|
+
|
|
214
|
+
*Breaking changes, deprecations, and other items that affect sequant.*
|
|
215
|
+
|
|
216
|
+
[list of breaking, deprecation, new-tool, hook-change findings]
|
|
217
|
+
|
|
218
|
+
### Informational
|
|
219
|
+
|
|
220
|
+
*Opportunities noted for human triage. No individual issues auto-created.*
|
|
221
|
+
|
|
222
|
+
[list of opportunity findings]
|
|
223
|
+
|
|
224
|
+
### No Action Required
|
|
225
|
+
|
|
226
|
+
[list of irrelevant changes]
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
*Generated by /upstream skill*
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Output 2: Individual Issues (Actionable Findings)**
|
|
234
|
+
|
|
235
|
+
For each actionable finding (breaking, deprecation, new-tool, hook-change), create an issue.
|
|
236
|
+
**Note:** Opportunities do NOT get individual issues — they are listed in the assessment report's Informational section for human triage.
|
|
237
|
+
|
|
238
|
+
```markdown
|
|
239
|
+
## feat: Leverage <feature> from Claude Code <version>
|
|
240
|
+
|
|
241
|
+
**Upstream:** Claude Code <version>
|
|
242
|
+
**Category:** <category>
|
|
243
|
+
**Assessment:** #<assessment-issue>
|
|
244
|
+
|
|
245
|
+
### Context
|
|
246
|
+
|
|
247
|
+
<description from release notes>
|
|
248
|
+
|
|
249
|
+
### Opportunity
|
|
250
|
+
|
|
251
|
+
<how sequant could use this>
|
|
252
|
+
|
|
253
|
+
### Proposed Implementation
|
|
254
|
+
|
|
255
|
+
[To be determined during /spec phase]
|
|
256
|
+
|
|
257
|
+
### Acceptance Criteria
|
|
258
|
+
|
|
259
|
+
- [ ] AC-1: [To be defined]
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
*Auto-created by /upstream assessment #<N>*
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Labels: `upstream`, `needs-triage`, `enhancement`
|
|
267
|
+
|
|
268
|
+
**Output 3: Local Report**
|
|
269
|
+
|
|
270
|
+
Save to `.sequant/upstream/<version>.md`:
|
|
271
|
+
|
|
272
|
+
```markdown
|
|
273
|
+
# Claude Code <version> Assessment
|
|
274
|
+
|
|
275
|
+
Assessed: <date>
|
|
276
|
+
Previous: <last-assessed-version>
|
|
277
|
+
|
|
278
|
+
## Summary
|
|
279
|
+
|
|
280
|
+
[same as GitHub issue]
|
|
281
|
+
|
|
282
|
+
## Raw Findings
|
|
283
|
+
|
|
284
|
+
[detailed analysis data]
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
**Output 4: Update Baseline**
|
|
288
|
+
|
|
289
|
+
Update `.sequant/upstream/baseline.json`:
|
|
290
|
+
- Set `lastAssessedVersion` to the assessed version
|
|
291
|
+
|
|
292
|
+
### 7. Multi-Version Batching
|
|
293
|
+
|
|
294
|
+
When `--since <version>` is used:
|
|
295
|
+
|
|
296
|
+
1. List all releases after the specified version
|
|
297
|
+
2. Assess each version individually
|
|
298
|
+
3. Create a batched summary issue linking all individual assessments
|
|
299
|
+
4. Update baseline to latest assessed version
|
|
300
|
+
|
|
301
|
+
## Dry-Run Mode
|
|
302
|
+
|
|
303
|
+
When `--dry-run` is specified:
|
|
304
|
+
|
|
305
|
+
1. Perform full analysis
|
|
306
|
+
2. Generate local report
|
|
307
|
+
3. Output what issues WOULD be created (titles, labels)
|
|
308
|
+
4. Skip actual GitHub issue creation
|
|
309
|
+
5. Skip baseline update
|
|
310
|
+
|
|
311
|
+
## Error Handling
|
|
312
|
+
|
|
313
|
+
- **No releases found**: Exit with clear message
|
|
314
|
+
- **Baseline missing**: Create default baseline, warn user
|
|
315
|
+
- **GitHub API errors**: Retry with backoff, then fail gracefully
|
|
316
|
+
- **Already assessed**: Skip with message (idempotent)
|
|
317
|
+
|
|
318
|
+
## Output Verification
|
|
319
|
+
|
|
320
|
+
**Before completing, verify:**
|
|
321
|
+
|
|
322
|
+
- [ ] Release data successfully fetched
|
|
323
|
+
- [ ] Baseline loaded (or created with defaults)
|
|
324
|
+
- [ ] Each change categorized
|
|
325
|
+
- [ ] Duplicates checked before issue creation
|
|
326
|
+
- [ ] Assessment report created (or dry-run output shown)
|
|
327
|
+
- [ ] Individual issues created for actionable findings (not opportunities)
|
|
328
|
+
- [ ] Local report saved
|
|
329
|
+
- [ ] Baseline updated with new version
|
|
330
|
+
|
|
331
|
+
## Examples
|
|
332
|
+
|
|
333
|
+
### Example 1: Assess Latest Release
|
|
334
|
+
|
|
335
|
+
```
|
|
336
|
+
/upstream
|
|
337
|
+
|
|
338
|
+
Fetching latest Claude Code release...
|
|
339
|
+
Release: v2.1.29 (2025-01-31)
|
|
340
|
+
|
|
341
|
+
Loading baseline from .sequant/upstream/baseline.json...
|
|
342
|
+
Last assessed: v2.1.27
|
|
343
|
+
|
|
344
|
+
Analyzing 12 changes from release notes...
|
|
345
|
+
- 3 relevant changes detected
|
|
346
|
+
- 9 no-action changes
|
|
347
|
+
|
|
348
|
+
Findings:
|
|
349
|
+
1. [opportunity] New --background flag on Task tool
|
|
350
|
+
Matched keywords: Task, background
|
|
351
|
+
Impact files: .claude/skills/**/*.md
|
|
352
|
+
|
|
353
|
+
2. [hook-change] Permissions now respect content-level ask
|
|
354
|
+
Matched keywords: permission
|
|
355
|
+
Impact files: src/hooks/pre-tool-hook.ts
|
|
356
|
+
|
|
357
|
+
3. [deprecation] oldHookName deprecated
|
|
358
|
+
Matched pattern: deprecat
|
|
359
|
+
Impact files: src/hooks/pre-tool-hook.ts
|
|
360
|
+
|
|
361
|
+
Creating assessment issue...
|
|
362
|
+
Created: #250 - Upstream: Claude Code v2.1.29 Assessment
|
|
363
|
+
|
|
364
|
+
Creating individual issues...
|
|
365
|
+
Created: #251 - feat: Leverage new --background flag from Claude Code v2.1.29
|
|
366
|
+
Created: #252 - chore: Update to new hook name (deprecation from v2.1.29)
|
|
367
|
+
|
|
368
|
+
Saving local report to .sequant/upstream/v2.1.29.md...
|
|
369
|
+
Updating baseline lastAssessedVersion to v2.1.29...
|
|
370
|
+
|
|
371
|
+
Done! Assessment complete.
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Example 2: Dry Run
|
|
375
|
+
|
|
376
|
+
```
|
|
377
|
+
/upstream --dry-run
|
|
378
|
+
|
|
379
|
+
[DRY RUN MODE - No issues will be created]
|
|
380
|
+
|
|
381
|
+
Fetching latest Claude Code release...
|
|
382
|
+
Release: v2.1.29 (2025-01-31)
|
|
383
|
+
|
|
384
|
+
...analysis...
|
|
385
|
+
|
|
386
|
+
Would create issues:
|
|
387
|
+
1. Assessment: Upstream: Claude Code v2.1.29 Assessment
|
|
388
|
+
2. Finding: feat: Leverage new --background flag from Claude Code v2.1.29
|
|
389
|
+
3. Finding: chore: Update to new hook name (deprecation from v2.1.29)
|
|
390
|
+
|
|
391
|
+
Local report saved: .sequant/upstream/v2.1.29.md
|
|
392
|
+
Baseline NOT updated (dry-run mode)
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### Example 3: Already Assessed
|
|
396
|
+
|
|
397
|
+
```
|
|
398
|
+
/upstream
|
|
399
|
+
|
|
400
|
+
Fetching latest Claude Code release...
|
|
401
|
+
Release: v2.1.29 (2025-01-31)
|
|
402
|
+
|
|
403
|
+
Already assessed: .sequant/upstream/v2.1.29.md exists
|
|
404
|
+
Use --force to re-assess.
|
|
405
|
+
|
|
406
|
+
No action taken.
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
## Notes
|
|
410
|
+
|
|
411
|
+
- This is an internal tool for sequant maintainers
|
|
412
|
+
- All created issues get `needs-triage` label for human review
|
|
413
|
+
- The skill is read-only for Claude Code repo (no PRs or edits)
|
|
414
|
+
- Baseline file should be committed to version control
|
|
415
|
+
- Local reports in `.sequant/upstream/` should be committed
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
*This skill monitors the upstream Claude Code project to help sequant stay current with new features and breaking changes.*
|
package/dist/src/lib/errors.d.ts
CHANGED
|
@@ -86,6 +86,91 @@ export declare class SubprocessError extends SequantError {
|
|
|
86
86
|
readonly metadata: SubprocessErrorMetadata;
|
|
87
87
|
constructor(message: string, metadata?: SubprocessErrorMetadata, cause?: Error);
|
|
88
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Metadata carried by {@link RateLimitError} / {@link BillingError}.
|
|
91
|
+
*
|
|
92
|
+
* Fields mirror the structured signals the Claude Agent SDK emits via
|
|
93
|
+
* `rate_limit_event` (`SDKRateLimitInfo`). The `canUserPurchaseCredits` /
|
|
94
|
+
* `hasChargeableSavedPaymentMethod` fields arrived in SDK 0.3.181 and are
|
|
95
|
+
* optional so older streams (or absent fields) degrade gracefully.
|
|
96
|
+
*/
|
|
97
|
+
export interface RateLimitMetadata {
|
|
98
|
+
[key: string]: unknown;
|
|
99
|
+
/** Unix timestamp (seconds or ms) at which the limit resets. */
|
|
100
|
+
resetsAt?: number;
|
|
101
|
+
/** Which limit window was hit (five_hour, seven_day, overage, …). */
|
|
102
|
+
rateLimitType?: string;
|
|
103
|
+
/** Why overage/billing was disabled (e.g. `out_of_credits`). */
|
|
104
|
+
overageDisabledReason?: string;
|
|
105
|
+
/** SDK error code; `credits_required` indicates a billing failure. */
|
|
106
|
+
errorCode?: string;
|
|
107
|
+
/** Whether the user can self-serve purchase credits (≥0.3.181). */
|
|
108
|
+
canUserPurchaseCredits?: boolean;
|
|
109
|
+
/** Whether a chargeable payment method is on file (≥0.3.181). */
|
|
110
|
+
hasChargeableSavedPaymentMethod?: boolean;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Transient rate-limit error (HTTP 429-style throttle, overloaded API).
|
|
114
|
+
*
|
|
115
|
+
* Retryable: waiting and re-running can succeed once the limit window resets.
|
|
116
|
+
*/
|
|
117
|
+
export declare class RateLimitError extends SequantError {
|
|
118
|
+
readonly metadata: RateLimitMetadata;
|
|
119
|
+
constructor(message: string, metadata?: RateLimitMetadata, cause?: Error);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Billing / out-of-credits error.
|
|
123
|
+
*
|
|
124
|
+
* NOT retryable: a no-MCP retry (or any retry) cannot refill credits, so the
|
|
125
|
+
* executor must surface the real cause instead of looping. Drives the #592
|
|
126
|
+
* fallback-noise skip in phase-executor.
|
|
127
|
+
*/
|
|
128
|
+
export declare class BillingError extends SequantError {
|
|
129
|
+
readonly metadata: RateLimitMetadata;
|
|
130
|
+
constructor(message: string, metadata?: RateLimitMetadata, cause?: Error);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Structural subset of the SDK's `SDKRateLimitInfo` consumed when building a
|
|
134
|
+
* rate-limit error. Declared here (not imported from the SDK) so `errors.ts`
|
|
135
|
+
* stays SDK-free — only the driver owns the `@anthropic-ai/claude-agent-sdk`
|
|
136
|
+
* import.
|
|
137
|
+
*/
|
|
138
|
+
export interface RateLimitInfoLike {
|
|
139
|
+
status?: string;
|
|
140
|
+
resetsAt?: number;
|
|
141
|
+
rateLimitType?: string;
|
|
142
|
+
overageDisabledReason?: string;
|
|
143
|
+
errorCode?: string;
|
|
144
|
+
canUserPurchaseCredits?: boolean;
|
|
145
|
+
hasChargeableSavedPaymentMethod?: boolean;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* True when the rate-limit info represents a billing/credits failure (which a
|
|
149
|
+
* retry cannot fix), rather than a transient throttle.
|
|
150
|
+
*/
|
|
151
|
+
export declare function isBillingFailure(info: RateLimitInfoLike): boolean;
|
|
152
|
+
/**
|
|
153
|
+
* True when the rate-limit info represents an actual failure (rejection or
|
|
154
|
+
* billing), as opposed to an informational `allowed` / `allowed_warning`
|
|
155
|
+
* event. The driver uses this to avoid mis-attributing a stale warning event
|
|
156
|
+
* to an unrelated phase failure.
|
|
157
|
+
*/
|
|
158
|
+
export declare function isRateLimitFailureInfo(info: RateLimitInfoLike): boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Build a user-facing message from rate-limit info, naming the real cause:
|
|
161
|
+
* - billing/credits → "Out of credits" (enriched with purchasable vs hard
|
|
162
|
+
* limit when the ≥0.3.181 `canUserPurchaseCredits` field is present)
|
|
163
|
+
* - transient throttle → "Rate limited — resets at HH:MM" (date-qualified as
|
|
164
|
+
* "MM-DD HH:MM" when the reset is not today; reset time omitted entirely when
|
|
165
|
+
* `resetsAt` is absent)
|
|
166
|
+
*/
|
|
167
|
+
export declare function formatRateLimitMessage(info: RateLimitInfoLike): string;
|
|
168
|
+
/**
|
|
169
|
+
* Construct the appropriate typed error from structured rate-limit info.
|
|
170
|
+
* Billing/credits failures become a non-retryable {@link BillingError};
|
|
171
|
+
* transient throttles become a retryable {@link RateLimitError}.
|
|
172
|
+
*/
|
|
173
|
+
export declare function createRateLimitError(info: RateLimitInfoLike): RateLimitError | BillingError;
|
|
89
174
|
/**
|
|
90
175
|
* Map of error type names to their constructors.
|
|
91
176
|
* Used for deserialization from logs.
|
package/dist/src/lib/errors.js
CHANGED
|
@@ -82,6 +82,115 @@ export class SubprocessError extends SequantError {
|
|
|
82
82
|
this.name = "SubprocessError";
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Transient rate-limit error (HTTP 429-style throttle, overloaded API).
|
|
87
|
+
*
|
|
88
|
+
* Retryable: waiting and re-running can succeed once the limit window resets.
|
|
89
|
+
*/
|
|
90
|
+
export class RateLimitError extends SequantError {
|
|
91
|
+
constructor(message, metadata = {}, cause) {
|
|
92
|
+
super(message, { isRetryable: true, metadata, cause });
|
|
93
|
+
this.name = "RateLimitError";
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Billing / out-of-credits error.
|
|
98
|
+
*
|
|
99
|
+
* NOT retryable: a no-MCP retry (or any retry) cannot refill credits, so the
|
|
100
|
+
* executor must surface the real cause instead of looping. Drives the #592
|
|
101
|
+
* fallback-noise skip in phase-executor.
|
|
102
|
+
*/
|
|
103
|
+
export class BillingError extends SequantError {
|
|
104
|
+
constructor(message, metadata = {}, cause) {
|
|
105
|
+
super(message, { isRetryable: false, metadata, cause });
|
|
106
|
+
this.name = "BillingError";
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* True when the rate-limit info represents a billing/credits failure (which a
|
|
111
|
+
* retry cannot fix), rather than a transient throttle.
|
|
112
|
+
*/
|
|
113
|
+
export function isBillingFailure(info) {
|
|
114
|
+
return (info.errorCode === "credits_required" ||
|
|
115
|
+
info.overageDisabledReason === "out_of_credits");
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* True when the rate-limit info represents an actual failure (rejection or
|
|
119
|
+
* billing), as opposed to an informational `allowed` / `allowed_warning`
|
|
120
|
+
* event. The driver uses this to avoid mis-attributing a stale warning event
|
|
121
|
+
* to an unrelated phase failure.
|
|
122
|
+
*/
|
|
123
|
+
export function isRateLimitFailureInfo(info) {
|
|
124
|
+
return info.status === "rejected" || isBillingFailure(info);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Format a Unix timestamp (seconds or ms) as a local time string.
|
|
128
|
+
*
|
|
129
|
+
* Bare `HH:MM` when the reset falls on the current local calendar day;
|
|
130
|
+
* date-qualified `MM-DD HH:MM` otherwise. Multi-day windows
|
|
131
|
+
* (`rateLimitType: seven_day*`) can reset days out — a bare `HH:MM` there reads
|
|
132
|
+
* as "later today" and misleads the user (#732 QA follow-up), so the date is
|
|
133
|
+
* included whenever the reset is not today.
|
|
134
|
+
*/
|
|
135
|
+
function formatResetTime(resetsAt) {
|
|
136
|
+
// Heuristic: values below ~1e12 are seconds, otherwise milliseconds.
|
|
137
|
+
const ms = resetsAt < 1e12 ? resetsAt * 1000 : resetsAt;
|
|
138
|
+
const d = new Date(ms);
|
|
139
|
+
const hh = String(d.getHours()).padStart(2, "0");
|
|
140
|
+
const mm = String(d.getMinutes()).padStart(2, "0");
|
|
141
|
+
const now = new Date();
|
|
142
|
+
const sameDay = d.getFullYear() === now.getFullYear() &&
|
|
143
|
+
d.getMonth() === now.getMonth() &&
|
|
144
|
+
d.getDate() === now.getDate();
|
|
145
|
+
if (sameDay) {
|
|
146
|
+
return `${hh}:${mm}`;
|
|
147
|
+
}
|
|
148
|
+
const mon = String(d.getMonth() + 1).padStart(2, "0");
|
|
149
|
+
const day = String(d.getDate()).padStart(2, "0");
|
|
150
|
+
return `${mon}-${day} ${hh}:${mm}`;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Build a user-facing message from rate-limit info, naming the real cause:
|
|
154
|
+
* - billing/credits → "Out of credits" (enriched with purchasable vs hard
|
|
155
|
+
* limit when the ≥0.3.181 `canUserPurchaseCredits` field is present)
|
|
156
|
+
* - transient throttle → "Rate limited — resets at HH:MM" (date-qualified as
|
|
157
|
+
* "MM-DD HH:MM" when the reset is not today; reset time omitted entirely when
|
|
158
|
+
* `resetsAt` is absent)
|
|
159
|
+
*/
|
|
160
|
+
export function formatRateLimitMessage(info) {
|
|
161
|
+
if (isBillingFailure(info)) {
|
|
162
|
+
if (info.canUserPurchaseCredits === true) {
|
|
163
|
+
return "Out of credits — purchasable";
|
|
164
|
+
}
|
|
165
|
+
if (info.canUserPurchaseCredits === false) {
|
|
166
|
+
return "Out of credits — hard limit";
|
|
167
|
+
}
|
|
168
|
+
return "Out of credits";
|
|
169
|
+
}
|
|
170
|
+
if (info.resetsAt !== undefined) {
|
|
171
|
+
return `Rate limited — resets at ${formatResetTime(info.resetsAt)}`;
|
|
172
|
+
}
|
|
173
|
+
return "Rate limited";
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Construct the appropriate typed error from structured rate-limit info.
|
|
177
|
+
* Billing/credits failures become a non-retryable {@link BillingError};
|
|
178
|
+
* transient throttles become a retryable {@link RateLimitError}.
|
|
179
|
+
*/
|
|
180
|
+
export function createRateLimitError(info) {
|
|
181
|
+
const message = formatRateLimitMessage(info);
|
|
182
|
+
const metadata = {
|
|
183
|
+
resetsAt: info.resetsAt,
|
|
184
|
+
rateLimitType: info.rateLimitType,
|
|
185
|
+
overageDisabledReason: info.overageDisabledReason,
|
|
186
|
+
errorCode: info.errorCode,
|
|
187
|
+
canUserPurchaseCredits: info.canUserPurchaseCredits,
|
|
188
|
+
hasChargeableSavedPaymentMethod: info.hasChargeableSavedPaymentMethod,
|
|
189
|
+
};
|
|
190
|
+
return isBillingFailure(info)
|
|
191
|
+
? new BillingError(message, metadata)
|
|
192
|
+
: new RateLimitError(message, metadata);
|
|
193
|
+
}
|
|
85
194
|
/**
|
|
86
195
|
* Map of error type names to their constructors.
|
|
87
196
|
* Used for deserialization from logs.
|
|
@@ -94,4 +203,6 @@ export const ERROR_TYPE_MAP = {
|
|
|
94
203
|
BuildError: BuildError,
|
|
95
204
|
TimeoutError: TimeoutError,
|
|
96
205
|
SubprocessError: SubprocessError,
|
|
206
|
+
RateLimitError: RateLimitError,
|
|
207
|
+
BillingError: BillingError,
|
|
97
208
|
};
|
|
@@ -114,6 +114,25 @@ export declare function fetchLatestVersion(): Promise<string | null>;
|
|
|
114
114
|
* Returns: -1 if a < b, 0 if a == b, 1 if a > b
|
|
115
115
|
*/
|
|
116
116
|
export declare function compareVersions(a: string, b: string): number;
|
|
117
|
+
/**
|
|
118
|
+
* Pure preflight check for the running Node version against the engines floor.
|
|
119
|
+
*
|
|
120
|
+
* Returns an actionable, multi-line message when `current` is below `floor`,
|
|
121
|
+
* or `null` when it satisfies the floor (or when `floor` is missing/unparseable,
|
|
122
|
+
* in which case the guard is skipped rather than crashing the CLI).
|
|
123
|
+
*
|
|
124
|
+
* `floor` is the raw `engines.node` value (e.g. ">=22.12.0"); the leading range
|
|
125
|
+
* operator is stripped before comparison. Reuses {@link compareVersions} — no
|
|
126
|
+
* `semver` dependency.
|
|
127
|
+
*/
|
|
128
|
+
export declare function getNodeVersionError(current: string, floor: string | null | undefined): string | null;
|
|
129
|
+
/**
|
|
130
|
+
* Side-effecting wrapper around {@link getNodeVersionError}: prints the message
|
|
131
|
+
* and exits non-zero when the running Node is below the floor. Uses only
|
|
132
|
+
* built-in globals (`process.version`, `console`, `process.exit`) so it runs —
|
|
133
|
+
* rather than crashes — on the old Node it rejects.
|
|
134
|
+
*/
|
|
135
|
+
export declare function assertNodeVersion(floor: string | null | undefined): void;
|
|
117
136
|
/**
|
|
118
137
|
* Check if the current version is outdated
|
|
119
138
|
*/
|