Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ checkpoint, and status-only commits are intentionally omitted.

### Changed

- Made ClawHub diversion comments a practical self-serve handoff with package-shape, manifest, configuration, documentation, usage, and smoke-proof guidance. Thanks @brokemac79.
- Reduced duplicate GitHub API reads in each live-dashboard status snapshot and batched recent automerge hydration into one GraphQL request with a REST fallback. Thanks @brokemac79.
- Raised the apply-existing close limit and checkpoint size from 5 to 20 fresh closes per run so continuation chains drain the proposal queue faster while each GitHub App token stays within its lifetime.
- Restored the global Codex worker budget to 128, reserved 24 slots for interactive work and matrix expansion, and let serialized background planners refill capacity while older review waves finish publishing.
Expand Down
1 change: 1 addition & 0 deletions prompts/review-item.md
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ Close only when the evidence is strong and the repository policy allows it. Allo
- `mostly_implemented_on_main`: an older PR is more than 60 days old, current `main` already implements the central useful part of the PR, and no meaningful unique remainder should be merged from the branch. Use only for pull requests, not issues. The close comment must say what part is already on `main`, what leftover part is minor/obsolete/superseded or separately tracked, and why keeping the stale branch open is not useful.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not current mani report

- `cannot_reproduce`: you tried a reasonable reproduction path against current `main` and it does not reproduce, or the report is obsolete and no longer matches current behavior.
- `clawhub`: useful idea, but it belongs as a ClawHub skill/plugin rather than OpenClaw core. Use `VISION.md` as the scope anchor. Prefer this when the requested capability is optional integration/provider/channel/skill/bundle/MCP work, can be built with current skill/MCP/plugin surfaces, has no concrete missing core extension API, and has no protected maintainer signal. This includes service-specific channels, providers, optional skills, and plugin-discovery/publishing ideas when the current plugin or bundle-style interface is sufficient. For OpenClaw PRs that only add bundled skills under paths like `skills/<vendor>/**`, set `itemCategory: "skill"` and prefer `closeReason: "clawhub"` with high confidence; the close comment should ask the contributor to upload or publish it through ClawHub.com instead of bundling it in OpenClaw core. Keep open when the item reports a regression in bundled core behavior, identifies a missing plugin API needed before external implementation is possible, involves security/core hardening, or clearly needs explicit maintainer product judgment.
For `clawhub` closes, make `bestSolution` and `closeComment` useful as a self-serve handoff: identify the likely package shape such as skill, plugin, provider, channel, bundle, or MCP integration; list manifest/package basics to verify, such as metadata, entrypoint, permissions, secrets/config, install/update docs, example usage, and smoke proof; and explicitly state that ClawSweeper should not open a ClawHub issue, open a ClawHub PR, create a tracking issue, or publish the package on the contributor's behalf.
- `duplicate_or_superseded`: another issue/PR already tracks the same remaining work, or the linked discussion/PR clearly supersedes this item. Link the canonical item and explain whether it is open or closed/merged. For clusters with the same root cause, keep one canonical issue open and close satellites when their unique logs, platforms, or context can be preserved by linking them in the close comment. For PR-to-PR supersession, the canonical PR must be merged or still open, proof-positive, and viable; do not treat a closed-unmerged, F/no-proof, proposed-close, not-cleanly-mergeable, or otherwise unsafe PR as a reason to close another PR. Unique evidence blocks duplicate close only when it implies a distinct root cause, platform-specific fix, or separate remaining product behavior.
- `low_signal_unmergeable_pr`: a pull request may contain a small useful idea, but the submitted branch is net-negative and should not stay open as a landing candidate because most of the diff is unrelated, copied, generated, bloated, internally incoherent, or conflicts with the repository's existing structure. Use this for PRs like a narrow docs title that inserts a large unrelated reference block, a tiny bug fix mixed with broad unrelated rewrites, or generated/vendor/config churn unrelated to the stated purpose. The close comment must acknowledge any useful part, explain the concrete unmergeable diff, and invite a new narrow PR for the useful change. Do not use this when the PR has meaningful unique work that can be repaired without throwing away most of the branch, when maintainers asked to preserve/adopt the branch, when a protected label or maintainer author requires human judgment, or when the only issue is ordinary test coverage, style, or review follow-up. When the only blocker is missing real-behavior proof on an idle low-rated PR, use `stalled_unproven_pr` instead.
- `stalled_unproven_pr`: an external (non-maintainer) pull request was asked for real-behavior proof and the ask expired. Use this only when every condition is true: the item is a pull request from a non-maintainer author; `realBehaviorProof.status` is `missing`, `mock_only`, or `insufficient`; `prRating.overallTier` is `D` or `F`; the PR is at least 14 days old; the head branch shows no new commit or check activity for at least 14 days; a dated proof ask is visible on the PR — a `status: 📣 needs proof` or `triage: needs-real-behavior-proof` label applied at least 14 days ago, or a proof-nudge comment at least 14 days old — so the contributor had a real window to respond; and there is no maintainer engagement (assignee, requested reviewer, maintainer comment or review) and no `clawsweeper:human-review`, `clawsweeper:manual-only`, `clawsweeper:autofix`, or `clawsweeper:automerge` label. Do not use it for draft PRs (drafts belong to `abandoned_pr` at 30 days), for PRs whose only gap is minor follow-up on an otherwise well-rated patch, or when a `proof: sufficient` or `proof: override` label is present. The close comment must name the missing proof kind and invite reopening this PR or opening a fresh one with real-behavior proof such as a live run, logs, or a reproducible validation transcript.
Expand Down
15 changes: 14 additions & 1 deletion src/clawsweeper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9072,7 +9072,7 @@ function closeOutro(reason: CloseReason, canonicalLinks: string[] = []): string
case "mostly_implemented_on_main":
return "So I’m closing this older PR as already covered on `main` rather than keeping a mostly-duplicated branch open.";
case "clawhub":
return `So I’m closing this as a scope-fit item for the plugin/community path. Please upload or publish it through ${markdownLink("ClawHub.com", targetProfile().communityUrl ?? "https://clawhub.ai/")} so it can live as an installable community skill instead of a bundled OpenClaw core change.`;
return `So I’m closing this as a scope-fit item for the plugin/community path. Please upload or publish it through ${markdownLink("ClawHub.com", targetProfile().communityUrl ?? "https://clawhub.ai/")} so it can live as an installable ClawHub package instead of a bundled OpenClaw core change.`;
case "duplicate_or_superseded":
return canonicalLinks.length
? `So I’m closing this here and keeping the remaining discussion on ${formatCanonicalLinks(canonicalLinks)}.`
Expand All @@ -9092,6 +9092,17 @@ function closeOutro(reason: CloseReason, canonicalLinks: string[] = []): string
}
}

function closeClawHubHandoffBlock(reason: CloseReason): string {
if (reason !== "clawhub") return "";
return [
"If you want to carry this forward, package it as a self-serve ClawHub item rather than a core patch:",
"",
"- Scope: choose the smallest skill, plugin, provider, channel, bundle, or MCP integration that matches the requested capability.",
"- Checklist: include package metadata/manifest, entrypoint, required permissions, secrets/config notes, install/update docs, example usage, and a smoke test or proof command.",
"- Boundary: ClawSweeper will not open a ClawHub issue or PR, create a tracking issue, or publish the package automatically; the contributor should create that ClawHub work separately.",
].join("\n");
}

function issueOrPullReferenceNumbers(value: string): string[] {
return [
...value.matchAll(
Expand Down Expand Up @@ -14328,6 +14339,8 @@ function renderCloseComment(options: {
if (evidence.length) details.push("", "What I checked:", "", ...evidence);
if (likelyOwners.length) details.push("", "Likely related people:", "", ...likelyOwners);

const clawhubHandoff = closeClawHubHandoffBlock(options.reason);
if (clawhubHandoff) lines.push("", "**ClawHub handoff**", clawhubHandoff);
const outro = closeOutro(options.reason, canonicalLinks);
if (outro) lines.push("", outro);
if (options.reviewLine) details.push("", options.reviewLine);
Expand Down
6 changes: 5 additions & 1 deletion test/review-close-policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,11 @@ test("skill-only OpenClaw PRs can close through ClawHub with upload guidance", (
assert.equal(action.actionTaken, "proposed_close");
assert.match(action.closeComment, /ClawHub\.com/);
assert.match(action.closeComment, /upload or publish/i);
assert.match(action.closeComment, /installable community skill/);
assert.match(action.closeComment, /ClawHub handoff/);
assert.match(action.closeComment, /skill, plugin, provider, channel, bundle, or MCP integration/);
assert.match(action.closeComment, /package metadata\/manifest/);
assert.match(action.closeComment, /will not open a ClawHub issue or PR/);
assert.match(action.closeComment, /installable ClawHub package/);
});

test("ClawHub policy allows main-implemented issue and PR close proposals", () => {
Expand Down
12 changes: 12 additions & 0 deletions test/review-prompt-policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,18 @@ test("review prompt treats plugin API changes as compatibility-sensitive P1 repa
);
});

test("review prompt makes ClawHub closes a self-serve handoff", () => {
const prompt = readFileSync("prompts/review-item.md", "utf8");

assert.match(prompt, /For `clawhub` closes/);
assert.match(prompt, /self-serve handoff/);
assert.match(prompt, /skill, plugin, provider, channel, bundle, or MCP integration/);
assert.match(prompt, /metadata, entrypoint, permissions, secrets\/config/);
assert.match(prompt, /should not open a ClawHub issue/);
assert.match(prompt, /open a ClawHub PR/);
assert.match(prompt, /publish the package on the contributor's behalf/);
});

test("review prompt requires upgrade and preference overwrite checks", () => {
const prompt = readFileSync("prompts/review-item.md", "utf8");

Expand Down