fix(runner): NODE_PATH voor pg-resolution + cache-bust ARG + soft quota-probe
Drie kleine fixes voor de runner uit PBI-4 die in een lokale smoke-test
naar boven kwamen:
1. NODE_PATH=/opt/scrum4me-mcp/node_modules in Dockerfile ENV — anders
vindt tsx de top-level `pg` import in bin/run-one-job.ts niet (resolve
start vanaf /opt/agent/bin/, zoekt geen scrum4me-mcp/node_modules).
2. ARG MCP_CACHE_BUST in Dockerfile vóór de scrum4me-mcp clone-laag.
BuildKit cached anders de clone op MCP_GIT_REF=main, ook als main
intussen nieuwere commits heeft. Rebuild met
`--build-arg MCP_CACHE_BUST=$(date +%s)` invalidate't deze laag
deterministisch.
3. quotaProbe in run-one-job.ts soft-failt nu bij niet-zero exit, geen
pct-veld, of geen rate-limit-headers in response. De Anthropic API
retourneert niet altijd headers; dit zou de runner niet hard moeten
crashen. Komt overeen met CLAUDE.md stap 0.4 ("anders: ga door").
Lokale smoke-test bevestigt nu dat een IDEA_GRILL job correct geclaimd
wordt met `--model=claude-sonnet-4-6 --permission-mode=plan --effort=high`
en de juiste 10 allowed_tools.
Apart probleem ontdekt (NIET in deze PR): IDEA_GRILL/IDEA_MAKE_PLAN/
PLAN_CHAT draaien default in --permission-mode plan. In autonomous batch-
mode kan Claude in plan-mode mogelijk geen update_job_status aanroepen
(plan-mode wacht op human approval), waardoor jobs FAILED raken na
2x lease-expiry. Verdient eigen issue/PR voor permission_mode review.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
51a7c5dd7b
commit
4d28e084dd
2 changed files with 20 additions and 10 deletions
10
Dockerfile
10
Dockerfile
|
|
@ -55,8 +55,13 @@ RUN curl -fsSL https://claude.ai/install.sh | bash -s ${CLAUDE_CODE_VERSION} \
|
|||
# niet om te builden. Pin via build-arg; default = main.
|
||||
ARG MCP_GIT_REPO=https://github.com/madhura68/scrum4me-mcp.git
|
||||
ARG MCP_GIT_REF=main
|
||||
# Cache-bust voor de clone-laag: hetzelfde MCP_GIT_REF kan tussen rebuilds
|
||||
# een ander commit aanwijzen (bv. main na een merge). Geef als build-arg
|
||||
# `--build-arg MCP_CACHE_BUST=$(date +%s)` mee om deze laag te invalidaten.
|
||||
ARG MCP_CACHE_BUST=1
|
||||
|
||||
RUN git clone --branch ${MCP_GIT_REF} --depth 1 \
|
||||
RUN echo "cache-bust=${MCP_CACHE_BUST}" \
|
||||
&& git clone --branch ${MCP_GIT_REF} --depth 1 \
|
||||
${MCP_GIT_REPO} /opt/scrum4me-mcp \
|
||||
&& cd /opt/scrum4me-mcp \
|
||||
&& npm ci --omit=dev --omit=optional || npm install --omit=dev \
|
||||
|
|
@ -112,7 +117,8 @@ ENV PATH=/opt/agent/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:
|
|||
AGENT_REPO_CACHE=/var/cache/repos \
|
||||
AGENT_JOB_ROOT=/tmp \
|
||||
AGENT_HEALTH_PORT=8080 \
|
||||
SCRUM4ME_MCP_DIR=/opt/scrum4me-mcp
|
||||
SCRUM4ME_MCP_DIR=/opt/scrum4me-mcp \
|
||||
NODE_PATH=/opt/scrum4me-mcp/node_modules
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
|
|
|
|||
|
|
@ -60,24 +60,28 @@ const TOKEN_EXPIRY_PATTERNS: RegExp[] = [
|
|||
]
|
||||
|
||||
// ----- quota probe ----------------------------------------------------
|
||||
// Soft-fail: als de probe geen rate-limit-headers krijgt (sommige Anthropic
|
||||
// endpoints retourneren ze niet) of een transient netwerkfout heeft, log
|
||||
// een warning en ga door. Alleen bij gemeten quota-overschrijding sleepen.
|
||||
// Dit spiegelt het gedrag van CLAUDE.md stap 0.4 ("anders: ga door").
|
||||
async function quotaProbe(userId: string): Promise<void> {
|
||||
const probe = spawnSync(QUOTA_PROBE_PATH, [], { encoding: 'utf8' })
|
||||
if (probe.status !== 0) {
|
||||
logError(
|
||||
`quota probe failed: status=${probe.status} stderr=${(probe.stderr ?? '').trim()}`,
|
||||
log(
|
||||
`quota probe non-zero status=${probe.status} stdout=${probe.stdout.slice(0, 200).trim()} — continuing without gate`,
|
||||
)
|
||||
throw new Error('quota probe failed')
|
||||
return
|
||||
}
|
||||
let parsed: { pct?: number; limit?: number; remaining?: number; reset_at_iso?: string }
|
||||
let parsed: { pct?: number; limit?: number; remaining?: number; reset_at_iso?: string; error?: string }
|
||||
try {
|
||||
parsed = JSON.parse(probe.stdout)
|
||||
} catch {
|
||||
logError(`quota probe stdout not JSON: ${probe.stdout.slice(0, 200)}`)
|
||||
throw new Error('quota probe stdout invalid')
|
||||
log(`quota probe stdout not JSON (continuing): ${probe.stdout.slice(0, 200)}`)
|
||||
return
|
||||
}
|
||||
if (parsed.pct === undefined) {
|
||||
logError(`quota probe missing pct field: ${probe.stdout.slice(0, 200)}`)
|
||||
throw new Error('quota probe missing pct')
|
||||
log(`quota probe no pct (continuing): error=${parsed.error ?? '-'}`)
|
||||
return
|
||||
}
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue