diff --git a/AGENTS.md b/AGENTS.md index 8b01782..7fcfaf5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -47,6 +47,29 @@ openai_yaml_defaults: - If a public skill is added or renamed, update `catalog.yaml` entry. - Regenerate published indexes when public skills change: `make marketplace` and `make releases-index`. +### Add/remove skill checklist + +When adding or removing a public skill: + +- Add public skill path: `skills//`. +- Add or update `SKILL.md` required sections and `metadata.source`/`license`. +- Add `agents/openai.yaml` and `assets/icon.jpg` for public skills. +- Update `catalog.yaml` entry: + - set `id`, `name`, `path`, and `source`. + - remove stale entry for deleted/renamed skills. +- Update `README.md` public skills table and install examples. +- Run `make marketplace && make releases-index`. +- Run `make check-generated` and fix any sync gaps. +- On publish, include versioned tag/release flow after PR merge. + +When adding or removing a private skill: + +- Place or remove under `private-skills//`. +- Do not update `catalog.yaml`. +- Do not update public `README.md` install list unless you intentionally expose it. +- No public-release index regeneration is required unless a public skill changed. +- Still run `make validate`, `pre-commit run --all-files`, and `make check-generated`. + ## PR/Issue Hygiene - Include issue references when available (for example `Fixes: 123`). diff --git a/README.md b/README.md index 974eca3..efeb248 100644 --- a/README.md +++ b/README.md @@ -31,11 +31,11 @@ This is my personal **.skills** repository for Codex, Cursor, OpenClaw and agent | Skill | What it does | Install | |---|---|---| +| `openclaw-github-dedupe` | Triage GitHub issue/PR clusters across repositories, preserving contributor credit while selecting canonical fixes and safe closures. | `npx skills add vincentkoc/dotskills --skill openclaw-github-dedupe -y` | | `technical-deslop` | Ship clean diffs fast: remove AI noise and keep behavior unchanged. | `npx skills add vincentkoc/dotskills --skill technical-deslop -y` | | `technical-documentation` | Produce dev‑ready docs: clear, structured build/review for brownfield + evergreen. | `npx skills add vincentkoc/dotskills --skill technical-documentation -y` | | `technical-integrations` | Design integrations that land: vendor‑agnostic API/RFC/SDK plans with rollout safety. | `npx skills add vincentkoc/dotskills --skill technical-integrations -y` | | `technical-skill-finder` | Turn real agent pain into new skills: mine logs, rank wins, draft next steps. | `npx skills add vincentkoc/dotskills --skill technical-skill-finder -y` | -| `openclaw-github-dedupe` | Triage GitHub issue/PR clusters, preserve contributor credit, and manage canonical duplicates safely. | `npx skills add vincentkoc/dotskills --skill openclaw-github-dedupe -y` | Internal/private workflow skills can live in this repo and are marked in the metadata as `internal: true` and excluded from public marketplace/release artifacts. diff --git a/skills/openclaw-github-dedupe/SKILL.md b/skills/openclaw-github-dedupe/SKILL.md index a11e45f..3274c03 100644 --- a/skills/openclaw-github-dedupe/SKILL.md +++ b/skills/openclaw-github-dedupe/SKILL.md @@ -3,7 +3,7 @@ name: openclaw-github-dedupe description: Investigate a cluster of GitHub issues and PRs, determine canonical candidates, post duplicate/related status, preserve contributor credit, and execute cleanup actions (comments, closes, labels, changelog touchpoints). license: AGPL-3.0-only metadata: - short-description: GitHub triage for issue/PR dedupe clusters + short-description: GitHub triage for issue/PR clusters and dedupe decisions source: "https://github.com/vincentkoc/dotskills" --- @@ -15,18 +15,53 @@ Use this skill when a cluster of GitHub issues and pull requests has been report Provide a consistent, evidence-driven triage pass for issue and PR clusters so duplicate work is folded, contributor credit is preserved, and cleanup actions stay auditable. +Primary goal: make every run action-ready with explicit per-item actions, links, and command outcomes. + +## Vision + +Treat each cluster as a triage system, not a documentation exercise. The expected behavior is deterministic classification, auditable comment text, safe mutation flow, and fast operator comprehension. + +## Principles (read before execution) + +These are defined in `principles.md`: + +- Evidence over narrative +- Root-cause alignment over title similarity +- Credit-preserving attribution +- Safe defaults (`dry-run` and blockers) +- Complete audit trail in comments and labels +- Humans first: communicate like a senior developer advocate, not a script. + +Read `constitution.md` for governance requirements and decision quality rules before choosing final outcomes. + +## Operator experience and communication defaults + +This workflow is designed for high-velocity maintainers and external contributors: + +- Keep every reply short, clear, and respectful. +- Lead with what happened, then why. +- Include a plain-English next step and reopen path. +- Avoid abrupt or accusatory language, especially on duplicates. +- Never hide uncertainty; if blocked, say what is missing and what you need next. +- Treat the assistant as a Developer Experience lead: helpful, practical, and direct without sounding mechanical. +- Use examples as style guidance, not templates to paste verbatim. +- Vary sentence ordering and opener lines per message so repeated runs do not sound identical. +- Do not repeat the exact same message body twice in one cluster run unless no safe variation is possible. +- Use short, conversational paragraphs (2-4 paragraphs), and avoid one-liner robotic templates. +- If intent is clear, keep tone warm and explanatory even when issuing a close. + ## When to use - You have a cluster of suspected duplicates to classify as canonical/related/independent. -- You need a concise dedupe plan with explicit credit and rationale before taking action. -- The user asked to execute safe closure/label/comment steps (or return a vetted plan only). +- You need a concrete action plan with exact statuses instead of generic commentary. +- The user asked to execute safe closure/label/comment steps. - You need to avoid duplicate PR churn by identifying which change should stay canonical. ## Inputs - `cluster_refs` (required): list of issue/PR references as IDs or URLs. - `mode` (optional): `plan` (default) or `execute`. -- `channel` (optional): source context like `slack`, `discord`, `support`, etc. +- `channel` (optional): source context like `slack`, `imessage`, `support`, etc. - `repo` (optional): explicit `owner/repo` when not using current checkout. - `canonical_hint` (optional): explicit preference when ambiguity exists. - `merge_guard` (optional): `high|medium` mergeability strictness; default `high`. @@ -37,173 +72,326 @@ Provide a consistent, evidence-driven triage pass for issue and PR clusters so d - `reuse_copy_detection` (optional): `off|on` with default `on` for bot/copied-work checks. - `bot_author_pattern` (optional): list of substrings for suspicious authors. - `merge_tool_pref` (optional): `auto`, `gh`, `merge-skill`, or `land-skill`; default `auto`. +- `dry_run` (optional): `0|1` to force non-mutating mode. +- `output_mode` (optional): `compact|detailed`; default `detailed`. + +## Outputs + +- Per-item action matrix with explicit status (`KEEP_OPEN_CANONICAL`, `CLOSE_DUPLICATE`, `KEEP_OPEN_RELATED`, `KEEP_OPEN_UNRELATED`, `MANUAL_REVIEW_REQUIRED`). +- Evidence matrix with root-cause mapping, scope deltas, and risk blockers. +- Credit chain and attribution rationale (single-credit default, dual-credit only by exception). +- Required command set (dry-run and execution mode): close, comment, label, merge, and changelog actions. +- Escalation list for `manual-review-required` outcomes, with confidence score and hard-stop reason. + +## Sub-agent orchestration + +Use sub-agents in this chain for higher consistency and lower mistakes: + +- `agents/cluster-intake-agent.md` +- `agents/cluster-evidence-agent.md` +- `agents/cluster-decision-agent.md` +- `agents/cluster-synthesis-agent.md` + +Run in sequence and feed each output to the next. + +- Intake → Evidence: normalizes items and fetches GH context. +- Evidence → Decision: maps risk and hard-stop states. +- Decision → Synthesis: emits final action matrix and command plan. + +If any sub-agent blocks, continue only with explicit `manual-review-required` and keep execution safe. + +When orchestrator support exists, run them as a chain and pass structured outputs between steps: + +- Start with `cluster-intake-agent` +- Feed output to `cluster-evidence-agent` +- Feed output to `cluster-decision-agent` +- Feed output to `cluster-synthesis-agent` + +If sub-agents are unavailable, execute the same steps manually in this file order and keep output format intact. + +## Execution discipline for consistent tool UIs + +Use `update_plan` at runtime and keep one in-progress step at a time. + +- `Discover` → `Assess` → `Plan` → `Execute` (if requested) → `Verify`. +- Convert each stage between `in_progress` and `completed`. +- If hard-stop blockers exist, keep `Execute` as `pending` and return `manual-review-required`. +- This keeps Codex/Cursor/Claude execution format consistent. ## Workflow -1. Fetch cluster evidence. +1. Cluster intake and normalization + - Resolve each input to canonical links and types. + - Skip malformed entries with a reasoned note for `manual-review-required`. + +2. Fetch evidence from GitHub - For PRs: `gh pr view --json number,title,body,state,author,labels,createdAt,updatedAt,mergedAt,closedAt,mergeable,mergeStateStatus,isDraft,changedFiles,additions,deletions,statusCheckRollup,commits,url` - For issues: `gh issue view --json number,title,body,state,labels,author,createdAt,updatedAt,url,comments` - - Pull quick file scope context if needed: `gh pr diff --name-only` - - Pull status checks: `gh pr checks ` - - Pull review/AI-tool comments for score hints: `gh issue view --json comments` - - Record common bot/copied-work signals: - - `author.login` ending with `[bot]` or matching `bot_author_pattern`. - - PR body that advertises generated/copied content (`generated by`, `copy/pasted`, `cherry-picked from`, etc.). - - Commit messages that indicate lifted or mechanical work without problem-specific reasoning. - -2. Normalize signals into a guardrail matrix. - - Mergeability signal: mergeable state, draft status, merge-state blockers, and check conclusions. - - Churn signal: `changedFiles`, `additions`, and `deletions`. - - Body hygiene signal: body length, meaningful root-cause description, and presence of placeholder/junk patterns (e.g. `WIP`, `TODO`, blank text, automation template only, no concrete impact). - - AI review signal: Greptile or equivalent score-like comments. If score is present and below threshold, downgrade confidence. - - Source integrity signal: bot/copied-work risk and commit provenance. - - Any PR matched by bot/copied-work signals is marked `review-heavy` and cannot become canonical without explicit manual confirmation. - -3. Run full review-on-candidate for likely canonical PR(s). - - For the top canonical candidate(s), perform a complete pass: - - `gh pr view --json files` and `gh pr diff `. - - `gh pr checks ` and ensure required checks are passing or have explicit acceptable exceptions. - - Quick duplicate/conflict scan against canonical cluster references via file overlap and root-cause text. - - If mergeability and hygiene are clean, treat this as the "winning PR" candidate and move to merge-prep. - -4. Choose canonical outputs. - - Prefer merged + validated PRs with mergeability and a strong scope match. - - If a newer item is a strict superset and still merge-safe, prefer the newer item. - - If two items have equivalent scope, keep the most stable/least conflicting anchor. - - If uncertainty is high, do not close anything; return a report of open questions. - -5. Apply hard guardrails before assigning `canonical` or `duplicate`. - - Mergeability hard-stop: - - Reject as canonical if `isDraft` is true. - - Reject as canonical if `mergeable` is false or `mergeStateStatus` indicates blocking. - - If checks are failing, mark as `manual-review-required` unless user explicitly wants forced action. - - Churn hard-stop: - - If `changedFiles > max_changed_files_for_canonical` or `additions + deletions > max_delta_lines_for_canonical`, do not auto-close other PRs as duplicate. - - Treat as related/review-needed even if overlap appears strong. - - Body hygiene hard-stop: - - For empty/junk bodies or no concrete root cause, classify confidence as low and require explicit manual confirmation before duplicate actions. - - AI review hard-stop: - - If a recognized score (for example Greptile) is below `min_greptile_score`, require manual confirmation before duplicates and avoid auto-canonicalization. - - Bot/copy hard-stop: - - If author appears as bot/auto-generated and work appears copied with low evidence of original validation, classify as `manual-review-required`. - - Do not suppress original human credit; keep attribution to originator and include a provenance note. - -6. Map outcomes. + - Pull file footprint for PRs when deciding canonical scope: `gh pr diff --name-only` + - Pull check state for PRs: `gh pr checks ` + - Pull review/AI-tool signal text: `gh issue view --json comments` + +3. Normalize guardrails + - Mergeability: mergeable flag, merge-state blockers, draft state, check rollup status. + - Churn: `changedFiles`, `additions`, `deletions`. + - Body hygiene: concrete root-cause detail vs template/placeholder-only text. + - AI-review score: Greptile-like comments below threshold downgrade confidence. + - Copy/bot signal: generated/copied language, bot-like authors, low-evidence mechanical commits. + - Any hard-stop issue marks item `manual-review-required` and blocks automatic close. + +4. Review candidate canonicals + - For each top candidate PR: `gh pr view --json files` and `gh pr diff `. + - If healthy, treat as canonical candidate and move toward merge prep. + - If two candidates are equivalent, prefer stable, lower-risk scope. + - If a newer PR is superset-safe, prefer the newer with higher-surface fix coverage. + +5. Decide outcomes - Canonical issue/PR: keep open. - - Duplicate PRs/issues: close with explicit duplicate rationale and credit. - - Winning PR that passes all guardrails: perform final review and help merge. - - Related but not duplicate: keep open and add explicit relationship note. - - Unrelated: split into separate routing plan. - - For any hard-stop failures, return `manual-review-required` with blockers listed. - -7. Merge and OpenClaw follow-up. - - If user asked `mode=execute` and the winning PR is green: - - Use `merge_tool_pref`: - - `merge-skill`/`land-skill`: invoke local merge/land workflow/skill if available. - - `gh`: run `gh pr merge --auto --merge` (or `--squash`, `--rebase` based on repo policy). - - `auto`: prefer merge/land skill first if detected; otherwise fallback to `gh` merge. - - Re-check checks after merge and report final state. - - If canonical PR is merge-ready but not yet merged, add/verify OpenClaw changelog entry in that PR: - - Check presence of `CHANGELOG.md`. - - If entry exists, do not duplicate; otherwise add a concise bullet under current unreleased `Fixes` section with PR number + credits. - - Prefer including this within the canonical PR before merge. - - If not possible, create follow-up squash commit after merge to add changelog. - -8. Run boundary check. - - If `mode=plan`, return a precise command plan and message drafts with confidence and blocker list. - - If `mode=execute`, run GH commands only for items with no blockers; otherwise stop and report. - -9. Emit results with explicit evidence and attribution. + - Duplicate PR/issue: close with explicit comment and reasoned message. + - Related not duplicate: keep open and mark relationship. + - Unrelated: split into a separate cluster/routing note. + - For any hard-stop failure: keep `manual-review-required` with explicit blockers. + +6. Merge and changelog follow-up + - If execute + winning PR is green: + - prefer merge/land helper when available + - fallback: `gh pr merge --auto --merge` (or repo policy `--squash` / `--rebase`) + - rerun check discovery and report final state + - If changelog is needed, add only once under Unreleased `### Fixes` and do not duplicate existing entries. + - If changelog cannot be added before merge, create a follow-up squash commit only if required by repo policy. + +7. Emit outcomes + - In `plan` mode: only draft comments, labels, close commands, and blockers. + - In `execute` mode: run only safe GH mutations after all guardrails pass. + - Return final output using the required format below. + +8. Review for governance drift + - Check `AGENTS.md` and `CONTRIBUTING.md` for scope changes or repo policy changes. + - Validate that output keeps explicit credit references and concise issue/PR references. + +## Governance and anti-drift checks + +- If the repo has a higher-priority instruction source (project-specific AGENTS/CONTRIBUTING), that source wins over this skill's defaults. +- Keep close reasons and comments compliant with repository conventions. +- Never ignore required validation gates. + +## Required final output format + +### Cluster summary (compact) +- Canonical PR: `` +- Canonical issue: `` +- Merge gate: `` +- Credit chain: `` (default 1 credited contributor in 95%+ cases; max 2 only by explicit exception) +- Dry run: `` + +### Per-item action matrix (required) +- `pr:20988` — `KEEP_OPEN_CANONICAL` — `https://github.com/openclaw/openclaw/pull/20988` — `Streaming recipient-id root-cause fix` +- `issue:19839` — `CLOSE_DUPLICATE` — `https://github.com/openclaw/openclaw/issues/19839` — `->` `https://github.com/openclaw/openclaw/issues/20337` +- `issue:12714` — `KEEP_OPEN_RELATED` — `https://github.com/openclaw/openclaw/issues/12714` — `Block-mode emission behavior mismatch` + +### Command/result block (required) +- `planned`/`executed`/`blocked` status per command. +- For each command, include exact command text and resulting state. + +### Evidence matrix (required) +- Item-level evidence anchors: PR/issue link, root-cause marker, scope delta, merge risk, and confidence tag. +- Blockers must be explicit. + +### Credit and closure rationale block (required) +- Explicit credit chain for all merged/closed outcomes with default one credited contributor in 95%+ cases; max two only by explicit exception. + - Rule: default one credited contributor (target 95%+ of cases), two only when the earlier PR is non-mergeable and the later PR is a direct, clean continuation. +- Canonical/related boundary rationale for each non-canonical item. +- Include the exact customer-facing message body (or template) for each comment-close action, using the communication defaults above. + +### Escalations +- List unresolved blockers and uncertainty with `manual-review-required` if any. +- Include confidence per item (`high|med|low`) and hard-stop reason. -## Outputs +## Message templates -- A canonicality assessment for the cluster with evidence bullets. -- A `plan` table: item, role (canonical/duplicate/related/unrelated), rationale, and confidence. -- A `risk register` per item for: `mergeability`, `churn`, `body_hygiene`, `ai_review_score`. -- A merge-readiness checklist for each candidate (checks, approvals, conflicts, branch state, policy alignment). -- For chosen canonical PR: explicit merge command used, merge result, and OpenClaw changelog action status. -- Draft close/keep messages containing contributor credits. -- Command list for labels/comments/close steps (and execution status when run). -- Explicit escalation notes for manual review and uncertainty. +### Message behavior contract -## Message templates +Use template intent only; do not replay exact wording across issues/PRs. + +- Start with context acknowledgment. +- Explain keep/close decision in plain terms. +- State why this is the chosen path. +- Include a direct reopen path when uncertainty remains. +- End with one clear next action. + +Prefer sentence variation over strict block copying. Keep grammar natural and avoid repetitive phrasing. ### Canonical PR credit line -`This final fix is in #{canonical_pr} by @{canonical_author}. Earlier related work is credited to #{prior_pr} by @{prior_author}; thanks for that groundwork.` +Style rule: use the intent below, then vary wording naturally for each message. Do not output a single fixed text. + +`Great progress here. + +The final fix is in # by @. +This is the version we're keeping because it is the most stable and complete path. + +If you think there's a gap, tell me and I'll reopen review right away.` + +Default single-credit template: +`Thanks for the earlier contribution. + +The final fix is in # by @. +Your earlier contribution is preserved in the canonical history. + +If this looks off, tell me and I can reopen review right away.` + +Exceptional dual-credit template: +`I appreciate the earlier pass. + +The final fix is in # by @ and @. +The earlier path in # built strong groundwork, and the later PR completed a merge-safe continuation. + +If this needs correction, tell me and I can re-check credit and closure right away.` ### Close duplicate PR -`Thanks for the earlier contribution. Closing as a duplicate of #{canonical_pr}. Your PR covered part of the same root cause and is credited in the canonical fix. If this is a mistake, please tell me and we'll reopen a review path.` +`Thanks for the earlier contribution. + +I'm going to close this as a duplicate of #. +Great attempt here, but this PR is stale and a newer, stable PR is handling the same root-cause path. +Your work is preserved in the canonical attribution trail. + +If this is a mistake, tell me and I can reopen review right away.` + +Single-credit close template: +`I appreciate you pushing this. + +I'm going to close this as a duplicate of #. +This was an earlier step, and the newer canonical fix now includes the covered scope. + +If this feels wrong, tell me and I can reopen review right away.` + +Exceptional dual-credit close template: +`Thank you for taking this on. + +I'm going to close this as a duplicate of #. +# created the initial path, and the later PR carried it into a merge-safe continuation. +Both contributions are retained in the canonical credit trail. + +If this is a mistake, tell me and I can reopen review right away.` ### Keep canonical issue open -`Keeping this open as canonical for this {channel}-specific failure cluster.` +`Keeping this open as canonical for this cluster. + +This appears to be the shared issue shape for the channel cluster we are solving. + +If this should be reassigned, tell me what you're seeing and I'll reassess the boundary.` ### Close duplicate issue -`Closing as duplicate of #{canonical}. This matches the same root-cause path and behavior. Credit is tracked in #{canonical_pr} with foundational work from #{prior_pr}. If this is a mistake, please tell me and we'll reopen a review path.` +`Thanks for the report. + +I'm closing this as duplicate of #. +The same failure pattern and behavior map to the canonical fix path there. + +If this is a mistake, tell me and I can reopen review right away.` + +### Related / not duplicate +`Good call raising this. + +This appears related, but this is not a duplicate. It diverges at {reason}, so it stays as a separate track. + +If this feels like a miss, tell me and I can re-check it quickly.` + +### Unrelated +`Thanks for flagging this. + +This appears separate from this cluster and will stay in its own thread. + +If this looks related, point to the shared failure step and I can rerun dedupe right away.` -### Related (not duplicate) -`This appears related but not a duplicate: symptom path diverges at {reason}. Keeping it open separately.` +### Variation examples +`Nice work circling this one. -### Winning PR full-review summary -`I reviewed the winning PR for scope, checks, and mergeability. Conflicts: {status}. Check status: {status}. Final action: {merged|ready|blocked}.` +I reviewed the overlap and confirmed the final fix is tracking in #20988 by @Dithilli. -### Unrelated (routing only) -`This appears separate from this cluster and should be tracked independently.` +It covers the same failure mode and is the right place for closure path continuity. + +If this seems off in your view, tell me what changed and I can reopen the review quickly.` + +`Thanks for taking the first pass on this. + +I'm closing this as a duplicate of #20988. A later stable PR carried this forward with the merge-safe completion path. + +Your contribution is still part of the attribution trail, and I can reopen this review if there is a miss.` + +`Good observation. This is related, but not a duplicate. + +The failure path diverges at message-route semantics, so this remains in a separate track. + +If that boundary feels wrong, I can reassess with the extra context right away.` + +## Messaging examples by situation + +### Situation 1: clean duplicate, single-credit result +- Canonical: `pr:20988` +- Duplicate: `issue:19839`, `issue:12714` +- Required behavior: + - One credited canonical author only (target 95%+ of cases). + - Duplicate closure uses single-credit close templates. + - Related notes include a specific divergence reason. + +### Situation 2: earlier PR non-mergeable, direct follow-up continuation, dual-credit +- Canonical: `pr:20988` +- Earlier groundwork: `pr:20377` (not mergeable, direct continuation proven by diff overlap and clean follow-up checks) +- Required behavior: + - Dual-credit templates are used. +- Rationale statement must include: + - non-mergeability reason for the first PR, + - why the second PR is a direct continuation, + - why test/conflict risk remains clean. + +### Situation 3: related but not duplicate +- Example outcome: `KEEP_OPEN_RELATED`. +- Message must use the related template with explicit `{reason}` describing vector divergence. ## Action commands > Run commands from repo checkout unless explicitly using full `owner/repo` URLs. ### Add labels for closed duplicates -- PR/issue duplicate: `gh issue edit --add-label dedupe:child --add-label close:duplicate` (repo labels vary; use `duplicate` fallback as needed). -- Canonical issue: `gh issue edit --add-label dedupe:parent`. +- PR/issue duplicate: `gh issue edit --add-label dedupe:child --add-label close:duplicate` +- Canonical issue: `gh issue edit --add-label dedupe:parent` ### Close with comment (issues) - Comment first, then close: -`gh issue comment --body "..."` -`gh issue close --reason not planned` + - `gh issue comment --body "..."` + - `gh issue close --reason not planned` ### Close PR -- For duplicate PR: `gh pr close --comment "..."`. - -### Guardrail helper checks -- Mergeability snapshot: -`gh pr view --json mergeable,mergeStateStatus,isDraft,statusCheckRollup` -- Churn snapshot: -`gh pr view --json changedFiles,additions,deletions` -- Greptile/AI review scan (optional): -`gh issue view --json comments` - -### Changelog policy -- If changelog already has an entry, do not duplicate it. -- If adding new entry, place under current Unreleased `### Fixes` section with PR number and contributor credits. +- `gh pr close --comment "..."` (preferred with canonical close message). -### Suggested merge helpers -- Prefer local merge/land skill (`merge_tool_pref=merge-skill` or `land-skill`) when available and configured. -- Otherwise use: -`gh pr merge --merge --auto` -`gh pr merge --squash --auto` -`gh pr merge --rebase --auto` +### Merge helpers +- `gh pr merge --merge --auto` +- `gh pr merge --squash --auto` +- `gh pr merge --rebase --auto` -Select merge mode based on repo policy and branch protection requirements. +### Guardrail checks +- `gh pr view --json mergeable,mergeStateStatus,isDraft,statusCheckRollup` +- `gh pr view --json changedFiles,additions,deletions` +- `gh issue view --json comments` ## scripts/alias.sh helper -Run the tiny helper directly from this skill directory for repetitive cluster operations: +Run the helper from this skill directory for batch-driven dedupe actions: `./scripts/alias.sh run-cluster /path/to/cluster.txt` -Minimal `cluster.txt` format: +`./scripts/alias.sh --dry-run run-cluster /path/to/cluster.txt` + +Supported cluster format: `:||` Supported actions: +- `inspect` +- `close-pr-duplicate` +- `close-issue-duplicate` +- `noop` -- `inspect` → fetch issue/PR views, diff file list, and checks. -- `close-pr-duplicate` → close PR as duplicate of target PR. -- `close-issue-duplicate` → comment + close issue as duplicate of target issue. -- `noop` → no action. - -Typical example file: +Example: ```text pr:20988|inspect| @@ -212,23 +400,19 @@ issue:19839|close-issue-duplicate|20337 issue:12714|noop| ``` -Use `ODGH_DRY_RUN=1` for dry-run mode to print command intent without making mutations. -You can also use it inline: - -`./scripts/alias.sh --dry-run run-cluster /path/to/cluster.txt` +Use placeholder IDs in examples only: -For safe editing without real references, copy: -`scripts/cluster-example.txt` +`pr:xxxxx|inspect|` ## Git cleanup option -- To remove stale branch: -`git branch -D ` -`git push origin --delete ` + +- Remove stale branch: `git branch -D ` +- Remove remote branch: `git push origin --delete ` ## Safety / anti-patterns -- Do not assume duplicate status from metadata alone; always inspect body + diff for scope overlap. -- Do not use failed closure defaults when hard-stop guardrails fail. -- Do not invent non-existent GH close reasons (for example, `--reason duplicate` in `gh issue close` is invalid; use `not planned` plus label/comments). -- Preserve evidence in each comment text for auditability. -- Do not merge or close items while mergeability/churn/AI-review warnings are unresolved. +- Do not classify duplicates from metadata alone; inspect body and diff semantics. +- Do not use invalid GH issue-close reasons (for example `--reason duplicate`). +- Preserve source attribution when duplicate actions are taken. +- Never auto-close when hard-stop guardrails fail. +- Do not merge or close items while mergeability/churn/AI-review blockers are unresolved. diff --git a/skills/openclaw-github-dedupe/agents/cluster-decision-agent.md b/skills/openclaw-github-dedupe/agents/cluster-decision-agent.md new file mode 100644 index 0000000..73225e8 --- /dev/null +++ b/skills/openclaw-github-dedupe/agents/cluster-decision-agent.md @@ -0,0 +1,28 @@ +--- +name: cluster-decision-agent +description: Decide canonical/duplicate/related/unrelated outcomes for issue and PR clusters. +model: sonnet +tools: + - Read + - Shell +permissionMode: default +maxTurns: 10 +--- + +You are the decision sub-agent for openclaw-github-dedupe. + +Goals: +- Identify canonical issue/PR candidates. +- Propose close/keep outcomes with rationale. + +Tasks: +- Compare failure paths across items, not only titles. +- Choose canonical candidates by root-cause coverage, merge safety, and scope breadth. +- Preserve newer-superset exception rules where newer item is cleaner. +- Produce conservative classifications when confidence is low. + +Return: +- outcome per item, +- confidence tier, +- rationale snippet, +- action priority order. diff --git a/skills/openclaw-github-dedupe/agents/cluster-evidence-agent.md b/skills/openclaw-github-dedupe/agents/cluster-evidence-agent.md new file mode 100644 index 0000000..f565a59 --- /dev/null +++ b/skills/openclaw-github-dedupe/agents/cluster-evidence-agent.md @@ -0,0 +1,27 @@ +--- +name: cluster-evidence-agent +description: Gather and score PR/issue evidence for dedupe and duplicate classification. +model: sonnet +tools: + - Shell + - Read +permissionMode: default +maxTurns: 10 +--- + +You are the evidence sub-agent for openclaw-github-dedupe. + +Goals: +- Collect GitHub metadata for each cluster item. +- Compute hard-stop risks and risk register entries. + +Tasks: +- Run `gh` lookups for each PR/issue in mode-safe manner. +- Capture mergeability/churn/body-hygiene signals. +- Compute confidence with explicit blockers. + +Return: +- per-item evidence summary, +- guardrail results, +- provisional confidence, +- hard-stop flags. diff --git a/skills/openclaw-github-dedupe/agents/cluster-intake-agent.md b/skills/openclaw-github-dedupe/agents/cluster-intake-agent.md new file mode 100644 index 0000000..f8cfe5e --- /dev/null +++ b/skills/openclaw-github-dedupe/agents/cluster-intake-agent.md @@ -0,0 +1,28 @@ +--- +name: cluster-intake-agent +description: Normalize and validate cluster refs for issue/PR dedupe runs. +model: haiku +tools: + - Read + - Shell +permissionMode: default +maxTurns: 6 +--- + +You are the intake sub-agent for openclaw-github-dedupe. + +Goals: +- Canonicalize raw references to typed and linked items. +- Detect malformed/ambiguous entries. +- Split the cluster into PR and issue sets. + +Tasks: +- Resolve bare IDs, URLs, and already-formatted refs. +- Expand `cluster_refs` into canonical `pr:` / `issue:` entries. +- Flag and explain malformed items with severity. + +Return: +- normalized list, +- unresolved item list, +- confidence score (high/med/low), +- blocked_reason when missing mandatory data. diff --git a/skills/openclaw-github-dedupe/agents/cluster-synthesis-agent.md b/skills/openclaw-github-dedupe/agents/cluster-synthesis-agent.md new file mode 100644 index 0000000..aff8f3b --- /dev/null +++ b/skills/openclaw-github-dedupe/agents/cluster-synthesis-agent.md @@ -0,0 +1,26 @@ +--- +name: cluster-synthesis-agent +description: Merge sub-agent findings into operator-ready output for dedupe execution. +model: opus +tools: + - Read +permissionMode: default +maxTurns: 12 +--- + +You are the synthesis sub-agent for openclaw-github-dedupe. + +Goals: +- Convert evidence and decisions into final plan/action payload. +- Keep output machine-readable and directly actionable. + +Tasks: +- Resolve contradictions between candidate outputs. +- Build final per-item action matrix, comment text, and command matrix. +- Set final status labels: `ready`, `blocked`, or `manual-review-required`. + +Return: +- compact execution plan, +- ordered command list with status, +- escalation list, +- final summary with confidence and credit chain. diff --git a/skills/openclaw-github-dedupe/constitution.md b/skills/openclaw-github-dedupe/constitution.md new file mode 100644 index 0000000..31ecedf --- /dev/null +++ b/skills/openclaw-github-dedupe/constitution.md @@ -0,0 +1,37 @@ +# Constitution for Cluster Triage Decisions + +## Core article + +1. The canonical decision must be traceable. +2. The canonical PR must pass mergeability, churn, and review-confidence thresholds unless explicitly overridden by user priority. +3. Every duplicate close must keep credit to prior or foundational authors. +4. Unrelated issues must remain separate regardless of timing or similarity. +5. Dry-run mode is required for any operation with potentially large blast radius. +6. No closure action is complete without comments and labels. +7. Credit attribution is capped to one contributor by default. +8. Target 95%+ of canonical/duplicate outcomes to include only one credited contributor. +9. Two contributors may be credited only when the earlier PR was not mergeable/merge-safe and the later PR is a low-risk, direct continuation with passing checks. +10. Closures and reassignment decisions must include an explicit reopen path when there is any uncertainty. +11. Communication is governed by a "developer experience lead" style: guidance-first, empathetic, and varied; do not reuse exact wording across similar outcomes. +12. Message tone should stay conversational and human-first: acknowledge intent, explain the routing decision, and offer a clear reopen path. + +## Decision quality rules + +- If hard-stop rules exist, the cluster remains in `manual-review-required` mode. +- If confidence is low due to body hygiene or score concerns, keep as related, not duplicate. +- Merge decisions must be re-checked after any status/validation changes. +- Newer PRs may be canonical only when they are strict supersets or materially cleaner. +- Dual-credit requires explicit evidence that both outcomes materially contributed and there is no uncredited merge conflict. + +## Output accountability + +Each run must produce: +- per-item status and action, +- per-item confidence, +- blocker list, +- execution status per command, +- explicit credit lineage. + +Credit lineage format: +- `primary` (required) +- `secondary` (optional, only under constitutional exception above) diff --git a/skills/openclaw-github-dedupe/principles.md b/skills/openclaw-github-dedupe/principles.md new file mode 100644 index 0000000..d79464e --- /dev/null +++ b/skills/openclaw-github-dedupe/principles.md @@ -0,0 +1,25 @@ +# Principles for OpenClaw Cluster Dedupe + +## Purpose + +These are hard constraints for every execution of this skill. If a step conflicts with a higher-priority instruction, that instruction wins. + +## Principles + +- Evidence over narrative. +- Dedup decisions must map failure semantics, not just title similarity. +- Preserve contributor credit and avoid erasing historical context. +- Keep visible credit bounded: + - default: one credited contributor on canonical outcomes (target 95%+ of cases), + - exception only: two credited contributors when the first PR is not mergeable/merged and an unmerged later PR is a direct, conflict-free continuation that passes checks. +- Keep actions reversible when possible; prefer dry-run first for large cluster changes. +- Never infer intent from metadata alone; verify body, diff, and failure path. +- Treat risk and quality gates as non-negotiable before closure. +- Prefer one canonical resolution per cluster, with explicit rationale for every non-canonical item. +- If uncertainty exceeds one unresolved hard stop, return `manual-review-required` instead of closing. +- Maintain transparent provenance: always leave a comment trail and explicit labels. +- Keep output scannable and command-oriented for operators. +- Prefer minimal edits and deterministic commands. +- Keep communication constructive and contributor-safe, especially on closures. +- Keep communication adaptive and human: treat examples as prompts, not scripts, and vary phrasing so output never reads as templated. +- Keep comms warm and practical: prioritize what the maintainer needs next over polished copy. diff --git a/skills/openclaw-github-dedupe/scripts/alias.sh b/skills/openclaw-github-dedupe/scripts/alias.sh index 5abe058..ae46309 100755 --- a/skills/openclaw-github-dedupe/scripts/alias.sh +++ b/skills/openclaw-github-dedupe/scripts/alias.sh @@ -4,6 +4,7 @@ set -euo pipefail REPO="${ODGH_REPO:-openclaw/openclaw}" DRY_RUN="${ODGH_DRY_RUN:-0}" +STYLE_VARIANTS="${ODGH_STYLE_VARIANTS:-1}" usage() { cat <<'EOF' @@ -16,6 +17,7 @@ Usage: Environment: ODGH_REPO GitHub repo (default: openclaw/openclaw) ODGH_DRY_RUN if set to 1, print actions without mutating state + ODGH_STYLE_VARIANTS if set to 0, use fixed legacy comment texts Flags: --dry-run preview command intent without mutating GitHub state @@ -81,10 +83,96 @@ gh_pr_files() { gh pr diff --name-only "$id" --repo "$REPO" } +variant_index() { + local key="$1" + local max="$2" + local total=0 + local i ch + for ((i = 0; i < ${#key}; i++)); do + ch=$(printf '%d' "'${key:i:1}") + total=$((total + ch)) + done + echo $((total % max)) +} + +issue_close_body() { + local canonical="$1" + local item_id="$2" + local idx + local opener trail + idx="$(variant_index "${item_id}-${canonical}-issue" 4)" + case "$idx" in + 0) + opener='Thanks for the report.' + trail='I can reroute this if I missed the right cluster alignment.' + ;; + 1) + opener='Good catch, thank you.' + trail='If you see a mismatch, I can reopen this right away.' + ;; + 2) + opener='Great call reporting this.' + trail='Please flag the exact shared failure step if you want me to re-check it now.' + ;; + *) + opener='I appreciate the report.' + trail='If this is a miss, tell me and I can reopen review right away.' + ;; + esac + + cat <