Back to skills
SkillHub ClubShip Full StackFull StackBackend

concept-vetting

Use when orchestrator generates new concepts or user says "vet concepts", "check conflicts", "find duplicates", "scan for overlaps" - scans story-tree database to detect duplicate, overlapping, or competing concepts. Returns conflict pairs with types and confidence scores for human review.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
1
Hot score
77
Updated
March 20, 2026
Overall rating
C3.1
Composite score
3.1
Best-practice grade
A88.4

Install command

npx @skill-hub/cli install mharbulous-syncopaid-concept-vetting

Repository

Mharbulous/SyncoPaid

Skill path: .claude/skills/concept-vetting

Use when orchestrator generates new concepts or user says "vet concepts", "check conflicts", "find duplicates", "scan for overlaps" - scans story-tree database to detect duplicate, overlapping, or competing concepts. Returns conflict pairs with types and confidence scores for human review.

Open repository

Best for

Primary workflow: Ship Full Stack.

Technical facets: Full Stack, Backend.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: Mharbulous.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install concept-vetting into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/Mharbulous/SyncoPaid before adding concept-vetting to shared team environments
  • Use concept-vetting for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: concept-vetting
description: Use when orchestrator generates new concepts or user says "vet concepts", "check conflicts", "find duplicates", "scan for overlaps" - scans story-tree database to detect duplicate, overlapping, or competing concepts. Returns conflict pairs with types and confidence scores for human review.
disable-model-invocation: true
---

# Concept Vetting - Automated Concept Conflict Resolution

Detect and resolve conflicting concepts in the story-tree database. This skill **vets concepts** before presenting them to humans - most conflicts are resolved automatically.

**Database:** `.claude/data/story-tree.db`

**Critical:** Use Python sqlite3 module, NOT sqlite3 CLI.

**Platform Note:** All Python commands use `python` (not `python3`) for cross-platform compatibility.

## Architecture Overview

```
Phase 1: Candidate Detection (Python script)
├── Run keyword/similarity heuristics
├── Output CANDIDATE pairs (potential conflicts)
└── No classification — just "these might conflict"

Phase 2: Classification & Resolution (Main Agent)
├── For each candidate pair:
│   ├── Read both story descriptions
│   ├── Classify: duplicate / scope_overlap / competing / incompatible / false_positive
│   ├── Look up action (deterministic based on classification + effective status)
│   └── Execute action (LLM for merges, Python for deletes/three-field updates)
└── Present only HUMAN REVIEW cases interactively
```

## Decision Matrix

The skill vets **concepts only** — deciding what ideas to present to the human.

### Conflict Types

| Type | Description |
|------|-------------|
| `duplicate` | Essentially the same story |
| `scope_overlap` | One subsumes or partially covers another |
| `competing` | Same problem, different/incompatible approaches |
| `incompatible` | Mutually exclusive approaches that cannot be merged |
| `false_positive` | Flagged by heuristics but not actually conflicting |

### Automated Actions

| Conflict Type | Concept vs... | Action |
|---------------|---------------|--------|
| **DUPLICATE** | `wishlist`, `refine` | TRUE MERGE → keep stage |
| **DUPLICATE** | `concept` | TRUE MERGE → concept |
| **DUPLICATE** | everything else | DELETE concept |
| **SCOPE_OVERLAP** | `concept` | TRUE MERGE → concept |
| **SCOPE_OVERLAP** | any other | HUMAN REVIEW |
| **COMPETING** | `concept`, `wishlist`, `refine` | TRUE MERGE |
| **COMPETING** | `rejected`, `infeasible`, `duplicative`, `broken`, `queued`, `pending`, `blocked`, `conflict` | BLOCK concept with note |
| **COMPETING** | everything else | AUTO-DUPLICATIVE with note (not a goal signal) |
| **INCOMPATIBLE** | `concept` | Claude picks better, DELETE other |
| **FALSE_POSITIVE** | — | SKIP (no action) |
| **Non-concept vs non-concept** | — | IGNORE |

### Effective Status Reference

Effective status is computed as `COALESCE(terminus, hold_reason, stage)`.

**Mergeable with concepts:**
- `stage = 'concept'`
- `hold_reason = 'wishlisted'`
- `hold_reason = 'polish'`
- `hold_reason = 'refine'`

**Block against:**
- `terminus IN ('rejected', 'infeasible', 'duplicative')`
- `hold_reason IN ('broken', 'queued', 'escalated', 'blocked', 'conflicted')`

**Auto-duplicative against:**
- `stage IN ('planning', 'implementing', 'reviewing', 'implemented', 'ready', 'polish', 'released')`
- `terminus IN ('legacy', 'deprecated', 'archived')`

### Three-Field System Internals

The vetting system computes a pseudo-status field using:
```sql
COALESCE(terminus, hold_reason, stage) AS status
```

Priority: terminus (terminal) > hold_reason (paused) > stage (position)

This means:
- Story with `terminus='rejected'` shows status='rejected' regardless of stage
- Story with `hold_reason='escalated'` shows status='escalated' (stage preserved for resume)
- Story with only stage set shows that stage value

---

## CI Mode

When running in CI (non-interactive environment), HUMAN_REVIEW cases cannot prompt for input. Instead:

- **HUMAN_REVIEW → DEFER_PENDING**: Set concept `hold_reason = 'refine'` with note listing conflicting story-node IDs (e.g., "Scope overlap detected with story-node IDs: 3.2.1, 4.1.1.3")
- All other automated actions work the same

**Detection**: CI mode is active when running in GitHub Actions or when explicitly specified.

**Purpose of refine status**: Stories set to `refine` should be reworked to eliminate scope overlaps before proceeding to approval.

---

## Decision Cache

The vetting system uses a persistent cache to avoid re-classifying the same story pairs on each run. This is especially important when running vetting daily, as most pairs will be false positives that don't need repeated LLM analysis.

### How It Works

1. **Version Tracking**: Each `story_nodes` record has a `version` column (INTEGER, default 1)
2. **Cache Storage**: Classification decisions are stored in `vetting_decisions` table with:
   - Canonical pair key (smaller ID first, e.g., `1.1|1.8.4`)
   - Version numbers at time of decision
   - Classification and action taken
3. **Invalidation**: When a story's `title`, `description`, `stage`, `hold_reason`, or `terminus` changes, increment its `version`. All cached pairs involving that story become stale.

### Cache Behavior

- **First run (cold cache)**: All 238 candidates processed by LLM, decisions stored
- **Subsequent runs (warm cache)**: ~150-180 false_positives skipped, only stale/new pairs classified
- **After story edit**: Pairs involving edited story re-enter Phase 2

### Reporting Cache Operations

When reporting cache activity, use specific language:

| Avoid | Use Instead |
|-------|-------------|
| "Stored 3 decisions" | "Cached 3 new conflict classifications (will skip on future runs)" |
| "Cache: stored..." | "Decision cache: recorded 3 pair classifications to avoid re-analysis" |
| "Cached for future runs" | "Cached to skip LLM re-classification on next run" |

**Why clear language matters**: "Stored" is ambiguous - it could mean written to database, saved to file, or something else. Explicit language helps users understand that cached decisions let future vetting runs skip pairs that have already been classified.

### CLI Commands

```bash
# Run schema migration (safe to run multiple times)
python .claude/skills/concept-vetting/vetting_cache.py migrate

# View cache statistics
python .claude/skills/concept-vetting/vetting_cache.py stats

# Clear all cached decisions
python .claude/skills/concept-vetting/vetting_cache.py clear
```

---

## Phase 1: Candidate Detection

Run the detector script to find candidate conflict pairs:

```bash
python .claude/skills/concept-vetting/candidate_detector.py
```

**What it does:** Scans all stories, applies keyword/similarity heuristics, filters cached false_positives, outputs candidate pairs as JSON.

**Output format:**
```json
{
  "total_stories": N,
  "candidates_before_cache": N,
  "candidates_after_cache": N,
  "cache_hits": {"false_positive": N, "other_cached": N, "uncached": N},
  "candidates": [
    {
      "story_a": {"id": "...", "title": "...", "status": "...", "description": "..."},
      "story_b": {"id": "...", "title": "...", "status": "...", "description": "..."},
      "signals": {"shared_keywords": [...], "title_similarity": 0.XX, ...}
    }
  ]
}
```
*Note: The `status` field is computed as `COALESCE(terminus, hold_reason, stage)` from the three-field system.*

**Detection thresholds:** Pairs flagged if any: shared implementation keywords ≥1, title Jaccard >0.15, title overlap >0.4, description Jaccard >0.10.

---

## Phase 2: Classification & Resolution

For each candidate pair from Phase 1, the main agent must:

### Step 1: Classify the Conflict

Read both story descriptions and determine the conflict type:

- **duplicate**: Stories describe essentially the same feature/requirement
- **scope_overlap**: One story's scope partially overlaps with another (but they're distinct)
- **competing**: Same problem, but different/incompatible solution approaches
- **incompatible**: Two concepts with mutually exclusive approaches (cannot merge)
- **false_positive**: Heuristics flagged it, but stories are actually unrelated

### Step 2: Determine Action

Use this lookup based on classification and effective statuses (computed from three-field system):

```python
# Effective status = COALESCE(terminus, hold_reason, stage)
# Note: concept=stage, wishlisted/polish/refine=hold_reason
MERGEABLE_STATUSES = {'concept', 'wishlisted', 'polish', 'refine'}
BLOCK_STATUSES = {'rejected', 'infeasible', 'duplicative', 'broken', 'queued', 'escalated', 'blocked', 'conflicted'}

def get_action(conflict_type, eff_status_a, eff_status_b, ci_mode=False):
    # Ensure concept is always story_a for consistent logic
    if eff_status_b == 'concept' and eff_status_a != 'concept':
        eff_status_a, eff_status_b = eff_status_b, eff_status_a

    if conflict_type == 'false_positive':
        return 'SKIP'

    if conflict_type == 'duplicate':
        if eff_status_b in MERGEABLE_STATUSES:
            return 'TRUE_MERGE'
        else:
            return 'DELETE_CONCEPT'

    if conflict_type == 'scope_overlap':
        if eff_status_a == 'concept' and eff_status_b == 'concept':
            return 'TRUE_MERGE'
        else:
            # In CI mode, defer to pending instead of blocking for human input
            return 'DEFER_PENDING' if ci_mode else 'HUMAN_REVIEW'

    if conflict_type == 'competing':
        if eff_status_b in MERGEABLE_STATUSES:
            return 'TRUE_MERGE'
        elif eff_status_b in BLOCK_STATUSES:
            return 'BLOCK_CONCEPT'
        else:
            return 'DUPLICATIVE_CONCEPT'

    if conflict_type == 'incompatible':
        # Claude picks the better concept, deletes the other
        return 'PICK_BETTER'

    return 'SKIP'
```

### Step 3: Execute Action

Use the actions script: `python .claude/skills/concept-vetting/vetting_actions.py <action> <args...>`

| Action | Command | Description |
|--------|---------|-------------|
| DELETE_CONCEPT | `python ...vetting_actions.py delete <concept_id>` | Remove concept from database |
| DUPLICATIVE_CONCEPT | `python ...vetting_actions.py duplicative <concept_id> <duplicate_of_id>` | Set terminus=duplicative (not a goal signal) |
| BLOCK_CONCEPT | `python ...vetting_actions.py block <concept_id> <blocking_id>` | Set hold_reason=blocked with note |
| DEFER_PENDING | `python ...vetting_actions.py defer <concept_id> <conflicting_id>` | Set hold_reason=pending (CI mode) |
| TRUE_MERGE | `python ...vetting_actions.py merge <keep_id> <delete_id> "<title>" "<desc>"` | Combine stories, delete one |
| CACHE | `python ...vetting_actions.py cache <id_a> <id_b> <classification> <action>` | Store decision in cache |

#### TRUE_MERGE Process

Before calling merge, Claude must:
1. Read both descriptions carefully
2. Create merged title (concise, captures both scopes)
3. Create merged description combining best "As a user..." statement, deduplicated acceptance criteria, unique details
4. Keep the story with lower/earlier ID (more established in hierarchy)

#### PICK_BETTER

For incompatible concepts, Claude evaluates which is better based on clarity, feasibility, project alignment, technical soundness. Then use DELETE on the worse concept.

#### HUMAN_REVIEW

Present stories side-by-side, offer options: [A] Reject A, [B] Reject B, [M] Merge, [S] Skip. Execute chosen action.

---

## Workflow Summary

1. **Run Phase 1** - Execute candidate detection Python script
2. **Parse results** - Load candidate pairs from JSON output
3. **For each candidate:**
   - Read both story descriptions
   - Classify conflict type (duplicate/scope_overlap/competing/incompatible/false_positive)
   - Look up action from decision matrix (pass `ci_mode=True` in CI environment)
   - Execute action (auto for most, DEFER_PENDING for scope overlaps in CI)
4. **Report summary** - Show counts of actions taken

### Expected Output (Interactive)

```
STORY VETTING COMPLETE
======================

Candidates scanned: 45
Actions taken:
  - Deleted: 8 duplicate concepts
  - Merged: 12 concept pairs
  - Duplicative: 3 competing concepts
  - Blocked: 2 concepts
  - Skipped: 15 false positives
  - Human review: 5 scope overlaps

Human review required for 5 conflicts (see above).
```

### Expected Output (CI Mode)

```
STORY VETTING COMPLETE (CI MODE)
================================

Candidates scanned: 45
Actions taken:
  - Deleted: 8 duplicate concepts
  - Merged: 12 concept pairs
  - Duplicative: 3 competing concepts
  - Blocked: 2 concepts
  - Skipped: 15 false positives
  - Needs refinement: 5 scope overlaps

5 concepts set to hold_reason='refine' for scope overlap resolution.
```

---

## References

- **Database:** `.claude/data/story-tree.db`
- **Schema:** `.claude/skills/story-tree/references/schema.sql`
- **SQL Queries:** `.claude/skills/story-tree/references/sql-queries.md`
- **Three-Field System:** `.claude/skills/story-tree/SKILL.md` (stage + hold_reason + terminus)
- **Shared Utilities:** `.claude/skills/story-tree/utility/story_db_common.py` (DB_PATH, delete_story, reject_concept, etc.)
concept-vetting | SkillHub