/**
 * MCP Resources (Multi-Repo)
 *
 * Provides structured on-demand data to AI agents.
 * All resources use repo-scoped URIs: codragraph://repo/{name}/context
 */
import { checkStaleness } from './staleness.js';
/**
 * Static resources — includes per-repo resources and the global repos list
 */
export function getResourceDefinitions() {
    return [
        {
            uri: 'codragraph://repos',
            name: 'All Indexed Repositories',
            description: 'List of all indexed repos with stats. Read this first to discover available repos.',
            mimeType: 'text/yaml',
        },
        {
            uri: 'codragraph://setup',
            name: 'CodraGraph Setup Content',
            description: 'Returns AGENTS.md content for all indexed repos. Useful for setup/onboarding.',
            mimeType: 'text/markdown',
        },
    ];
}
/**
 * Dynamic resource templates
 */
export function getResourceTemplates() {
    return [
        {
            uriTemplate: 'codragraph://repo/{name}/context',
            name: 'Repo Overview',
            description: 'Codebase stats, staleness check, and available tools',
            mimeType: 'text/yaml',
        },
        {
            uriTemplate: 'codragraph://repo/{name}/clusters',
            name: 'Repo Modules',
            description: 'All functional areas (Leiden clusters)',
            mimeType: 'text/yaml',
        },
        {
            uriTemplate: 'codragraph://repo/{name}/feature-clusters',
            name: 'Repo Feature Clusters',
            description: 'Human-facing product/domain feature areas with members and dependencies',
            mimeType: 'text/yaml',
        },
        {
            uriTemplate: 'codragraph://repo/{name}/processes',
            name: 'Repo Processes',
            description: 'All execution flows',
            mimeType: 'text/yaml',
        },
        {
            uriTemplate: 'codragraph://repo/{name}/schema',
            name: 'Graph Schema',
            description: 'Node/edge schema for Cypher queries',
            mimeType: 'text/yaml',
        },
        {
            uriTemplate: 'codragraph://repo/{name}/cluster/{clusterName}',
            name: 'Module Detail',
            description: 'Deep dive into a specific functional area',
            mimeType: 'text/yaml',
        },
        {
            uriTemplate: 'codragraph://repo/{name}/feature/{featureName}',
            name: 'Feature Context',
            description: 'Members, line ranges, dependencies, and flows for one feature cluster',
            mimeType: 'text/yaml',
        },
        {
            uriTemplate: 'codragraph://repo/{name}/process/{processName}',
            name: 'Process Trace',
            description: 'Step-by-step execution trace',
            mimeType: 'text/yaml',
        },
        // ── Phase 4: versioned graph ─────────────────────────────────
        {
            uriTemplate: 'codragraph://repo/{name}/graphstore/log',
            name: 'Graph Commit Log',
            description: 'Phase 4: history of content-addressed snapshots for the indexed repo, newest-first. Pairs with the graphstore_log tool.',
            mimeType: 'text/yaml',
        },
        {
            uriTemplate: 'codragraph://repo/{name}/graphstore/branches',
            name: 'Graph Branches',
            description: 'Phase 4: list of versioned-graph branches with their head commits. Pairs with graphstore_branches.',
            mimeType: 'text/yaml',
        },
        {
            uriTemplate: 'codragraph://repo/{name}/graphstore/head',
            name: 'Graph HEAD',
            description: "Phase 4: the indexed repo's current branch + head commit, plus the snapshot it points at. Pairs with graphstore_log/diff/blame.",
            mimeType: 'text/yaml',
        },
        {
            uriTemplate: 'codragraph://repo/{name}/graphpack/status',
            name: 'Team Graphpack Status',
            description: 'Team graphpack provenance: canonical main graph, PR overlay, local graph, chunk health, and compatibility.',
            mimeType: 'text/yaml',
        },
        {
            uriTemplate: 'codragraph://repo/{name}/graphpack/lock',
            name: 'Team Graphpack Lock',
            description: 'Committed .codragraph/index.lock.json content for shared team graph bootstrapping.',
            mimeType: 'application/json',
        },
        {
            uriTemplate: 'codragraph://repo/{name}/semantic-relationships',
            name: 'Semantic Relationships',
            description: 'Developer-intent relationship families with confidence, evidence, provenance, and extractor version.',
            mimeType: 'text/yaml',
        },
        {
            uriTemplate: 'codragraph://repo/{name}/recipes',
            name: 'Harness Recipes',
            description: 'Phase 4 × Phase 3 moat: harness recipes learned for this repo, keyed by (snapshot_id, task_family). Pairs with harness_recipes_list / harness_recipes_lookup / harness_swarm_run with use_cache.',
            mimeType: 'text/yaml',
        },
        {
            uriTemplate: 'codragraph://repo/{name}/recipes/{family}',
            name: 'Recipes for Task Family',
            description: 'Phase 4 × Phase 3 moat: recipes filtered to a specific task family across all snapshots — visualizes how the recipe set evolves as the codebase changes.',
            mimeType: 'text/yaml',
        },
        {
            uriTemplate: 'codragraph://group/{name}/contracts',
            name: 'Group Contract Registry',
            description: 'Cross-repo contract registry for a repository group. Optional query: type, repo, unmatchedOnly (true|false).',
            mimeType: 'text/yaml',
        },
        {
            uriTemplate: 'codragraph://group/{name}/status',
            name: 'Group Index Status',
            description: 'Per-repo index and contract-registry staleness for a repository group',
            mimeType: 'text/yaml',
        },
    ];
}
function parseUnmatchedOnlyParam(raw) {
    if (raw === null)
        return undefined;
    const v = raw.trim().toLowerCase();
    if (v === 'true' || v === '1')
        return true;
    if (v === 'false' || v === '0')
        return false;
    return undefined;
}
/**
 * Parse a CodraGraph resource URI (repos, setup, per-repo, or per-group templates).
 * Used by `readResource` and tests (round-trip / dispatch coverage).
 */
export function parseResourceUri(uri) {
    if (uri === 'codragraph://repos')
        return { kind: 'repos' };
    if (uri === 'codragraph://setup')
        return { kind: 'setup' };
    let u;
    try {
        u = new URL(uri);
    }
    catch {
        throw new Error(`Unknown resource URI: ${uri}`);
    }
    if (u.protocol !== 'codragraph:') {
        throw new Error(`Unknown resource URI: ${uri}`);
    }
    if (u.hostname === 'group') {
        const segments = u.pathname
            .replace(/^\/+|\/+$/g, '')
            .split('/')
            .filter(Boolean);
        if (segments.length < 2) {
            throw new Error(`Invalid group resource URI (expected codragraph://group/{name}/contracts or .../status): ${uri}`);
        }
        const tail = segments[segments.length - 1];
        if (tail !== 'contracts' && tail !== 'status') {
            throw new Error(`Unknown group resource path in URI: ${uri}`);
        }
        const groupName = segments
            .slice(0, -1)
            .map((s) => decodeURIComponent(s))
            .join('/');
        if (!groupName) {
            throw new Error(`Invalid group resource URI (empty group name): ${uri}`);
        }
        if (tail === 'status') {
            return { kind: 'group', groupName, resourceType: 'status' };
        }
        const contractsFilter = {};
        const type = u.searchParams.get('type');
        if (type && type.trim())
            contractsFilter.type = type.trim();
        const repo = u.searchParams.get('repo');
        if (repo && repo.trim())
            contractsFilter.repo = repo.trim();
        if (u.searchParams.has('unmatchedOnly')) {
            const coerced = parseUnmatchedOnlyParam(u.searchParams.get('unmatchedOnly'));
            if (coerced !== undefined)
                contractsFilter.unmatchedOnly = coerced;
        }
        return { kind: 'group', groupName, resourceType: 'contracts', contractsFilter };
    }
    if (u.hostname === 'repo') {
        const segments = u.pathname
            .replace(/^\/+|\/+$/g, '')
            .split('/')
            .filter(Boolean);
        if (segments.length < 2) {
            throw new Error(`Unknown resource URI: ${uri}`);
        }
        const repoName = decodeURIComponent(segments[0]);
        const restEncoded = segments.slice(1);
        const rest = restEncoded.map((s) => decodeURIComponent(s)).join('/');
        if (rest.startsWith('cluster/')) {
            return {
                kind: 'repo',
                repoName,
                resourceType: 'cluster',
                param: rest.replace(/^cluster\//, ''),
            };
        }
        if (rest.startsWith('feature/')) {
            return {
                kind: 'repo',
                repoName,
                resourceType: 'feature',
                param: rest.replace(/^feature\//, ''),
            };
        }
        if (rest.startsWith('process/')) {
            return {
                kind: 'repo',
                repoName,
                resourceType: 'process',
                param: rest.replace(/^process\//, ''),
            };
        }
        return { kind: 'repo', repoName, resourceType: rest };
    }
    throw new Error(`Unknown resource URI: ${uri}`);
}
/**
 * Read a resource and return its content
 */
export async function readResource(uri, backend) {
    const parsed = parseResourceUri(uri);
    if (parsed.kind === 'repos') {
        return getReposResource(backend);
    }
    if (parsed.kind === 'setup') {
        return getSetupResource(backend);
    }
    if (parsed.kind === 'group') {
        if (parsed.resourceType === 'contracts') {
            return backend.readGroupContractsResource(parsed.groupName, parsed.contractsFilter);
        }
        return backend.readGroupStatusResource(parsed.groupName);
    }
    const repoName = parsed.repoName;
    switch (parsed.resourceType) {
        case 'context':
            return getContextResource(backend, repoName);
        case 'clusters':
            return getClustersResource(backend, repoName);
        case 'feature-clusters':
            return getFeatureClustersResource(backend, repoName);
        case 'processes':
            return getProcessesResource(backend, repoName);
        case 'schema':
            return getSchemaResource();
        case 'cluster':
            return getClusterDetailResource(parsed.param, backend, repoName);
        case 'feature':
            return getFeatureDetailResource(parsed.param, backend, repoName);
        case 'process':
            return getProcessDetailResource(parsed.param, backend, repoName);
        case 'graphstore/log':
            return getGraphstoreLogResource(backend, repoName);
        case 'graphstore/branches':
            return getGraphstoreBranchesResource(backend, repoName);
        case 'graphstore/head':
            return getGraphstoreHeadResource(backend, repoName);
        case 'graphpack/status':
            return getGraphpackStatusResource(backend, repoName);
        case 'graphpack/lock':
            return getGraphpackLockResource(backend, repoName);
        case 'semantic-relationships':
            return getSemanticRelationshipsResource(backend, repoName);
        case 'recipes':
            return getRecipesResource(backend, repoName);
        default:
            if (parsed.resourceType.startsWith('recipes/')) {
                const family = parsed.resourceType.slice('recipes/'.length);
                return getRecipesResource(backend, repoName, family);
            }
            throw new Error(`Unknown resource: ${uri}`);
    }
}
// ─── Resource Implementations ─────────────────────────────────────────
/**
 * Repos resource — list all indexed repositories
 */
async function getReposResource(backend) {
    const repos = await backend.listRepos();
    if (repos.length === 0) {
        return 'repos: []\n# No repositories indexed. Run: codragraph analyze';
    }
    const lines = ['repos:'];
    for (const repo of repos) {
        lines.push(`  - name: "${repo.name}"`);
        lines.push(`    path: "${repo.path}"`);
        lines.push(`    indexed: "${repo.indexedAt}"`);
        lines.push(`    commit: "${repo.lastCommit?.slice(0, 7) || 'unknown'}"`);
        if (repo.stats) {
            lines.push(`    files: ${repo.stats.files || 0}`);
            lines.push(`    symbols: ${repo.stats.nodes || 0}`);
            lines.push(`    processes: ${repo.stats.processes || 0}`);
        }
    }
    if (repos.length > 1) {
        lines.push('');
        lines.push('# Multiple repos indexed. Use repo parameter in tool calls:');
        lines.push(`# codragraph_search({query: "auth", repo: "${repos[0].name}"})`);
    }
    return lines.join('\n');
}
/**
 * Context resource — codebase overview for a specific repo
 */
async function getContextResource(backend, repoName) {
    // Resolve repo
    const repo = await backend.resolveRepo(repoName);
    const repoId = repo.name.toLowerCase();
    const context = backend.getContext(repoId) || backend.getContext();
    if (!context) {
        return 'error: No codebase loaded. Run: codragraph analyze';
    }
    // Check staleness
    const repoPath = repo.repoPath;
    const lastCommit = repo.lastCommit || 'HEAD';
    const staleness = repoPath
        ? checkStaleness(repoPath, lastCommit)
        : { isStale: false, commitsBehind: 0 };
    const lines = [`project: ${context.projectName}`];
    if (staleness.isStale && staleness.hint) {
        lines.push('');
        lines.push(`staleness: "${staleness.hint}"`);
    }
    lines.push('');
    lines.push('stats:');
    lines.push(`  files: ${context.stats.fileCount}`);
    lines.push(`  symbols: ${context.stats.functionCount}`);
    lines.push(`  processes: ${context.stats.processCount}`);
    lines.push(`  feature_clusters: ${repo.stats?.featureClusters || 0}`);
    lines.push('');
    lines.push('tools_available:');
    lines.push('  - query: Process-grouped code intelligence (execution flows related to a concept)');
    lines.push('  - context: 360-degree symbol view (categorized refs, process participation)');
    lines.push('  - impact: Blast radius analysis (what breaks if you change a symbol)');
    lines.push('  - detect_changes: Git-diff impact analysis (what do your changes affect)');
    lines.push('  - rename: Multi-file coordinated rename with confidence tags');
    lines.push('  - graphpack_status: Team graph provenance and artifact health');
    lines.push('  - semantic_relationships: Developer-intent semantic edge families');
    lines.push('  - cypher: Raw graph queries');
    lines.push('  - list_repos: Discover all indexed repositories');
    lines.push('');
    lines.push('re_index: Run `npx @codragraph/cli analyze` in terminal if data is stale');
    lines.push('');
    lines.push('resources_available:');
    lines.push('  - codragraph://repos: All indexed repositories');
    lines.push(`  - codragraph://repo/${context.projectName}/clusters: All functional areas`);
    lines.push(`  - codragraph://repo/${context.projectName}/feature-clusters: Human-facing feature areas`);
    lines.push(`  - codragraph://repo/${context.projectName}/processes: All execution flows`);
    lines.push(`  - codragraph://repo/${context.projectName}/graphpack/status: Team graphpack status`);
    lines.push(`  - codragraph://repo/${context.projectName}/semantic-relationships: Developer-intent relationships`);
    lines.push(`  - codragraph://repo/${context.projectName}/cluster/{name}: Module details`);
    lines.push(`  - codragraph://repo/${context.projectName}/feature/{name}: Feature context pack`);
    lines.push(`  - codragraph://repo/${context.projectName}/process/{name}: Process trace`);
    lines.push('  - codragraph://group/{name}/contracts: Group contract registry (optional ?type=&repo=&unmatchedOnly=)');
    lines.push('  - codragraph://group/{name}/status: Group index / contract staleness');
    return lines.join('\n');
}
/**
 * Clusters resource — queries graph directly via backend.queryClusters()
 */
async function getClustersResource(backend, repoName) {
    try {
        const result = await backend.queryClusters(repoName, 100);
        if (!result.clusters || result.clusters.length === 0) {
            return 'modules: []\n# No functional areas detected. Run: codragraph analyze';
        }
        const displayLimit = 20;
        const lines = ['modules:'];
        const toShow = result.clusters.slice(0, displayLimit);
        for (const cluster of toShow) {
            const label = cluster.heuristicLabel || cluster.label || cluster.id;
            lines.push(`  - name: "${label}"`);
            lines.push(`    symbols: ${cluster.symbolCount || 0}`);
            if (cluster.cohesion) {
                lines.push(`    cohesion: ${(cluster.cohesion * 100).toFixed(0)}%`);
            }
        }
        if (result.clusters.length > displayLimit) {
            lines.push(`\n# Showing top ${displayLimit} of ${result.clusters.length} modules. Use codragraph_query for deeper search.`);
        }
        return lines.join('\n');
    }
    catch (err) {
        return `error: ${err.message}`;
    }
}
/**
 * Processes resource — queries graph directly via backend.queryProcesses()
 */
/**
 * Feature clusters resource - human-facing product/domain areas.
 */
async function getFeatureClustersResource(backend, repoName) {
    try {
        const result = await backend.queryFeatureClusters(repoName, 100);
        if (!result.clusters || result.clusters.length === 0) {
            return 'feature_clusters: []\n# No feature clusters detected. Run: codragraph analyze';
        }
        const displayLimit = 30;
        const lines = ['feature_clusters:'];
        for (const cluster of result.clusters.slice(0, displayLimit)) {
            lines.push(`  - name: "${cluster.name || cluster.slug || cluster.id}"`);
            lines.push(`    slug: "${cluster.slug || ''}"`);
            lines.push(`    kind: ${cluster.featureKind || 'feature'}`);
            if (cluster.summary)
                lines.push(`    summary: "${cluster.summary}"`);
            lines.push(`    members: ${cluster.memberCount || 0}`);
            if (cluster.routes?.length)
                lines.push(`    routes: ${cluster.routes.length}`);
            if (cluster.tools?.length)
                lines.push(`    tools: ${cluster.tools.length}`);
            lines.push(`    confidence: ${Math.round((cluster.confidence || 0) * 100)}%`);
        }
        if (result.clusters.length > displayLimit) {
            lines.push(`\n# Showing top ${displayLimit} of ${result.clusters.length} feature clusters. Use feature_context for details.`);
        }
        return lines.join('\n');
    }
    catch (err) {
        return `error: ${err.message}`;
    }
}
async function getProcessesResource(backend, repoName) {
    try {
        const result = await backend.queryProcesses(repoName, 50);
        if (!result.processes || result.processes.length === 0) {
            return 'processes: []\n# No processes detected. Run: codragraph analyze';
        }
        const displayLimit = 20;
        const lines = ['processes:'];
        const toShow = result.processes.slice(0, displayLimit);
        for (const proc of toShow) {
            const label = proc.heuristicLabel || proc.label || proc.id;
            lines.push(`  - name: "${label}"`);
            lines.push(`    type: ${proc.processType || 'unknown'}`);
            lines.push(`    steps: ${proc.stepCount || 0}`);
        }
        if (result.processes.length > displayLimit) {
            lines.push(`\n# Showing top ${displayLimit} of ${result.processes.length} processes. Use codragraph_query for deeper search.`);
        }
        return lines.join('\n');
    }
    catch (err) {
        return `error: ${err.message}`;
    }
}
/**
 * Schema resource — graph structure for Cypher queries
 */
function getSchemaResource() {
    return `# CodraGraph Graph Schema

nodes:
  - File: Source code files
  - Folder: Directory containers
  - Function: Functions and arrow functions
  - Class: Class definitions
  - Interface: Interface/type definitions
  - Method: Class methods
  - CodeElement: Catch-all for other code elements
  - Community: Auto-detected functional area (Leiden algorithm)
  - Process: Execution flow trace
  - FeatureCluster: Human-facing feature/domain cluster for targeted context

additional_node_types: "Multi-language: Struct, Enum, Macro, Typedef, Union, Namespace, Trait, Impl, TypeAlias, Const, Static, Property, Record, Delegate, Annotation, Constructor, Template, Module (use backticks in queries: \`Struct\`, \`Enum\`, etc.)"

node_properties:
  common: "name (STRING), filePath (STRING), startLine (INT32), endLine (INT32)"
  Method: "parameterCount (INT32), returnType (STRING), isVariadic (BOOL), visibility (STRING), isStatic (BOOL), isAbstract (BOOL), isFinal (BOOL), isVirtual (BOOL), isOverride (BOOL), isAsync (BOOL), isPartial (BOOL), requiredParameterCount (INT32), parameterTypes (STRING[]), annotations (STRING[])"
  Function: "parameterCount (INT32), returnType (STRING), isVariadic (BOOL), visibility (STRING), isStatic (BOOL), isAbstract (BOOL), isFinal (BOOL), isAsync (BOOL), parameterTypes (STRING[]), annotations (STRING[])"
  Property: "declaredType (STRING) — the field's type annotation (e.g., 'Address', 'City'). Used for field-access chain resolution."
  Constructor: "parameterCount (INT32), visibility (STRING), isStatic (BOOL), parameterTypes (STRING[])"
  FeatureCluster: "name (STRING), slug (STRING), featureKind (STRING), summary (STRING), repo (STRING), service (STRING), memberCount (INT32), entryPointIds (STRING[]), routes (STRING[]), tools (STRING[]), testCoverageHints (STRING[]), lastIndexedCommit (STRING), confidence (DOUBLE), signals (STRING[])"
  Community: "heuristicLabel (STRING), cohesion (DOUBLE), symbolCount (INT32), keywords (STRING[]), description (STRING), enrichedBy (STRING)"
  Process: "heuristicLabel (STRING), processType (STRING — 'intra_community' or 'cross_community'), stepCount (INT32), communities (STRING[]), entryPointId (STRING), terminalId (STRING)"

relationships:
  - CONTAINS: File/Folder contains child
  - DEFINES: File defines a symbol
  - CALLS: Function/method invocation
  - IMPORTS: Module imports
  - EXTENDS: Class inheritance
  - IMPLEMENTS: Interface implementation
  - HAS_METHOD: Class/Struct/Interface owns a Method
  - HAS_PROPERTY: Class/Struct/Interface owns a Property (field)
  - ACCESSES: Function/Method reads or writes a Property (reason: 'read' or 'write')
  - METHOD_OVERRIDES: Method overrides another Method (MRO)
  - METHOD_IMPLEMENTS: ConcreteMethod implements InterfaceMethod (matched by name + parameterTypes)
  - MEMBER_OF: Symbol belongs to community
  - STEP_IN_PROCESS: Symbol is step N in process
  - WRAPS: Wrapper/decorator relationship
  - QUERIES: Data/query relationship
  - FEATURE_MEMBER_OF: Symbol/file belongs to a FeatureCluster
  - FEATURE_DEPENDS_ON: FeatureCluster depends on another FeatureCluster via member edges

relationship_table: "All relationships use a single CodeRelation table with a 'type' property. Properties: type (STRING), confidence (DOUBLE), reason (STRING), step (INT32)"

example_queries:
  find_callers: |
    MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "myFunc"})
    RETURN caller.name, caller.filePath
  
  find_community_members: |
    MATCH (s)-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community)
    WHERE c.heuristicLabel = "Auth"
    RETURN s.name, labels(s)[0] AS type
  
  trace_process: |
    MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
    WHERE p.heuristicLabel = "LoginFlow"
    RETURN s.name, r.step
    ORDER BY r.step
`;
}
/**
 * Cluster detail resource — queries graph directly via backend.queryClusterDetail()
 */
async function getClusterDetailResource(name, backend, repoName) {
    try {
        const result = await backend.queryClusterDetail(name, repoName);
        if (result.error) {
            return `error: ${result.error}`;
        }
        const cluster = result.cluster;
        const members = result.members || [];
        const lines = [
            `module: "${cluster.heuristicLabel || cluster.label || cluster.id}"`,
            `symbols: ${cluster.symbolCount || members.length}`,
        ];
        if (cluster.cohesion) {
            lines.push(`cohesion: ${(cluster.cohesion * 100).toFixed(0)}%`);
        }
        if (members.length > 0) {
            lines.push('');
            lines.push('members:');
            for (const member of members.slice(0, 20)) {
                lines.push(`  - name: ${member.name}`);
                lines.push(`    type: ${member.type}`);
                lines.push(`    file: ${member.filePath}`);
            }
            if (members.length > 20) {
                lines.push(`  # ... and ${members.length - 20} more`);
            }
        }
        return lines.join('\n');
    }
    catch (err) {
        return `error: ${err.message}`;
    }
}
/**
 * Process detail resource — queries graph directly via backend.queryProcessDetail()
 */
async function getFeatureDetailResource(name, backend, repoName) {
    try {
        const result = await backend.queryFeatureContext(name, repoName);
        if (result.error) {
            return `error: ${result.error}`;
        }
        const cluster = result.cluster;
        const members = result.members || [];
        const outgoing = result.dependencies?.outgoing || [];
        const incoming = result.dependencies?.incoming || [];
        const processes = result.processes || [];
        const lines = [
            `feature: "${cluster.name || cluster.slug || cluster.id}"`,
            `slug: "${cluster.slug || ''}"`,
            `kind: ${cluster.featureKind || 'feature'}`,
            `members: ${cluster.memberCount || members.length}`,
            `confidence: ${Math.round((cluster.confidence || 0) * 100)}%`,
        ];
        if (members.length > 0) {
            lines.push('');
            lines.push('members:');
            for (const member of members.slice(0, 30)) {
                lines.push(`  - name: ${member.name}`);
                lines.push(`    type: ${member.type}`);
                lines.push(`    file: ${member.filePath || ''}`);
                if (member.startLine !== undefined)
                    lines.push(`    startLine: ${member.startLine}`);
                if (member.endLine !== undefined)
                    lines.push(`    endLine: ${member.endLine}`);
            }
        }
        if (outgoing.length > 0 || incoming.length > 0) {
            lines.push('');
            lines.push('dependencies:');
            if (outgoing.length > 0) {
                lines.push('  outgoing:');
                for (const dep of outgoing.slice(0, 15)) {
                    lines.push(`    - ${dep.name || dep.slug || dep.id}`);
                }
            }
            if (incoming.length > 0) {
                lines.push('  incoming:');
                for (const dep of incoming.slice(0, 15)) {
                    lines.push(`    - ${dep.name || dep.slug || dep.id}`);
                }
            }
        }
        if (processes.length > 0) {
            lines.push('');
            lines.push('processes:');
            for (const proc of processes.slice(0, 10)) {
                lines.push(`  - ${proc.heuristicLabel || proc.label || proc.id}`);
            }
        }
        return lines.join('\n');
    }
    catch (err) {
        return `error: ${err.message}`;
    }
}
async function getProcessDetailResource(name, backend, repoName) {
    try {
        const result = await backend.queryProcessDetail(name, repoName);
        if (result.error) {
            return `error: ${result.error}`;
        }
        const proc = result.process;
        const steps = result.steps || [];
        const lines = [
            `name: "${proc.heuristicLabel || proc.label || proc.id}"`,
            `type: ${proc.processType || 'unknown'}`,
            `step_count: ${proc.stepCount || steps.length}`,
        ];
        if (steps.length > 0) {
            lines.push('');
            lines.push('trace:');
            for (const step of steps) {
                lines.push(`  ${step.step}: ${step.name} (${step.filePath})`);
            }
        }
        return lines.join('\n');
    }
    catch (err) {
        return `error: ${err.message}`;
    }
}
/**
 * Setup resource — generates AGENTS.md content for all indexed repos.
 * Useful for `codragraph setup` onboarding or dynamic content injection.
 */
async function getSetupResource(backend) {
    const repos = await backend.listRepos();
    if (repos.length === 0) {
        return '# CodraGraph\n\nNo repositories indexed. Run: `npx @codragraph/cli analyze` in a repository.';
    }
    const sections = [];
    for (const repo of repos) {
        const stats = repo.stats || {};
        const lines = [
            `# CodraGraph MCP — ${repo.name}`,
            '',
            `This project is indexed by CodraGraph as **${repo.name}** (${stats.nodes || 0} symbols, ${stats.edges || 0} relationships, ${stats.processes || 0} execution flows).`,
            '',
            '## Tools',
            '',
            '| Tool | What it gives you |',
            '|------|-------------------|',
            '| `query` | Process-grouped code intelligence — execution flows related to a concept |',
            '| `context` | 360-degree symbol view — categorized refs, processes it participates in |',
            '| `impact` | Symbol blast radius — what breaks at depth 1/2/3 with confidence |',
            '| `detect_changes` | Git-diff impact — what do your current changes affect |',
            '| `rename` | Multi-file coordinated rename with confidence-tagged edits |',
            '| `feature_clusters` | Product/domain feature map for targeted context |',
            '| `feature_context` | Members, line ranges, dependencies, and flows for one feature |',
            '| `cluster_query` | Cluster-first alias for `feature_clusters` |',
            '| `cluster_context` | Cluster-first alias for `feature_context` |',
            '| `context_pack` | Compact context pack for one feature cluster |',
            '| `cluster_impact` | Feature-level blast radius across cluster dependencies |',
            '| `cypher` | Raw graph queries |',
            '| `list_repos` | Discover indexed repos |',
            '',
            '## Resources',
            '',
            `- \`codragraph://repo/${repo.name}/context\` — Stats, staleness check`,
            `- \`codragraph://repo/${repo.name}/clusters\` — All functional areas`,
            `- \`codragraph://repo/${repo.name}/feature-clusters\` — Human-facing feature areas`,
            `- \`codragraph://repo/${repo.name}/feature/{name}\` — Feature context pack`,
            `- \`codragraph://repo/${repo.name}/processes\` — All execution flows`,
            `- \`codragraph://repo/${repo.name}/schema\` — Graph schema for Cypher`,
            '',
            '## Cross-platform commands',
            '',
            '- Use `npx @codragraph/cli ...`, `bunx @codragraph/cli ...`, or `codragraph ...` in Windows PowerShell, macOS bash/zsh, and Linux shells.',
            '- Prefer `npm --prefix <package> <script>` or `bun run --filter <workspace> <script>` from repo root for package checks instead of shell-specific `cd dir && ...` chains.',
        ];
        sections.push(lines.join('\n'));
    }
    return sections.join('\n\n---\n\n');
}
// ─── Phase 4: Versioned-graph resources ─────────────────────────────────
async function getGraphstoreLogResource(backend, repoName) {
    const repo = await backend.resolveRepo(repoName);
    const handler = await import('./local/graphstore-handler.js');
    let result;
    try {
        result = await handler.handleGraphstoreLog({
            storagePath: repo.storagePath,
            limit: 50,
        });
    }
    catch (err) {
        return `error: ${err instanceof Error ? err.message : String(err)}`;
    }
    if (result.commits.length === 0) {
        return [
            `repo: "${repo.name}"`,
            'commits: []',
            '# No graph commits yet. Run `codragraph analyze` to create the first snapshot.',
        ].join('\n');
    }
    const lines = [`repo: "${repo.name}"`, `branch: "${result.branch ?? '(detached)'}"`];
    lines.push('commits:');
    for (const c of result.commits) {
        lines.push(`  - id: "${c.id}"`);
        lines.push(`    short: "${c.short}"`);
        lines.push(`    snapshot: "${c.snapshot}"`);
        lines.push(`    ts: "${c.ts}"`);
        lines.push(`    author: "${c.author}"`);
        lines.push(`    message: ${JSON.stringify(c.message)}`);
        if (c.parents.length > 0) {
            lines.push(`    parents: [${c.parents.map((p) => `"${p}"`).join(', ')}]`);
        }
    }
    return lines.join('\n');
}
async function getGraphstoreBranchesResource(backend, repoName) {
    const repo = await backend.resolveRepo(repoName);
    const handler = await import('./local/graphstore-handler.js');
    let result;
    try {
        result = await handler.handleGraphstoreBranches({ storagePath: repo.storagePath });
    }
    catch (err) {
        return `error: ${err instanceof Error ? err.message : String(err)}`;
    }
    if (result.branches.length === 0) {
        return [
            `repo: "${repo.name}"`,
            'branches: []',
            '# Run `codragraph analyze` to create the first branch.',
        ].join('\n');
    }
    const lines = [
        `repo: "${repo.name}"`,
        `current: "${result.current ?? '(detached)'}"`,
        'branches:',
    ];
    for (const b of result.branches) {
        lines.push(`  - name: "${b.name}"`);
        lines.push(`    head: "${b.head}"`);
        lines.push(`    short: "${b.short}"`);
        lines.push(`    createdAt: "${b.createdAt}"`);
        lines.push(`    isCurrent: ${b.isCurrent}`);
    }
    return lines.join('\n');
}
async function getGraphpackStatusResource(backend, repoName) {
    const repo = await backend.resolveRepo(repoName);
    const { getGraphpackStatus } = await import('../core/graphpack/index.js');
    try {
        const status = await getGraphpackStatus({
            repoPath: repo.repoPath,
            storagePath: repo.storagePath,
        });
        const lines = [
            `repo: "${repo.name}"`,
            `source: "${status.source}"`,
            `lockPresent: ${status.lockPresent}`,
            `compatible: ${status.compatibility.ok}`,
            `localGraphstore: ${status.local.graphstorePresent}`,
            `verifiedChunks: ${status.chunks.verified}`,
            `expectedChunks: ${status.chunks.expected}`,
        ];
        if (status.lock?.graphpack.id)
            lines.push(`graphpack: "${status.lock.graphpack.id}"`);
        if (status.lock?.graphpack.graphstoreSnapshot) {
            lines.push(`snapshot: "${status.lock.graphpack.graphstoreSnapshot}"`);
        }
        if (status.local.headCommit)
            lines.push(`localHead: "${status.local.headCommit}"`);
        if (status.compatibility.reasons.length > 0) {
            lines.push('reasons:');
            for (const reason of status.compatibility.reasons)
                lines.push(`  - ${JSON.stringify(reason)}`);
        }
        if (status.chunks.missing.length > 0) {
            lines.push('missingChunks:');
            for (const chunk of status.chunks.missing)
                lines.push(`  - "${chunk}"`);
        }
        if (status.chunks.mismatched.length > 0) {
            lines.push('mismatchedChunks:');
            for (const chunk of status.chunks.mismatched)
                lines.push(`  - "${chunk}"`);
        }
        return lines.join('\n');
    }
    catch (err) {
        return `error: ${err instanceof Error ? err.message : String(err)}`;
    }
}
async function getGraphpackLockResource(backend, repoName) {
    const repo = await backend.resolveRepo(repoName);
    const { defaultLockPath, readGraphpackLock } = await import('../core/graphpack/index.js');
    const lock = await readGraphpackLock(defaultLockPath(repo.repoPath));
    if (!lock) {
        return JSON.stringify({ error: 'No .codragraph/index.lock.json found', repo: repo.name });
    }
    return JSON.stringify(lock, null, 2);
}
async function getSemanticRelationshipsResource(backend, repoName) {
    const repo = await backend.resolveRepo(repoName);
    const { analyzeSemanticRelationships } = await import('../core/semantic/relationships.js');
    try {
        const report = await analyzeSemanticRelationships({
            storagePath: repo.storagePath,
            limit: 200,
            write: false,
        });
        const lines = [
            `repo: "${repo.name}"`,
            `snapshot: "${report.snapshotId ?? 'unknown'}"`,
            `extractor: "${report.extractorVersion}"`,
            `relationships: ${report.relationships.length}`,
            'summary:',
        ];
        for (const [family, count] of Object.entries(report.summary)) {
            lines.push(`  ${family}: ${count}`);
        }
        lines.push('edges:');
        for (const rel of report.relationships.slice(0, 50)) {
            lines.push(`  - family: "${rel.family}"`);
            lines.push(`    source: ${JSON.stringify(rel.sourceName ?? rel.sourceId)}`);
            lines.push(`    target: ${JSON.stringify(rel.targetName ?? rel.targetId)}`);
            lines.push(`    confidence: ${rel.confidence}`);
            lines.push(`    provenance: "${rel.provenance}"`);
            lines.push(`    extractor: "${rel.extractorVersion}"`);
            if (rel.evidence.filePath)
                lines.push(`    file: "${rel.evidence.filePath}"`);
            if (rel.evidence.startLine !== undefined)
                lines.push(`    startLine: ${rel.evidence.startLine}`);
            lines.push(`    reason: ${JSON.stringify(rel.evidence.reason)}`);
            lines.push(`    rawEdgeType: "${rel.evidence.rawEdgeType}"`);
        }
        return lines.join('\n');
    }
    catch (err) {
        return `error: ${err instanceof Error ? err.message : String(err)}`;
    }
}
async function getRecipesResource(backend, repoName, taskFamily) {
    const repo = await backend.resolveRepo(repoName);
    let result;
    try {
        const harnessModuleId = '@codragraph/harness/mcp/handler';
        const mod = (await import(/* @vite-ignore */ harnessModuleId));
        result = await mod.handleHarnessRecipesList({
            task_family: taskFamily,
            recipe_store: `${repo.storagePath}/recipes`.replace(/\\/g, '/'),
            limit: 100,
        });
    }
    catch (err) {
        return `error: ${err instanceof Error ? err.message : String(err)}`;
    }
    if (result.recipes.length === 0) {
        return [
            `repo: "${repo.name}"`,
            `recipeStoreRoot: "${result.recipeStoreRoot}"`,
            taskFamily ? `taskFamily: "${taskFamily}"` : '',
            'recipes: []',
            '# No recipes yet. Run harness_swarm_run with task_family + snapshot_id to learn the first one.',
        ]
            .filter(Boolean)
            .join('\n');
    }
    const lines = [`repo: "${repo.name}"`, `recipeStoreRoot: "${result.recipeStoreRoot}"`];
    if (taskFamily)
        lines.push(`taskFamily: "${taskFamily}"`);
    lines.push(`count: ${result.recipes.length}`);
    lines.push('recipes:');
    for (const r of result.recipes) {
        lines.push(`  - id: "${r.id}"`);
        lines.push(`    taskFamily: "${r.taskFamily}"`);
        lines.push(`    snapshotId: "${r.snapshotId}"`);
        if (r.requiredSubgraphSignature) {
            lines.push(`    requiredSubgraphSignature: "${r.requiredSubgraphSignature}"`);
        }
        lines.push(`    accuracy: ${r.accuracy}`);
        lines.push(`    tokens: ${r.tokens}`);
        lines.push(`    latencyMs: ${r.latencyMs}`);
        lines.push(`    harness: "${r.harnessName}"`);
        lines.push(`    searchedAt: "${r.searchedAt}"`);
    }
    return lines.join('\n');
}
async function getGraphstoreHeadResource(backend, repoName) {
    const repo = await backend.resolveRepo(repoName);
    const handler = await import('./local/graphstore-handler.js');
    let log, branches;
    try {
        log = await handler.handleGraphstoreLog({ storagePath: repo.storagePath, limit: 1 });
        branches = await handler.handleGraphstoreBranches({ storagePath: repo.storagePath });
    }
    catch (err) {
        return `error: ${err instanceof Error ? err.message : String(err)}`;
    }
    if (log.commits.length === 0) {
        return [`repo: "${repo.name}"`, 'head: null', '# No commits yet.'].join('\n');
    }
    const head = log.commits[0];
    const lines = [
        `repo: "${repo.name}"`,
        `branch: "${branches.current ?? '(detached)'}"`,
        'head:',
        `  id: "${head.id}"`,
        `  short: "${head.short}"`,
        `  snapshot: "${head.snapshot}"`,
        `  ts: "${head.ts}"`,
        `  author: "${head.author}"`,
        `  message: ${JSON.stringify(head.message)}`,
        '',
        '# Pair with: graphstore_log, graphstore_diff, graphstore_blame_symbol',
    ];
    return lines.join('\n');
}
