dupcanon is currently human-operated, but it is being shaped for workflow-native automation in GitHub Actions.What this is
Primary objective
Reduce duplicate noise in high-cadence repos (for example, OpenClaw) by selecting stable canonicals and closing true duplicates safely.
Why it exists
Naive automation creates duplicate chains and unstable targets; this system adds durable state + deterministic gates.
Operating constraints
Cheap enough to run continuously, accurate enough for guarded production use, and fully auditable.
Core strategy
Embeddings for retrieval, LLM for semantic judgment, deterministic policy for acceptance and close safety.
Current vs target mode
- Current mode
- Target mode
- Human-operated CLI pipeline
- Online
detect-newin shadow/suggest mode - Close actions gated through reviewed
plan-close+ explicitapply-close --yes
Core approach
Two paths share one data model and one safety model.- Online entrypoint:
detect-newfor newly opened issues/PRs sync/refresh: ingest issues + PRs into Postgresembed: title/body embeddings in pgvectorcandidates: persisted nearest-neighbor candidate setsjudge: LLM chooses duplicate target inside the candidate set- deterministic gates veto risky decisions
canonicalize: compute canonical representativesplan-close-> reviewedapply-close --yes
All key artifacts are persisted for replay, audit, and threshold tuning.
Deterministic gates (with actual thresholds)
Judge acceptance gates (batch judge)
Judge acceptance gates (batch judge)
- strict JSON parse
- target must be in candidate set
- confidence threshold:
model_confidence >= 0.85(min_edgedefault) - target must be open
- candidate gap gate:
selected_score - best_alternative_score >= 0.015 - mismatch vetoes (uncertain/overlap/root-cause/scope class failures)
- one accepted outgoing edge per source unless explicit rejudge
Close planning gates
Close planning gates
- maintainer author protection
- maintainer assignee protection
- direct accepted edge to canonical required
- close threshold: direct edge confidence
>= 0.90(min_closedefault)
Online detect-new gates
Online detect-new gates
- default thresholds:
maybe=0.85,duplicate=0.92 - strict duplicate downgrade if structural guardrails fail
- duplicate class also requires strong retrieval support (current floor: top match score
>= 0.90) - candidate gap gate also applies on strict duplicate path (
>= 0.015)
Confidence vs score (important):
- confidence = model’s self-reported duplicate confidence in
[0,1] - score = retrieval similarity score from vector search
- gap =
selected_candidate_score - best_alternative_score
Judge gate examples
| Case | Model confidence | Selected score | Best alternate | Gap | Outcome |
|---|---|---|---|---|---|
| Strong accepted | 0.91 | 0.93 | 0.89 | 0.04 | accepted |
| Rejected (below min_edge) | 0.82 | 0.95 | 0.70 | 0.25 | rejected |
| Rejected (gap too small) | 0.95 | 0.901 | 0.893 | 0.008 | rejected |
Actual judge system prompt (current)
Show system prompt from `src/dupcanon/judge_runtime.py`
Show system prompt from `src/dupcanon/judge_runtime.py`
Cost and accuracy stance
Current status
Implemented commands:init,sync,refresh,embed,candidates,judgejudge-audit,report-audit,detect-newcanonicalize,maintainers,plan-close,apply-close
What’s missing next
- first-class evaluation command + reporting workflow for production gate decisions
- programmatic orchestration command/workflow for unattended DB freshness updates
- richer action surface in future (for example, label taxonomy / tree-editing operations)
Stack
- Python + Typer + Pydantic + Rich
- Supabase Postgres + pgvector
- providers: OpenAI, Gemini, OpenRouter, and
openai-codexviapiRPC
Internal docs
Deep design and runbook docs are indocs/internal/.