specrails-hub 1.58.1 → 1.58.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specrails-hub",
3
- "version": "1.58.1",
3
+ "version": "1.58.2",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1831,7 +1831,11 @@ function createProjectRouter(registry) {
1831
1831
  // by the codex adapter (it doesn't read extraArgs that don't apply).
1832
1832
  const adapter = (0, providers_1.getAdapter)(provider);
1833
1833
  const toolFlags = provider === 'claude' ? (0, context_scope_1.toolFlagsForScope)(quickScope) : { args: [] };
1834
- const claudeMaxTurns = quickScope.full ? 6 : (hasAttachments ? 3 : 1);
1834
+ // Full scope grants Read/Grep/Glob. The model spends turns exploring the
1835
+ // repo before it writes the spec; 6 was too tight (a few tool calls on a
1836
+ // sparse/empty repo hit error_max_turns → exit 1 → opaque failure). 15
1837
+ // leaves comfortable headroom while --max-turns still bounds runaway loops.
1838
+ const claudeMaxTurns = quickScope.full ? 15 : (hasAttachments ? 3 : 1);
1835
1839
  const args = adapter.buildArgs('spec-gen', {
1836
1840
  prompt: userPrompt,
1837
1841
  systemPrompt,
@@ -1964,7 +1968,18 @@ function createProjectRouter(registry) {
1964
1968
  child.on('close', async (code) => {
1965
1969
  clearSpecGenWatchdog();
1966
1970
  let createdTicketId = null;
1967
- if (code === 0 && buffer.trim()) {
1971
+ // When claude burns its whole --max-turns budget it exits non-zero with
1972
+ // a result event of subtype:error_max_turns — but it may already have
1973
+ // emitted a complete spec. Salvage that usable output instead of failing
1974
+ // the whole request on an exit code.
1975
+ const resultSubtype = lastResultEvent?.subtype ?? null;
1976
+ const hasUsableSpec = buffer.trim().length > 0 && /##\s*Spec Title/i.test(buffer);
1977
+ const salvageMaxTurns = code !== 0 && resultSubtype === 'error_max_turns' && hasUsableSpec;
1978
+ if ((code === 0 && buffer.trim()) || salvageMaxTurns) {
1979
+ if (salvageMaxTurns) {
1980
+ console.warn(`[project-router] spec-gen salvaged partial output after error_max_turns (${requestId}); ` +
1981
+ `consider raising --max-turns if this recurs`);
1982
+ }
1968
1983
  // Extract title from generated spec
1969
1984
  const titleMatch = buffer.match(/##\s*Spec Title\s*\n+(.+)/);
1970
1985
  const specTitle = titleMatch ? titleMatch[1].trim() : idea.trim().slice(0, 80);
@@ -2088,7 +2103,11 @@ function createProjectRouter(registry) {
2088
2103
  }
2089
2104
  }
2090
2105
  else {
2091
- const reason = code === 0 ? 'Empty response from AI' : `Process exited with code ${code}`;
2106
+ const reason = code === 0
2107
+ ? 'Empty response from AI'
2108
+ : resultSubtype === 'error_max_turns'
2109
+ ? 'AI hit its turn limit before finishing the spec. Try again, or narrow the idea / turn off full-codebase context.'
2110
+ : `Process exited with code ${code}`;
2092
2111
  console.error(`[project-router] spec-gen failed (${requestId}): ${reason}` +
2093
2112
  (stderrBuf.trim() ? `\n stderr: ${stderrBuf.trim()}` : '') +
2094
2113
  (buffer.trim() ? `\n stdout-buffer: ${buffer.trim().slice(0, 500)}` : ''));
@@ -44,6 +44,14 @@ const COMMON_FLAGS = [
44
44
  '--tools', 'default',
45
45
  '--output-format', 'stream-json',
46
46
  '--verbose',
47
+ // Isolate hub-spawned claude from the *user's* global Claude config. Without
48
+ // this, the child loads ~/.claude (user CLAUDE.md memory, plugins like
49
+ // claude-mem, SessionStart hooks). That bled cross-project memory into
50
+ // Explore turns (e.g. an unrelated "fighting game" surfaced for a fresh
51
+ // project) and inflated spec-gen tool usage past --max-turns. `project,local`
52
+ // still loads the target repo's own .claude settings + CLAUDE.md, which is
53
+ // exactly the context a hub run should see.
54
+ '--setting-sources', 'project,local',
47
55
  ];
48
56
  function buildClaudeArgs(action, opts) {
49
57
  const args = [];