
    Ki^                    :   U d Z ddlmZ ddlZddlZddlZddlZddlmZ ddl	m
Z
  ej                  e      ZdVdZdd d	d
 ddddd dd ddddd dd ddddd dd ddddd dd ddddd dd  d!ddd"d# dd$ dddd%d& dd' dddd(d) dd* dddd+d, dd- dddd.
Zd/ed0<   dWdXd1ZdYd2Z	 dZ	 	 	 	 	 	 	 	 	 d[d3Z	 	 d\	 	 	 	 	 	 	 d]d4Zd5d6d7d8d9d:d;d8d<d=d>d8d?d@dAd8dBZdCedD<   d^d_dEZd`dFZdadGZdbdHZdIZe dJZdcdKZdbdLZdMdNdOdPdQdRZdSedT<   dddedUZy)fzClaude Code skills and hooks auto-install.

Generates Claude Code agent skill files, hooks configuration, and
CLAUDE.md integration for seamless code-review-graph usage.
Also supports multi-platform MCP server installation.
    )annotationsN)Path)Anyc                     t        j                         dk(  r t        j                         dz  dz  dz  dz  S t        j                         dz  dz  dz  S )z5Return the Zed settings.json path for the current OS.DarwinLibraryzApplication SupportZedsettings.jsonz.configzed)platformsystemr   home     d/home/jay/workspace/scripts/.codegraph-venv/lib/python3.12/site-packages/code_review_graph/skills.py_zed_settings_pathr      sM    H$yy{Y&)>>FXX99;"U*_<<r   Codexc                6    t        j                         dz  dz  S )N.codexzconfig.tomlr   r   roots    r   <lambda>r   !   s    DIIK($:]$J r   mcp_serversc                 L    t        j                         dz  j                         S )Nr   r   r   existsr   r   r   r   r   #   s    499;199; r   tomlT)nameconfig_pathkeydetectformat
needs_typezClaude Codec                    | dz  S )Nz	.mcp.jsonr   r   s    r   r   r   )   s    D;$6 r   
mcpServersc                      yNTr   r   r   r   r   r   +       r   objectCursorc                    | dz  dz  S )N.cursormcp.jsonr   r   s    r   r   r   1   s    D9$4z$A r   c                 L    t        j                         dz  j                         S )Nr-   r   r   r   r   r   r   3   s    499;2::< r   Windsurfc                <    t        j                         dz  dz  dz  S )N.codeiumwindsurfmcp_config.jsonr   r   s    r   r   r   9   s    DIIK*$<z$IL]$] r   c                 R    t        j                         dz  dz  j                         S )Nr2   r3   r   r   r   r   r   r   ;   s    499;3j@HHJ r   Fr	   c                    t               S N)r   r   s    r   r   r   A   s
    $6$8 r   context_serversc                 F    t               j                  j                         S r7   )r   parentr   r   r   r   r   r   C   s    ,.55<<> r   Continuec                6    t        j                         dz  dz  S )N	.continuezconfig.jsonr   r   s    r   r   r   I   s    DIIK+$=$M r   c                 L    t        j                         dz  j                         S )Nr=   r   r   r   r   r   r   K   s    499;4<<> r   arrayOpenCodec                    | dz  S )Nz.opencode.jsonr   r   s    r   r   r   Q   s    D+;$; r   c                      yr(   r   r   r   r   r   r   S   r)   r   Antigravityc                <    t        j                         dz  dz  dz  S )N.geminiantigravityr4   r   r   s    r   r   r   Y   s    DIIK)$;m$KN_$_ r   c                 R    t        j                         dz  dz  j                         S )NrE   rF   r   r   r   r   r   r   [   s    499;2]BJJL r   z	Qwen Codec                6    t        j                         dz  dz  S )N.qwenr
   r   r   s    r   r   r   a   s    DIIK'$9O$K r   c                 L    t        j                         dz  j                         S )NrI   r   r   r   r   r   r   c       499;088: r   Kiroc                    | dz  dz  dz  S )N.kirosettingsr.   r   r   s    r   r   r   i   s    D7NZ$?*$L r   c                 L    t        j                         dz  j                         S )NrN   r   r   r   r   r   r   k   rK   r   )
codexclaudecursorr3   r   continueopencoderF   qwenkirozdict[str, dict[str, Any]]	PLATFORMSc                t    t        j                  d      rdddgd}nddgd}| d   rd|d<   |dk(  rg |d	<   |S )
z*Build the MCP server entry for a platform.uvxcode-review-graphserve)commandargsr$   stdiotyperU   env)shutilwhich)platr!   entrys      r   _build_server_entryrf   r   sZ    ||E('2!
 +I
 Lf
jeLr   c                (   t        | t              r(| j                  dd      j                  dd      }d| dS t        | t              r| rdS dS t        | t              rddj                  d	 | D              z   d
z   S t        dt        |             )z(Format a primitive Python value as TOML.\z\\"z\"truefalse[z, c              3  2   K   | ]  }t        |        y wr7   )_format_toml_value).0items     r   	<genexpr>z%_format_toml_value.<locals>.<genexpr>   s     JD1$7Js   ]zUnsupported TOML value: )
isinstancestrreplaceboollistjoin	TypeErrorr`   )valueescapeds     r   rn   rn      s    %--f-55c5A7)1~%v+G+%TYYJEJJJSPP
.tE{o>
??r   c                   d| d}d}| j                         r| j                  d      }||v ry|g}|j                         D ]$  \  }}|j                  | dt	        |              & dj                  |      dz   }	|ry	| j                  j                  d	d	
       d}
|r.|j                  d      r|n|dz   }
|
j                  d      s|
dz  }
| j                  |
|	z   d       y	)zJAppend a Codex MCP server section without clobbering the rest of the file.z[mcp_servers.rr    utf-8encodingFz = 
Tparentsexist_okz

)
r   	read_textitemsappendrn   rx   r:   mkdirendswith
write_text)r    server_nameserver_entrydry_runsection_headerexistingsection_linesr!   rz   sectionprefixs              r   _merge_toml_mcp_serverr      s	    %[M3NH(('(:X%#$M"((* E
UuC(:5(A'BCDEii&-GTD9F%..t4(T/v&dNF6G+g>r   c                D   |dk(  rVt         j                         D ci c]  \  }} |d          s|| }}}d|vrK| dz  j                         r8t         d   |d<   n+|t         vrt        j	                  d|       g S |t         |   i}g }|j                         D ]E  \  }} |d   |       }	|d   }
t        ||      }|d	   d
k(  rzt        |	d||      }|s)t        d|d    d|	        |j                  |d          f|rt        d|d    d|	        nt        d|d    d|	        |j                  |d          i }|	j                         r&	 t        j                  |	j                  d            }|d	   dk(  r}|j!                  |
g       }t#        |t$              sg }t'        d |D              r*t        d|d    d|	        |j                  |d          Fddi|}|j                  |       |||
<   n\|j!                  |
i       }t#        |t(              si }d|v r*t        d|d    d|	        |j                  |d          ||d<   |||
<   |rt        d|d    d|	        n\|	j*                  j-                  dd       |	j/                  t        j0                  |d      dz   d       t        d|d    d|	        |j                  |d          H |S c c}}w # t        j                  t        f$ r t        j                  d|	       i }Y w xY w)a  Install MCP config for one or all detected platforms.

    Args:
        repo_root: Project root directory.
        target: Platform key or "all".
        dry_run: If True, print what would be done without writing.

    Returns:
        List of platform names that were configured.
    allr"   rW   rN   zUnknown platform: %sr    r!   )r!   r#   r   r[   )r   z  r   z: already configured in z  [dry-run] z: would write z: configured r~   r   z#Invalid JSON in %s, will overwrite.r?   c              3  h   K   | ]*  }t        |t              xr |j                  d       dk(   , yw)r   r[   N)rs   dictget)ro   ss     r   rq   z+install_platform_configs.<locals>.<genexpr>   s.     ]TU:a&O155=<O+OO]s   02Tr      indentr   )rX   r   is_dirloggererrorrf   r   printr   r   jsonloadsr   JSONDecodeErrorOSErrorwarningr   rs   rw   anyr   r:   r   r   dumps)	repo_roottargetr   kvplatforms_to_install
configuredr!   rd   r    
server_keyr   changedr   arr	arr_entryserverss                    r   install_platform_configsr      sj    1:1BTAkakm1TT--9w3F2N2N2P+4V+< ("LL/8I &	&(9:J)//1 >(	T/D/	:%[
*4S9>V#,#	G 4<.(@NO!!$v,/T&\N.NO4<.k]CDd6l+ $&::k&;&;W&;&MN
 >W$,,z2.Cc4(]Y\]]4<.(@NO!!$v,/!4EEIJJy!#&HZ ll:r2Ggt,"g-4<.(@NO!!$v,/+7G'(#*HZ Lfn[MJK$$TD$A""4::hq#AD#HSZ"[BtF|nM+?@$v,'}>(@ Y  UP (('2 DkRs   K$K$%K**1LLzExplore CodebasezDNavigate and understand codebase structure using the knowledge graphuB  ## Explore Codebase

Use the code-review-graph MCP tools to explore and understand the codebase.

### Steps

1. Run `list_graph_stats` to see overall codebase metrics.
2. Run `get_architecture_overview` for high-level community structure.
3. Use `list_communities` to find major modules, then `get_community` for details.
4. Use `semantic_search_nodes` to find specific functions or classes.
5. Use `query_graph` with patterns like `callers_of`, `callees_of`, `imports_of` to trace relationships.
6. Use `list_flows` and `get_flow` to understand execution paths.

### Tips

- Start broad (stats, architecture) then narrow down to specific areas.
- Use `children_of` on a file to see all its functions and classes.
- Use `find_large_functions` to identify complex code.

## Token Efficiency Rules
- ALWAYS start with `get_minimal_context(task="<your task>")` before any other graph tool.
- Use `detail_level="minimal"` on all calls. Only escalate to "standard" when minimal is insufficient.
- Target: complete any review/debug/refactor task in ≤5 tool calls and ≤800 total output tokens.)r   descriptionbodyzReview ChangeszBPerform a structured code review using change detection and impactu  ## Review Changes

Perform a thorough, risk-aware code review using the knowledge graph.

### Steps

1. Run `detect_changes` to get risk-scored change analysis.
2. Run `get_affected_flows` to find impacted execution paths.
3. For each high-risk function, run `query_graph` with pattern="tests_for" to check test coverage.
4. Run `get_impact_radius` to understand the blast radius.
5. For any untested changes, suggest specific test cases.

### Output Format

Provide findings grouped by risk level (high/medium/low) with:
- What changed and why it matters
- Test coverage status
- Suggested improvements
- Overall merge recommendation

## Token Efficiency Rules
- ALWAYS start with `get_minimal_context(task="<your task>")` before any other graph tool.
- Use `detail_level="minimal"` on all calls. Only escalate to "standard" when minimal is insufficient.
- Target: complete any review/debug/refactor task in ≤5 tool calls and ≤800 total output tokens.zDebug Issuez?Systematically debug issues using graph-powered code navigationu  ## Debug Issue

Use the knowledge graph to systematically trace and debug issues.

### Steps

1. Use `semantic_search_nodes` to find code related to the issue.
2. Use `query_graph` with `callers_of` and `callees_of` to trace call chains.
3. Use `get_flow` to see full execution paths through suspected areas.
4. Run `detect_changes` to check if recent changes caused the issue.
5. Use `get_impact_radius` on suspected files to see what else is affected.

### Tips

- Check both callers and callees to understand the full context.
- Look at affected flows to find the entry point that triggers the bug.
- Recent changes are the most common source of new issues.

## Token Efficiency Rules
- ALWAYS start with `get_minimal_context(task="<your task>")` before any other graph tool.
- Use `detail_level="minimal"` on all calls. Only escalate to "standard" when minimal is insufficient.
- Target: complete any review/debug/refactor task in ≤5 tool calls and ≤800 total output tokens.zRefactor Safelyz;Plan and execute safe refactoring using dependency analysisuD  ## Refactor Safely

Use the knowledge graph to plan and execute refactoring with confidence.

### Steps

1. Use `refactor_tool` with mode="suggest" for community-driven refactoring suggestions.
2. Use `refactor_tool` with mode="dead_code" to find unreferenced code.
3. For renames, use `refactor_tool` with mode="rename" to preview all affected locations.
4. Use `apply_refactor_tool` with the refactor_id to apply renames.
5. After changes, run `detect_changes` to verify the refactoring impact.

### Safety Checks

- Always preview before applying (rename mode gives you an edit list).
- Check `get_impact_radius` before major refactors.
- Use `get_affected_flows` to ensure no critical paths are broken.
- Run `find_large_functions` to identify decomposition targets.

## Token Efficiency Rules
- ALWAYS start with `get_minimal_context(task="<your task>")` before any other graph tool.
- Use `detail_level="minimal"` on all calls. Only escalate to "standard" when minimal is insufficient.
- Target: complete any review/debug/refactor task in ≤5 tool calls and ≤800 total output tokens.)zexplore-codebase.mdzreview-changes.mdzdebug-issue.mdzrefactor-safely.mdzdict[str, dict[str, str]]_SKILLSc                    || dz  dz  }|j                  dd       t        j                         D ]H  \  }}||z  }d|d    d|d    d	|d
    d}|j                  |d       t        j                  d|       J |S )a^  Generate Claude Code skill files.

    Creates `.claude/skills/` directory with 4 skill markdown files,
    each containing frontmatter and instructions.

    Args:
        repo_root: Repository root directory.
        skills_dir: Custom skills directory. Defaults to repo_root/.claude/skills.

    Returns:
        Path to the skills directory.
    .claudeskillsTr   z
---
name: r   z
description: r   z
---

r   r   r~   r   zWrote skill: %s)r   r   r   r   r   info)r   
skills_dirfilenameskillpathcontents         r   generate_skillsr     s     *X5
TD1"==? 
-%H$6]O $!-01 2V}oR	! 	 	'2%t,
- r   c                 4    ddddddgdgddd	d
dgdgdiS )u,  Return Claude Code hook definitions for .claude/settings.json.

    Hooks use the v1.x+ schema: each entry needs a ``matcher`` and a nested
    ``hooks`` array. Timeouts are in seconds. ``PreCommit`` is not a valid
    Claude Code event — pre-commit checks are handled by ``install_git_hook``.
    hookszEdit|Write|Bashr]   z%code-review-graph update --skip-flows   )r`   r]   timeout)matcherr   r}   zcode-review-graph status
   )PostToolUseSessionStartr   r   r   r   generate_hooks_configr     s^     	  1 %.'N')	  " %.'A')	
 r   c                   d}d}| dz  }|j                         st        j                  d|        y|dz  dz  }|j                  j	                  d	       |j                         rA|j                  d
      }||v r|S |j                  |j                  d      dz   |z   d
       n|j                  |d
       |j                  d       t        j                  d|       |S )uG  Install a git pre-commit hook that prints a risk summary before each commit.

    Called automatically by ``code-review-graph install``
    Creates ``.git/hooks/pre-commit`` if it doesn't exist, or appends to an
    existing one — preserving any hooks already there. Returns None when no
    ``.git`` directory is found.
    z#!/bin/sh
# Installed by code-review-graph. Remove this file to disable pre-commit graph checks.
if command -v code-review-graph >/dev/null 2>&1; then
    code-review-graph detect-changes --brief || true
fi
z code-review-graph detect-changesz.gitu<   No .git directory found at %s — skipping git hook install.Nr   z
pre-commitT)r   r~   r   r   i  zWrote git pre-commit hook: %s)r   r   r   r:   r   r   r   r   rstripchmodr   )r   scriptmarkergit_dir	hook_pathr   s         r   install_git_hookr     s    F 0F& G>>UW`a'!L0ID)&&&8XX__T2T9FBWUVg6OOE
KK/;r   c                   | dz  }|j                  dd       |dz  }i }|j                         r&	 t        j                  |j	                  d            }t               }|j                  |       |j                  t        j                  |d	
      dz   d       t        j                  d|       y# t        j
                  t        f$ r!}t        j                  d||       Y d}~d}~ww xY w)zWrite hooks config to .claude/settings.json.

    Merges with existing settings if present, preserving non-hook
    configuration.

    Args:
        repo_root: Repository root directory.
    r   Tr   r
   r~   r   zCould not read existing %s: %sNr   r   r   zWrote hooks config: %s)r   r   r   r   r   r   r   r   r   r   updater   r   r   )r   settings_dirsettings_pathr   exchooks_configs         r   install_hooksr     s     y(Ltd3 ?2M!H	Qzz-"9"97"9"KLH )*LOOL!TZZ;dBWU
KK(-8 $$g. 	QNN;]CPP	Qs   %B3 3C-C((C-z$<!-- code-review-graph MCP tools -->u  
## MCP Tools: code-review-graph

**IMPORTANT: This project has a knowledge graph. ALWAYS use the
code-review-graph MCP tools BEFORE using Grep/Glob/Read to explore
the codebase.** The graph is faster, cheaper (fewer tokens), and gives
you structural context (callers, dependents, test coverage) that file
scanning cannot.

### When to use graph tools FIRST

- **Exploring code**: `semantic_search_nodes` or `query_graph` instead of Grep
- **Understanding impact**: `get_impact_radius` instead of manually tracing imports
- **Code review**: `detect_changes` + `get_review_context` instead of reading entire files
- **Finding relationships**: `query_graph` with callers_of/callees_of/imports_of/tests_for
- **Architecture questions**: `get_architecture_overview` + `list_communities`

Fall back to Grep/Glob/Read **only** when the graph doesn't cover what you need.

### Key Tools

| Tool | Use when |
|------|----------|
| `detect_changes` | Reviewing code changes — gives risk-scored analysis |
| `get_review_context` | Need source snippets for review — token-efficient |
| `get_impact_radius` | Understanding blast radius of a change |
| `get_affected_flows` | Finding which execution paths are impacted |
| `query_graph` | Tracing callers, callees, imports, tests, dependencies |
| `semantic_search_nodes` | Finding functions/classes by name or keyword |
| `get_architecture_overview` | Understanding high-level codebase structure |
| `refactor_tool` | Planning renames, finding dead code |

### Workflow

1. The graph auto-updates on file changes (via hooks).
2. Use `detect_changes` for code review.
3. Use `get_affected_flows` to understand impact.
4. Use `query_graph` pattern="tests_for" to check coverage.
c                n   d}| j                         r| j                  d      }||v r!t        j                  d| j                         y|r|j                  d      sdnd}|rdnd}| j                  j                  dd       | j                  ||z   |z   |z   d       t        j                  d	|        y)
zAppend an instruction section to a file if not already present.

    Idempotent: checks if the marker is already present before appending.
    Creates the file if it doesn't exist.

    Returns True if the file was modified.
    r}   r~   r   z+%s already contains instructions, skipping.Fr   Tr   z Appended MCP tools section to %s)	r   r   r   r   r   r   r:   r   r   )	file_pathr   r   r   	separatorextra_newlines         r   _inject_instructionsr   5  s     H&&&8A9>>R ):):4)@bI$D"M4$7I-=GRYZ
KK2I>r   c                4    t        | dz  t        t               y)z&Append MCP tools section to CLAUDE.md.z	CLAUDE.mdN)r   _CLAUDE_MD_SECTION_MARKER_CLAUDE_MD_SECTION)r   s    r   inject_claude_mdr   M  s    K!r   )rS   rU   rF   )rF   )rS   )r3   )rW   )z	AGENTS.mdz	GEMINI.mdz.cursorrulesz.windsurfrulesz#.kiro/steering/code-review-graph.mdzdict[str, tuple[str, ...]]_PLATFORM_INSTRUCTION_FILESc                    g }t         j                         D ];  \  }}|dk7  r||vr| |z  }t        |t        t              s+|j                  |       = |S )u  Inject 'use graph first' instructions into platform rule files.

    Writes AGENTS.md, GEMINI.md, .cursorrules, and/or .windsurfrules
    depending on ``target``:

    - ``"all"`` (default): writes every file — matches pre-filter behavior.
    - ``"claude"``: writes nothing (CLAUDE.md is handled by ``inject_claude_md``).
    - any other platform key (``cursor``, ``windsurf``, ``antigravity``,
      ``opencode``): writes only the files associated with that platform.

    Returns list of filenames that were created or updated.
    r   )r   r   r   r   r   r   )r   r   updatedr   ownersr   s         r   inject_platform_instructionsr   b  sb     G7==? %&U?vV38#&?ASTNN8$% Nr   )returnr   )r}   )rd   dict[str, Any]r!   rt   r   r   )rz   r   r   rt   )F)
r    r   r   rt   r   r   r   rv   r   rv   )r   F)r   r   r   rt   r   rv   r   	list[str]r7   )r   r   r   Path | Noner   r   )r   r   )r   r   r   r   )r   r   r   None)r   r   r   rt   r   rt   r   rv   )r   )r   r   r   rt   r   r   ) __doc__
__future__r   r   loggingr   rb   pathlibr   typingr   	getLogger__name__r   r   rX   __annotations__rf   rn   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>r      s   #      			8	$= J; 6 A< ]J 8 > M> ; _L K: L:SQ(	$ Qh&	@  	 ! 	
 
D \\\ \ 	\F #].	: ![.	: X.	6 "T.	go&	" od@"J#L96 C 34 &5 & R0 7!#+4; 7 r   