$npx -y skills add warpdotdev/oz-for-oss --skill update-dedupeUpdate the repo-local dedupe-issue-local companion skill using closed-as-duplicate signals. Use when maintainers repeatedly close issues as duplicates of the same canonical thread and that pattern should feed back into triage duplicate detection.
| 1 | # Update Dedupe |
| 2 | |
| 3 | Use this skill to improve `.agents/skills/dedupe-issue-local/SKILL.md` from real closed-as-duplicate signals. The core skill at `.agents/skills/dedupe-issue/SKILL.md` is the cross-repo contract and is read-only from this loop. |
| 4 | |
| 5 | This loop is focused exclusively on closed-as-duplicate signals. Other maintainer signals (re-labels, re-opens, follow-up comments) are handled by the separate `update-triage` loop. |
| 6 | |
| 7 | ## Write surface |
| 8 | |
| 9 | This self-improvement loop may only write to: |
| 10 | |
| 11 | - `.agents/skills/dedupe-issue-local/` (and `SKILL.md` inside it) |
| 12 | |
| 13 | It must NOT touch: |
| 14 | |
| 15 | - `.agents/skills/dedupe-issue/SKILL.md` (the core contract) |
| 16 | - `.agents/skills/triage-issue-local/SKILL.md` (owned by `update-triage`) |
| 17 | - any other core skill |
| 18 | |
| 19 | The self-improvement runner enforces this via a `git diff` check against allowed prefixes before pushing. A violation aborts the run. |
| 20 | |
| 21 | ## Inputs |
| 22 | |
| 23 | - Optional repository override if you are not running from the target checkout. |
| 24 | - Optional time window override when you need something other than the default seven-day lookback. |
| 25 | |
| 26 | ## Workflow |
| 27 | |
| 28 | 1. Verify GitHub CLI auth: |
| 29 | |
| 30 | ```bash |
| 31 | gh auth status |
| 32 | ``` |
| 33 | |
| 34 | 2. Aggregate closed-as-duplicate signals for recently closed issues with the bundled script: |
| 35 | |
| 36 | ```bash |
| 37 | python3 .agents/skills/update-dedupe/scripts/aggregate_dedupe_feedback.py |
| 38 | ``` |
| 39 | |
| 40 | By default this targets the current repo and looks back 7 days. It collects only issues GitHub itself recorded as closed with the *duplicate* close reason (`state_reason == "duplicate"`) and looks up the canonical issue each was closed against via the issue timeline's `marked_as_duplicate` event. Ad-hoc maintainer comments that merely mention another issue are intentionally ignored to avoid false positives. The script writes structured JSON to a temporary file and prints the path. |
| 41 | |
| 42 | 3. Read the generated JSON and look for repeated clusters: |
| 43 | |
| 44 | - two or more different reporters filed similar issues that maintainers closed as duplicates of the same canonical thread |
| 45 | - an explicit maintainer statement that a class of issue should always be treated as a duplicate of a canonical thread |
| 46 | |
| 47 | 4. Propose the smallest edit that explains the cluster. Add or update a bullet under the "Known-duplicate clusters" section of `.agents/skills/dedupe-issue-local/SKILL.md` summarizing the canonical thread and the distinguishing signals maintainers use to identify duplicates. |
| 48 | |
| 49 | 5. Keep the core dedupe contract stable — never edit `dedupe-issue/SKILL.md`, never weaken the 2-candidate minimum, never change the similarity thresholds or the output shape. |
| 50 | |
| 51 | ## Evidence Rules |
| 52 | |
| 53 | - Only encode a cluster when at least two independent closed-as-duplicate events point at the same canonical issue, or a maintainer explicitly asks for one. |
| 54 | - Skip the PR when there is no repeated signal. |
| 55 | - Do not weaken precision-over-recall for dedupe. |
| 56 | |
| 57 | ## Final Checks |
| 58 | |
| 59 | - Re-read the updated `dedupe-issue-local` companion skill and confirm any new clusters are explicit. |
| 60 | - Keep the companion concise; prefer canonical links and short distinguishing notes over long prose. |
| 61 | - Commit any changes on a local branch named `oz-agent/update-dedupe`. Do NOT push the branch; the Python entrypoint will run a write-surface guard and push only when the guard passes. |
| 62 | - If the updates warrant a PR, it will be opened from the pushed branch. Tag `@captainsafia` as a reviewer on that PR. |
| 63 | - Validate any temporary JSON with `jq` before relying on it. |