# tools/core/validators/claim.validator.ts

> 62 lines of code and 17 definitions.

Tree: Coordination tree
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/coordination#file-coordination-tools-core-validators-claim-validator-ts
Source text: https://banes-lab.com/assets/sources/source.26bcf6ea309be7c9a56c0a8f89f52001fcc69a02873793db3235f3d3e59cc4a5.generated.txt

## Definitions

- `citedAbsolute` (lexical_declaration, line 7, exported)
- `contendedCitations` (lexical_declaration, line 46, exported)
- `absolute` (lexical_declaration, line 9, exported)
- `Contention` (interface_declaration, line 18, exported)
- `FanIn` (interface_declaration, line 25, exported)
- `OPEN_MARKER` (lexical_declaration, line 31)
- `MARKER_SEPARATOR` (lexical_declaration, line 33)
- `markerKey` (lexical_declaration, line 35, exported)
- `at` (lexical_declaration, line 36, exported)
- `rest` (lexical_declaration, line 41, exported)
- `stop` (lexical_declaration, line 42, exported)
- `contended` (lexical_declaration, line 50, exported)
- `counts` (lexical_declaration, line 51, exported)
- `key` (lexical_declaration, line 54, exported)
- `held` (lexical_declaration, line 60, exported)
- `now` (lexical_declaration, line 63, exported)
- `fanIn` (lexical_declaration, line 73, exported)

## Uses

- [config/surface.config.ts](https://banes-lab.com/source/coordination/config/surface.config.ts.md)
- [tools/core/formatters/board.formatter.ts](https://banes-lab.com/source/coordination/tools/core/formatters/board.formatter.ts.md)

## Source

```typescript
import { existsSync } from "node:fs";
import { resolve } from "node:path";

import { stampedCitations } from "../formatters/board.formatter.ts";
import { surfacePrefix } from "../../../config/surface.config.ts";

export const citedAbsolute = function citedAbsolute(repoRoot: string, cited: string): string | null {
    for (const root of [resolve(repoRoot, surfacePrefix()), repoRoot]) {
        const absolute = resolve(root, cited);
        if (existsSync(absolute)) {
            return absolute;
        }
    }

    return null;
};

export interface Contention {
    readonly key: string;
    readonly cited: string;
    readonly stamped: number;
    readonly moved: number;
}

export interface FanIn {
    readonly cited: string;
    readonly citations: number;
    readonly contended: number;
}

const OPEN_MARKER = "┌─── AGENT ";

const MARKER_SEPARATOR = " ─── ";

export const markerKey = function markerKey(line: string): string {
    const at = line.indexOf(OPEN_MARKER);
    if (at === -1) {
        return "";
    }

    const rest = line.slice(at + OPEN_MARKER.length);
    const stop = rest.indexOf(MARKER_SEPARATOR);
    return stop === -1 ? "" : rest.slice(0, stop).trim();
};

export const contendedCitations = function contendedCitations(
    source: string,
    modified: (path: string) => number | null,
): { contended: Contention[]; fanIn: FanIn[] } {
    const contended: Contention[] = [];
    const counts = new Map<string, { citations: number; contended: number }>();

    for (const line of source.split("\n")) {
        const key = markerKey(line);
        if (key.length === 0) {
            continue;
        }

        for (const citation of stampedCitations(line)) {
            const held = counts.get(citation.path) ?? { citations: 0, contended: 0 };
            held.citations += 1;

            const now = modified(citation.path);
            if (now !== null && now > citation.at) {
                held.contended += 1;
                contended.push({ cited: citation.path, key, moved: now, stamped: citation.at });
            }

            counts.set(citation.path, held);
        }
    }

    const fanIn = [...counts.entries()]
        .map(([cited, held]) => ({ citations: held.citations, cited, contended: held.contended }))
        .sort((first, second) => (second.citations === first.citations ? 0 : second.citations - first.citations));

    return { contended, fanIn };
};
```
