# tools/core/resolvers/checklist.resolver.ts

> 190 lines of code and 39 definitions.

Tree: Coordination tree
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/coordination#file-coordination-tools-core-resolvers-checklist-resolver-ts
Source text: https://banes-lab.com/assets/sources/source.a7d981704fe038e299c785fa5c0952cfe4d4417256f228c0dd91fe6336be608b.generated.txt

## Definitions

- `isDigit` (lexical_declaration, line 11, exported)
- `resolves` (lexical_declaration, line 227, exported)
- `idAt` (lexical_declaration, line 15)
- `citedIds` (lexical_declaration, line 63, exported)
- `idBreaches` (lexical_declaration, line 195, exported)
- `declaredId` (lexical_declaration, line 49, exported)
- `agentBreaches` (lexical_declaration, line 110, exported)
- `closureBreaches` (lexical_declaration, line 144, exported)
- `IdBreach` (interface_declaration, line 3, exported)
- `parts` (lexical_declaration, line 17)
- `digits` (lexical_declaration, line 18)
- `value` (lexical_declaration, line 19)
- `char` (lexical_declaration, line 22)
- `BINDING_FIELDS` (lexical_declaration, line 83)
- `boundAgent` (lexical_declaration, line 85)
- `marker` (lexical_declaration, line 86)
- `at` (lexical_declaration, line 87)
- `cursor` (lexical_declaration, line 92, exported)
- `after` (lexical_declaration, line 102)
- `letter` (lexical_declaration, line 117, exported)
- `names` (lexical_declaration, line 122, exported)
- `CLOSES_FIELD` (lexical_declaration, line 137)
- `phaseOf` (lexical_declaration, line 139)
- `dot` (lexical_declaration, line 140)
- `closes` (lexical_declaration, line 145, exported)
- `declaredAt` (lexical_declaration, line 146, exported)
- `open` (lexical_declaration, line 147, exported)
- `trimmed` (lexical_declaration, line 150, exported)
- `closurePhase` (lexical_declaration, line 168, exported)
- `later` (lexical_declaration, line 173, exported)
- `phase` (lexical_declaration, line 174, exported)
- `out` (lexical_declaration, line 196, exported)
- `declared` (lexical_declaration, line 197, exported)
- `id` (lexical_declaration, line 200, exported)
- `first` (lexical_declaration, line 205, exported)
- `twice` (lexical_declaration, line 211, exported)
- `index` (lexical_declaration, line 215, exported)
- `line` (lexical_declaration, line 216, exported)
- `cited` (lexical_declaration, line 226, exported)

## Used by

- [tools/core/coordinators/checklist.coordinator.ts](https://banes-lab.com/source/coordination/tools/core/coordinators/checklist.coordinator.ts.md)
- [tools/core/resolvers/reference.resolver.ts](https://banes-lab.com/source/coordination/tools/core/resolvers/reference.resolver.ts.md)
- [tools/core/validators/channel.validator.ts](https://banes-lab.com/source/coordination/tools/core/validators/channel.validator.ts.md)

## Source

```typescript
import { TASK_MARKER } from "../constants/checklist.constants.ts";

export interface IdBreach {
    readonly kind: string;
    readonly line: number;
    readonly id: string;
    readonly actual: string;
    readonly expected: string;
}

export const isDigit = function isDigit(char: string): boolean {
    return char >= "0" && char <= "9";
};

const idAt = function idAt(line: string, from: number): string | null {
    let cursor = from;
    let parts = 0;
    let digits = 0;
    let value = "";

    while (cursor < line.length) {
        const char = line.charAt(cursor);
        if (isDigit(char)) {
            digits += 1;
            value += char;
            cursor += 1;
            continue;
        }
        if (char === "." && digits > 0 && isDigit(line.charAt(cursor + 1))) {
            parts += 1;
            digits = 0;
            value += char;
            cursor += 1;
            continue;
        }
        break;
    }

    if (digits === 0 || parts !== 2) {
        return null;
    }
    if (cursor < line.length && isDigit(line.charAt(cursor))) {
        return null;
    }

    return value;
};

export const declaredId = function declaredId(line: string): string | null {
    const trimmed = line.trimStart();
    if (!trimmed.startsWith(TASK_MARKER)) {
        return null;
    }

    let cursor = TASK_MARKER.length;
    while (cursor < trimmed.length && trimmed.charAt(cursor) === " ") {
        cursor += 1;
    }

    return idAt(trimmed, cursor);
};

export const citedIds = function citedIds(line: string): string[] {
    const out: string[] = [];

    for (let index = 0; index < line.length; index += 1) {
        if (!isDigit(line.charAt(index))) {
            continue;
        }
        if (index > 0 && (isDigit(line.charAt(index - 1)) || line.charAt(index - 1) === ".")) {
            continue;
        }

        const id = idAt(line, index);
        if (id !== null) {
            out.push(id);
        }
    }

    return out;
};

const BINDING_FIELDS = ["verifier", "owner"];

const boundAgent = function boundAgent(line: string, field: string): string | null {
    const marker = `*${field}:*`;
    const at = line.indexOf(marker);
    if (at === -1) {
        return null;
    }

    let cursor = at + marker.length;
    while (cursor < line.length && line.charAt(cursor) === " ") {
        cursor += 1;
    }

    const letter = line.charAt(cursor);
    if (letter < "A" || letter > "Z") {
        return null;
    }

    const after = line.charAt(cursor + 1);
    if (after !== "" && after !== " " && after !== "\r") {
        return null;
    }

    return letter;
};

export const agentBreaches = function agentBreaches(lines: readonly string[], active: ReadonlySet<string>): IdBreach[] {
    const out: IdBreach[] = [];

    for (let index = 0; index < lines.length; index += 1) {
        const line = lines[index] ?? "";

        for (const field of BINDING_FIELDS) {
            const letter = boundAgent(line, field);
            if (letter === null || active.has(letter)) {
                continue;
            }

            const names = `the ${field} names agent ${letter}, and no active record declares it`;
            const resolves = `a ${field} resolves to an agent the board declares ACTIVE`;
            out.push({
                actual: names,
                expected: resolves,
                id: `${field}:${letter}`,
                kind: "danglingBinding",
                line: index + 1,
            });
        }
    }

    return out;
};

const CLOSES_FIELD = "CLOSES:";

const phaseOf = function phaseOf(id: string): number {
    const dot = id.indexOf(".");
    return dot === -1 ? Number.NaN : Number(id.slice(0, dot));
};

export const closureBreaches = function closureBreaches(lines: readonly string[]): IdBreach[] {
    let closes = "";
    let declaredAt = 0;
    const open: { id: string; line: number }[] = [];

    for (let index = 0; index < lines.length; index += 1) {
        const trimmed = (lines[index] ?? "").trim();

        if (trimmed.startsWith(CLOSES_FIELD)) {
            closes = trimmed.slice(CLOSES_FIELD.length).trim();
            declaredAt = index + 1;
            continue;
        }

        const id = declaredId(lines[index] ?? "");
        if (id !== null) {
            open.push({ id, line: index + 1 });
        }
    }

    if (closes.length === 0) {
        return [];
    }

    const closurePhase = phaseOf(closes);
    if (Number.isNaN(closurePhase)) {
        return [];
    }

    const later = open.filter((task) => {
        const phase = phaseOf(task.id);
        return task.id !== closes && !Number.isNaN(phase) && phase > closurePhase;
    });

    if (later.length === 0) {
        return [];
    }

    return [
        {
            actual: `the closure row ${closes} sits in phase ${String(closurePhase)} and these open rows sit later: ${later
                .map((task) => `${task.id} at line ${String(task.line)}`)
                .join(", ")}`,
            expected: `every open row sits at or before the phase of the closure row ${closes}`,
            id: closes,
            kind: "closureBeforeItsDependencies",
            line: declaredAt,
        },
    ];
};

export const idBreaches = function idBreaches(lines: readonly string[]): IdBreach[] {
    const out: IdBreach[] = [];
    const declared = new Map<string, number>();

    for (let index = 0; index < lines.length; index += 1) {
        const id = declaredId(lines[index] ?? "");
        if (id === null) {
            continue;
        }

        const first = declared.get(id);
        if (first === undefined) {
            declared.set(id, index + 1);
            continue;
        }

        const twice = `${id} is declared at line ${String(first)} and again here`;
        out.push({ actual: twice, expected: "one task per id", id, kind: "duplicateId", line: index + 1 });
    }

    for (let index = 0; index < lines.length; index += 1) {
        const line = lines[index] ?? "";
        if (declaredId(line) !== null) {
            continue;
        }

        for (const id of citedIds(line)) {
            if (declared.has(id)) {
                continue;
            }

            const cited = `${id} is cited and no task declares it`;
            const resolves = "a cited id resolves to a declared task";
            out.push({ actual: cited, expected: resolves, id, kind: "danglingReference", line: index + 1 });
        }
    }

    return out;
};
```
