diff --git a/src/clawsweeper.ts b/src/clawsweeper.ts index ea142105ae..d96deba3ce 100644 --- a/src/clawsweeper.ts +++ b/src/clawsweeper.ts @@ -5748,13 +5748,13 @@ function publicRealBehaviorProofLine(proof: RealBehaviorProof): string { function publicPrRatingLine(rating: PrRating, proof: RealBehaviorProof): string { const shiny = hasShinyProof(proof) ? " ✨ media proof bonus" : ""; const lines = [ - `Overall ${themedRatingName(rating.overallTier)} with proof ${themedRatingName( - rating.proofTier, - )}${shiny} and patch quality ${themedRatingName(rating.patchTier)}.`, - sentence(rating.summary), + `Overall: ${themedRatingName(rating.overallTier)}`, + `Proof: ${themedRatingName(rating.proofTier)}${shiny}`, + `Patch quality: ${themedRatingName(rating.patchTier)}`, + `Summary: ${sentence(rating.summary)}`, ]; if (rating.nextSteps.length) { - lines.push("", ...rating.nextSteps.slice(0, 3).map((step) => `- ${step}`)); + lines.push("", "Rank-up moves:", ...rating.nextSteps.slice(0, 3).map((step) => `- ${step}`)); } lines.push( "", @@ -9121,37 +9121,8 @@ function collapsedDetailsBlock(summary: string, lines: readonly string[]): strin return ["
", `${summary}`, "", body, "", "
"].join("\n"); } -type ReviewCommentBadge = "DONE" | "INFO" | "SKIP" | "P1" | "P2" | "P3"; - -function renderReviewCommentBadge(badge: ReviewCommentBadge): string { - const symbols: Record = { - DONE: "✅", - INFO: "ℹ️", - SKIP: "⏭️", - P1: "🚨", - P2: "💡", - P3: "🔎", - }; - return `${symbols[badge]} **${badge}**`; -} - -function appendPublicSection( - lines: string[], - heading: string, - body: string, - options: { - badge?: ReviewCommentBadge; - headline?: string; - metadata?: readonly string[]; - } = {}, -): void { - const badge = options.badge ?? "INFO"; - const headline = options.headline ?? heading; - const metadata = (options.metadata ?? []).filter(Boolean); - lines.push(`${renderReviewCommentBadge(badge)} **${heading}** **${headline}**`); - if (body.trim()) lines.push("", body.trim()); - if (metadata.length) lines.push("", ...metadata); - lines.push(""); +function appendPublicSection(lines: string[], heading: string, body: string): void { + lines.push(`**${heading}**`, body, ""); } function publicReproducibilityLine(reproductionAssessment: string): string { @@ -9170,67 +9141,6 @@ function publicSummaryBody(summaryLine: string, reproductionAssessment: string): .join("\n\n"); } -function reviewStatusBadge({ - hasRealBehaviorProofBlocker, - isRepairLoopPass, - isPullRequest, - isRepairCandidate, - hasReviewFindings, -}: { - hasRealBehaviorProofBlocker: boolean; - isRepairLoopPass: boolean; - isPullRequest: boolean; - isRepairCandidate: boolean; - hasReviewFindings: boolean; -}): ReviewCommentBadge { - if (hasRealBehaviorProofBlocker) return "P2"; - if (isRepairLoopPass) return "DONE"; - if (isPullRequest && isRepairCandidate) return "P2"; - if (hasReviewFindings) return "P2"; - if (isPullRequest) return "INFO"; - return "INFO"; -} - -function reviewStatusHeadline({ - hasRealBehaviorProofBlocker, - isRepairLoopPass, - isPullRequest, - isRepairCandidate, - hasReviewFindings, -}: { - hasRealBehaviorProofBlocker: boolean; - isRepairLoopPass: boolean; - isPullRequest: boolean; - isRepairCandidate: boolean; - hasReviewFindings: boolean; -}): string { - if (hasRealBehaviorProofBlocker) return "Needs real behavior proof before merge"; - if (isRepairLoopPass) return "Passed review"; - if (isPullRequest && isRepairCandidate) return "Needs changes before merge"; - if (hasReviewFindings) return "Found issues before merge"; - if (isPullRequest) return "Needs maintainer review before merge"; - return "Keep open for maintainer follow-up"; -} - -function legacyReviewStatusLine(headline: string): string { - if (headline === "Passed review") return "Codex review: passed."; - if (headline === "Needs real behavior proof before merge") { - return "Codex review: needs real behavior proof before merge."; - } - if (headline === "Needs changes before merge") return "Codex review: needs changes before merge."; - if (headline === "Found issues before merge") return "Codex review: found issues before merge."; - if (headline === "Needs maintainer review before merge") { - return "Codex review: needs maintainer review before merge."; - } - return `Codex review: ${headline.toLowerCase()}.`; -} - -function reviewedHeadFooter(markdown: string): string { - const sha = frontMatterValue(markdown, "pull_head_sha"); - const reviewed = sha ? ` · reviewed against ${String(sha).slice(0, 12)}` : ""; - return `_ClawSweeper 🐠${reviewed}._`; -} - function publicMergeRiskLine( risks: string, nextStepLine: string, @@ -9432,18 +9342,18 @@ function renderKeepOpenCommentFromReport( : ""; const details: string[] = []; const hasReviewFindings = isPullRequest && reviewFindings.length > 0; - const statusContext = { - hasRealBehaviorProofBlocker, - isRepairLoopPass, - isPullRequest, - isRepairCandidate, - hasReviewFindings, - }; const lines = [ - `${renderReviewCommentBadge(reviewStatusBadge(statusContext))} **Codex review** **${reviewStatusHeadline( - statusContext, - )}**`, - ``, + hasRealBehaviorProofBlocker + ? "Codex review: needs real behavior proof before merge." + : isRepairLoopPass + ? "Codex review: passed." + : isPullRequest && isRepairCandidate + ? "Codex review: needs changes before merge." + : hasReviewFindings + ? "Codex review: found issues before merge." + : isPullRequest + ? "Codex review: needs maintainer review before merge." + : "Codex review: keeping this open for maintainer follow-up; there is still a little grit to resolve.", "", ...reviewWorkflowCallout(), ]; @@ -9452,13 +9362,9 @@ function renderKeepOpenCommentFromReport( lines, "Summary", publicSummaryBody(changeSummaryLine, reproductionAssessment), - { badge: "INFO", headline: "Review the changed behavior" }, ); } else { - appendPublicSection(lines, "Summary", publicSummaryBody(summaryLine, reproductionAssessment), { - badge: "INFO", - headline: "Review the reported behavior", - }); + appendPublicSection(lines, "Summary", publicSummaryBody(summaryLine, reproductionAssessment)); } if (!isPullRequest) { const reproductionHelp = issueReproductionHelpSuggestions(markdown); @@ -9466,71 +9372,28 @@ function renderKeepOpenCommentFromReport( appendPublicSection( lines, "Ways to help us reproduce this", - "The report is still missing enough real-world detail to reproduce the issue confidently.", - { - badge: "P3", - headline: "Add concrete reproduction evidence", - metadata: reproductionHelp.map((suggestion) => `- ${suggestion}`), - }, + reproductionHelp.map((suggestion) => `- ${suggestion}`).join("\n"), ); } } if (isPullRequest) { - appendPublicSection(lines, "PR rating", publicPrRatingLine(prRating, realBehaviorProof), { - badge: isRepairLoopPass ? "DONE" : "INFO", - headline: "Rate readiness from proof and patch quality", - }); + appendPublicSection(lines, "PR rating", publicPrRatingLine(prRating, realBehaviorProof)); appendPublicSection( lines, "Real behavior proof", publicRealBehaviorProofLine(realBehaviorProof), - { - badge: realBehaviorProofBlocksMerge(markdown) ? "P2" : "DONE", - headline: "Assess whether proof is merge-ready", - }, ); } const mantisSuggestion = isPullRequest ? publicMantisRecommendationBlock(mantisRecommendation) : ""; - if (mantisSuggestion) { - appendPublicSection(lines, "Mantis proof suggestion", mantisSuggestion, { - badge: "INFO", - headline: "Collect stronger validation evidence", - }); - } - if (mergeRiskLine) { - appendPublicSection(lines, "Risk before merge", mergeRiskLine, { - badge: "P2", - headline: "Resolve the remaining merge risk", - }); - } - appendPublicSection(lines, isPullRequest ? "Next step before merge" : "Next step", nextStepLine, { - badge: isRepairLoopPass ? "DONE" : isRepairCandidate ? "P2" : "INFO", - headline: isPullRequest ? "Take the next merge decision" : "Take the next triage step", - }); + if (mantisSuggestion) appendPublicSection(lines, "Mantis proof suggestion", mantisSuggestion); + if (mergeRiskLine) appendPublicSection(lines, "Risk before merge", mergeRiskLine); + appendPublicSection(lines, isPullRequest ? "Next step before merge" : "Next step", nextStepLine); const securityLine = publicSecurityReviewLine(securityReview); - if (securityLine) { - appendPublicSection(lines, "Security", securityLine, { - badge: securityReview.status === "needs_attention" ? "P2" : "DONE", - headline: - securityReview.status === "needs_attention" - ? "Confirm the security-sensitive change" - : "No security blocker found", - }); - } + if (securityLine) appendPublicSection(lines, "Security", securityLine); if (isPullRequest && reviewFindings.length) { - const highestPriority = Math.min(...reviewFindings.map((finding) => finding.priority)); - appendPublicSection( - lines, - "Review findings", - "ClawSweeper found focused review comments that should be addressed before merge.", - { - badge: highestPriority === 1 ? "P1" : highestPriority === 2 ? "P2" : "P3", - headline: "Address the highest-signal findings", - metadata: reviewFindings.slice(0, 3).map(reviewFindingSummaryLine), - }, - ); + lines.push("**Review findings**", ...reviewFindings.slice(0, 3).map(reviewFindingSummaryLine)); } if (bestSolutionLine && publicReviewTextDiffers(bestSolutionLine, nextStepLine)) { details.push("Best possible solution:", "", bestSolutionLine); @@ -9587,7 +9450,6 @@ function renderKeepOpenCommentFromReport( if (reviewLine) details.push("", reviewLine); const detailsBlock = collapsedDetailsBlock("Review details", details); if (detailsBlock) lines.push("", detailsBlock); - lines.push("", reviewedHeadFooter(markdown)); return sanitizePublicSelfReferences( lines.join("\n"), Number(frontMatterValue(markdown, "number")), diff --git a/src/repair/comment-router-core.ts b/src/repair/comment-router-core.ts index a399a14aba..9dfbf1c4cf 100644 --- a/src/repair/comment-router-core.ts +++ b/src/repair/comment-router-core.ts @@ -1141,7 +1141,7 @@ function markdownSection(body: string, heading: string) { const escaped = heading.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); const match = String(body ?? "").match( new RegExp( - `(?:^|\\n)(?:\\*\\*${escaped}\\*\\*|(?:✅|ℹ️|⏭️|🚨|💡|🔎)\\s+\\*\\*(?:DONE|INFO|SKIP|P[123])\\*\\*\\s+\\*\\*${escaped}\\*\\*\\s+\\*\\*[^\\n*]+\\*\\*)\\s*\\n([\\s\\S]*?)(?=\\n\\n(?:\\*\\*|(?:✅|ℹ️|⏭️|🚨|💡|🔎)\\s+\\*\\*)|\\n|\\n/); - assert.match(body, /⏭️ \*\*SKIP\*\* \*\*No branch changes were pushed\*\*/); - assert.match(body, /did not find a safe narrow repair to push/i); + assert.match(body, /(without changing|no-op|No new branch changes|no safe branch change)/i); assert.doesNotMatch(body, /Target: #74156/); assert.doesNotMatch(body, /#74156/); assert.doesNotMatch(body, /issuecomment-/); assert.match(body, /Executor outcome: no planned fix actions\./); assert.match(body, /`route_security` on `this PR`: planned - central handling required/); - assert.match(body, /No branch update, rebase, replacement PR, merge/i); - assert.match(body, /ClawSweeper 🐠/); + assert.match( + body, + /(No branch push|No push|left the PR as-is|Nothing moved downstream|observational only)/i, + ); assert.match(body, /model gpt-test, reasoning medium; reviewed against 0123456789ab/); }); test("repairContributorBranchComment avoids self PR references", () => { const body = repairContributorBranchComment({ sourcePrUrl: "https://github.com/openclaw/openclaw/pull/75183", - validationCommands: ["pnpm check:changed", 'node -e "console.log(`ok`)"'], + validationCommands: ["pnpm check:changed"], provenance: { model: "gpt-test", reasoning: "medium", reviewedSha: "abcdef1234567890" }, }); - assert.match(body, /✅ \*\*DONE\*\* \*\*Repair pushed to the source branch\*\*/); - assert.match(body, /Validation: `pnpm check:changed`/); - assert.match(body, /``node -e "console\.log\(`ok`\)"``/); + assert.match(body, /reef update/); + assert.match(body, /Validation: pnpm check:changed/); assert.doesNotMatch(body, /Source PR:/); assert.doesNotMatch(body, /75183/); }); @@ -74,8 +73,7 @@ test("replacement comments explain no push rights and keep co-author credit visi contributorCredits, provenance, }); - assert.match(linkBody, /ℹ️ \*\*INFO\*\* \*\*Replacement PR opened from a writable branch\*\*/); - assert.match(linkBody, /push rights/i); + assert.match(linkBody, /Why replacement: .*push rights/i); assert.match(linkBody, /Source PR status: left open/i); assert.match( linkBody, @@ -87,11 +85,7 @@ test("replacement comments explain no push rights and keep co-author credit visi contributorCredits, provenance, }); - assert.match( - closeBody, - /✅ \*\*DONE\*\* \*\*Source PR closed after opening credited replacement\*\*/, - ); - assert.match(closeBody, /push rights/i); + assert.match(closeBody, /Why replacement: .*push rights/i); assert.match(closeBody, /Why close: .*credited replacement PR is open/i); assert.match( closeBody, @@ -195,37 +189,6 @@ test("external message provenance normalizes accidental xhigh reasoning", () => }); assert.equal(provenance.reasoning, "high"); - assert.match(body, /ClawSweeper 🐠/); assert.match(body, /model gpt-test, reasoning high/); assert.doesNotMatch(body, /reasoning xhigh/); }); - -test("sample external messages use Codex-style hierarchy and bounded paragraphs", () => { - for (const sample of sampleExternalMessages()) { - const lines = sample.body.split("\n"); - const hierarchyLine = lines.find((line) => - /^(?:✅|ℹ️|⏭️|💡) \*\*(?:DONE|INFO|SKIP|P2|P3)\*\* \*\*[^*]+\*\*$/.test(line), - ); - assert.ok(hierarchyLine, `${sample.title} should include a badge and headline`); - - const paragraphs = sample.body - .split(/\n{2,}/) - .map((paragraph) => paragraph.replace(/\n/g, " ").trim()) - .filter(Boolean); - for (const paragraph of paragraphs) { - assert.ok( - paragraph.length <= 700, - `${sample.title} has an overly long paragraph: ${paragraph.length} chars`, - ); - } - - const bodyWithoutCodeSpans = sample.body.replace(/`[^`\n]+`/g, ""); - const commandLikeTokens = - bodyWithoutCodeSpans.match(/\b(?:pnpm|npm|bun|node|cargo|swift)\s+[^\n`]+/g) ?? []; - assert.deepEqual( - commandLikeTokens, - [], - `${sample.title} has command-like text outside inline code: ${commandLikeTokens.join(", ")}`, - ); - } -});