{"record":{"id":"b8f8faed213f974a","repo":"ruvnet/ruflo","slug":"claim-is-protected-by-progress-claim-progress","errorCode":null,"errorMessage":"Claim is protected by progress (${claim.progress}%)","messagePattern":"Claim is protected by progress \\((.+?)%\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"v3/@claude-flow/claims/src/application/work-stealing-service.ts","lineNumber":226,"sourceCode":"    const claim = await this.repository.findByIssueId(issueId);\n\n    if (!claim) {\n      throw new Error(`Claim not found for issue: ${issueId}`);\n    }\n\n    // Check if already stealable\n    if (claim.stealInfo) {\n      return; // Already marked\n    }\n\n    // Check grace period protection\n    if (this.isInGracePeriod(claim)) {\n      throw new Error(`Claim is still in grace period`);\n    }\n\n    // Check progress protection\n    if (this.isProtectedByProgress(claim)) {\n      throw new Error(`Claim is protected by progress (${claim.progress}%)`);\n    }\n\n    // Update claim with stealable info\n    const now = new Date();\n    claim.stealInfo = {\n      ...info,\n      markedAt: now,\n    };\n    claim.stealableAt = now;\n\n    await this.repository.update(claim);\n\n    // Emit event\n    await this.emitMarkedStealableEvent(claim, info);\n  }\n\n  // ===========================================================================\n  // Steal","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/claims/src/application/work-stealing-service.ts#L208-L244","documentation":"Plain Error thrown by markStealable when isProtectedByProgress(claim) is true: the claim's progress field exceeds the configured protection threshold. The intent is that work making real progress should not be taken from its owner. The message includes the current progress percentage for diagnostics.","triggerScenarios":"Calling markStealable on a claim whose progress has advanced past the protection threshold; auto-detection that does not account for recent progress updates; threshold misconfigured too low.","commonSituations":"Stale-detection heuristic keys off inactivity but ignores progress; progress is not being updated so genuinely active work looks idle; threshold too aggressive.","solutions":["Do not mark actively-progressing work as stealable; let the owner continue.","Raise the progress-protection threshold in WorkStealingConfig if your definition of 'active' permits higher progress.","Ensure agents update claim.progress so real work is protected and only stalled work becomes stealable.","Treat the throw as a soft skip in auto-mark loops and continue to the next candidate."],"exampleFix":"// before\nawait workStealing.markStealable(issueId, info); // progress 60% -> throws\n\n// after\nconst claim = await repo.findByIssueId(issueId);\nif (claim.progress < progressThreshold) {\n  await workStealing.markStealable(issueId, info);\n}","handlingStrategy":"validation","validationCode":"const claim = await repository.findByIssueId(issueId);\nif (claim && claim.progress >= progressThreshold) {\n  // actively progressing; do not steal\n  return;\n}\nawait workStealing.markStealable(issueId, info);","typeGuard":null,"tryCatchPattern":"try {\n  await workStealing.markStealable(issueId, info);\n} catch (e) {\n  if (e instanceof Error && /protected by progress/.test(e.message)) {\n    // soft skip: this claim is making progress\n    return;\n  }\n  throw e;\n}","preventionTips":["Ensure agents update claim.progress so active work is protected.","Treat the progress-protection throw as a soft skip in auto-mark loops.","Tune the progress threshold against realistic task velocity."],"tags":["work-stealing","progress","protection","plain-error"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}