create-claude-workspace 1.1.103 → 1.1.104

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.
@@ -148,7 +148,7 @@ Options:
148
148
  --max-turns <n> Max turns per Claude invocation (default: 50)
149
149
  --delay <ms> Pause between tasks (default: 5000)
150
150
  --cooldown <ms> Wait after error (default: 60000)
151
- --process-timeout <ms> Max wall-clock time per invocation (default: 7200000 = 2h)
151
+ --process-timeout <ms> Max wall-clock time per invocation (default: 14400000 = 4h)
152
152
  --activity-timeout <ms> Max silence before kill (default: 900000 = 15min)
153
153
  --post-result-timeout <ms> Max wait after result (default: 30000 = 30s)
154
154
  --project-dir <path> Project directory (default: cwd)
@@ -21,21 +21,22 @@ export function classifyError(signals) {
21
21
  return 'auth_expired';
22
22
  if (signals.isAuthServerError)
23
23
  return 'auth_server_error';
24
- // Usage limit (account quota) takes priority over rate limit — it's hours, not seconds
25
- if (signals.isUsageLimit)
26
- return 'usage_limit';
27
- if (signals.isRateLimit)
28
- return 'rate_limited';
24
+ // Timeouts take priority over rate limit — timeout is the actual kill reason,
25
+ // rate limit is just a transient event that may have occurred during a 2h+ run.
26
+ // Without this, a normal process_timeout gets misclassified as rate_limited.
29
27
  if (signals.timedOut) {
30
- // Double-check stderr for auth errors (may not have been caught by stream events)
31
28
  if (/authentication_error|failed to authenticate|api error: 401|oauth token has expired/i.test(signals.stderr)) {
32
29
  return 'auth_expired';
33
30
  }
34
31
  return 'process_timeout';
35
32
  }
36
- // Activity timeout after result = success (process just hung after finishing)
37
33
  if (signals.activityTimedOut)
38
34
  return signals.hasResult ? 'none' : 'activity_timeout';
35
+ // Usage limit (account quota) takes priority over rate limit — it's hours, not seconds
36
+ if (signals.isUsageLimit)
37
+ return 'usage_limit';
38
+ if (signals.isRateLimit)
39
+ return 'rate_limited';
39
40
  // Clean exit
40
41
  if (signals.code === 0)
41
42
  return 'none';
@@ -78,9 +78,15 @@ describe('classifyError', () => {
78
78
  it('flag priority: auth flag wins over stderr patterns', () => {
79
79
  expect(classifyError({ ...base, isAuthError: true, stderr: 'rate limit' })).toBe('auth_expired');
80
80
  });
81
- it('flag priority: rate limit flag wins over timeout', () => {
81
+ it('flag priority: rate limit flag detected when not timed out', () => {
82
82
  expect(classifyError({ ...base, isRateLimit: true, timedOut: false })).toBe('rate_limited');
83
83
  });
84
+ it('flag priority: timeout wins over rate limit (rate limit is transient during long run)', () => {
85
+ expect(classifyError({ ...base, isRateLimit: true, timedOut: true })).toBe('process_timeout');
86
+ });
87
+ it('flag priority: activity timeout wins over rate limit', () => {
88
+ expect(classifyError({ ...base, isRateLimit: true, activityTimedOut: true })).toBe('activity_timeout');
89
+ });
84
90
  it('returns none when clean exit with result despite transient rate limit', () => {
85
91
  expect(classifyError({ ...base, code: 0, hasResult: true, isRateLimit: true })).toBe('none');
86
92
  });
@@ -659,8 +659,8 @@ describe('Loop integration: classifyError → getErrorAction → checkpoint', ()
659
659
  it('auth error beats auth server error', () => {
660
660
  expect(classifyError({ ...base, isAuthError: true, isAuthServerError: true })).toBe('auth_expired');
661
661
  });
662
- it('rate limit beats process timeout on non-zero exit', () => {
663
- expect(classifyError({ ...base, code: 1, isRateLimit: true, timedOut: true })).toBe('rate_limited');
662
+ it('process timeout beats rate limit (timeout is actual kill reason, rate limit is transient)', () => {
663
+ expect(classifyError({ ...base, code: 1, isRateLimit: true, timedOut: true })).toBe('process_timeout');
664
664
  });
665
665
  it('process timeout beats activity timeout', () => {
666
666
  expect(classifyError({ ...base, timedOut: true, activityTimedOut: true })).toBe('process_timeout');
@@ -7,7 +7,7 @@ export const DEFAULTS = {
7
7
  projectDir: process.cwd(),
8
8
  skipPermissions: false,
9
9
  resumeSession: null,
10
- processTimeout: 2 * 60 * 60_000,
10
+ processTimeout: 4 * 60 * 60_000,
11
11
  activityTimeout: 15 * 60_000,
12
12
  postResultTimeout: 30_000,
13
13
  logFile: '.claude/autonomous.log',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-claude-workspace",
3
- "version": "1.1.103",
3
+ "version": "1.1.104",
4
4
  "description": "Scaffold a project with Claude Code agents for autonomous AI-driven development",
5
5
  "type": "module",
6
6
  "bin": {