# tools/core/entrypoints/converge.entrypoint.ts

> 124 lines of code and 24 definitions.

Tree: Coordination tree
Language: typescript
Layer: runtime
Canonical: https://banes-lab.com/anatomy/coordination#file-coordination-tools-core-entrypoints-converge-entrypoint-ts
Source text: https://banes-lab.com/assets/sources/source.fdc431affa751a512df43b9fc13f66f2fde2ec5b829b71f31ea48aa6bf29365c.generated.txt

## Definitions

- `main` (lexical_declaration, line 69)
- `REPO_ROOT` (lexical_declaration, line 23)
- `RESTATES` (lexical_declaration, line 25, exported)
- `argumentValue` (lexical_declaration, line 31)
- `at` (lexical_declaration, line 32)
- `value` (lexical_declaration, line 37)
- `venueNames` (lexical_declaration, line 41)
- `root` (lexical_declaration, line 43)
- `out` (lexical_declaration, line 48)
- `resolveTarget` (lexical_declaration, line 59)
- `prefix` (lexical_declaration, line 64)
- `prefixed` (lexical_declaration, line 65)
- `agent` (lexical_declaration, line 75)
- `named` (lexical_declaration, line 76)
- `target` (lexical_declaration, line 83)
- `absolute` (lexical_declaration, line 84)
- `board` (lexical_declaration, line 96)
- `index` (lexical_declaration, line 97)
- `archivePath` (lexical_declaration, line 98)
- `edges` (lexical_declaration, line 100)
- `blocking` (lexical_declaration, line 117)
- `archiveRoot` (lexical_declaration, line 124)
- `destination` (lexical_declaration, line 125)
- `moved` (lexical_declaration, line 142)

## Uses

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

## Source

```typescript
import { AGENDA, BLOCKING_SUFFIX, VENUE_ARCHIVE } from "../constants/blocking.constants.ts";
import {
    CONVERGE_NEEDS_OPERANDS,
    archiveNameTaken,
    archiveRootMissing,
    convergeAbsent,
    convergeHelp,
    convergeNotVenue,
    convergePreview,
    converged,
    orderingsBlock,
} from "../strings/converge.strings.ts";

import { basename, resolve } from "node:path";
import { existsSync, readFileSync, readdirSync } from "node:fs";
import { historyPath, projectRoot, slotText, surfacePath, surfacePrefix } from "../../../config/surface.config.ts";
import { BOARD_PATH } from "../constants/board.constants.ts";
import { NO_FIX_FLAG } from "../constants/path.constants.ts";
import { convergenceEdges } from "../validators/converge.validator.ts";
import { plannedInvariants } from "../runners/venue.runner.ts";
import { runArchiveMove } from "../runners/converge.runner.ts";

const REPO_ROOT = projectRoot();

export const RESTATES: readonly string[] = [
    "a_venue_accumulates_and_the_board_is_swept",
    "a_venue_is_absorbed_before_it_is_archived",
    "an_undecided_half_names_its_receiver",
];

const argumentValue = function argumentValue(flag: string): string | null {
    const at = process.argv.indexOf(flag);
    if (at === -1 || at + 1 >= process.argv.length) {
        return null;
    }

    const value = process.argv[at + 1] ?? "";
    return value.startsWith("--") ? null : value;
};

const venueNames = function venueNames(): string[] {
    const prefix = surfacePrefix();
    const root = resolve(REPO_ROOT, prefix);
    if (!existsSync(root)) {
        return [];
    }

    const out: string[] = [];
    for (const entry of readdirSync(root, { withFileTypes: true })) {
        if (!entry.isFile() || !entry.name.endsWith(BLOCKING_SUFFIX)) {
            continue;
        }
        out.push(prefix.length === 0 ? entry.name : `${prefix}/${entry.name}`);
    }

    return out;
};

const resolveTarget = function resolveTarget(named: string): string {
    if (existsSync(resolve(REPO_ROOT, named))) {
        return named;
    }

    const prefix = surfacePrefix();
    const prefixed = prefix.length === 0 ? named : `${prefix}/${named}`;
    return existsSync(resolve(REPO_ROOT, prefixed)) ? prefixed : named;
};

const main = function main(): void {
    if (process.argv.includes("--help")) {
        process.stdout.write(convergeHelp(slotText("execution", "converge_command")));
        process.exit(0);
    }

    const agent = argumentValue("--agent");
    const named = argumentValue("--file");

    if (agent === null || named === null) {
        process.stdout.write(CONVERGE_NEEDS_OPERANDS);
        process.exit(2);
    }

    const target = resolveTarget(named);
    const absolute = resolve(REPO_ROOT, target);

    if (!absolute.endsWith(BLOCKING_SUFFIX)) {
        process.stdout.write(convergeNotVenue(target));
        process.exit(2);
    }

    if (!existsSync(absolute)) {
        process.stdout.write(convergeAbsent(target));
        process.exit(2);
    }

    const board = resolve(REPO_ROOT, BOARD_PATH);
    const index = resolve(REPO_ROOT, surfacePath("agent_index"));
    const archivePath = resolve(REPO_ROOT, historyPath());

    const edges = convergenceEdges(
        REPO_ROOT,
        target,
        readFileSync(absolute, "utf8"),
        existsSync(board) ? readFileSync(board, "utf8") : "",
        existsSync(index) ? readFileSync(index, "utf8") : "",
        existsSync(archivePath) ? readFileSync(archivePath, "utf8") : "",
        venueNames(),
        plannedInvariants(
            existsSync(resolve(REPO_ROOT, AGENDA)) ? readFileSync(resolve(REPO_ROOT, AGENDA), "utf8") : "",
        ),
    );

    for (const edge of edges) {
        process.stdout.write(`  ${edge.holds ? "holds  " : "BLOCKS "} ${edge.edge}\n           ${edge.detail}\n`);
    }

    const blocking = edges.filter((edge) => !edge.holds);

    if (blocking.length > 0) {
        process.stdout.write(orderingsBlock(blocking.length, edges.length, target));
        process.exit(2);
    }

    const archiveRoot = resolve(REPO_ROOT, VENUE_ARCHIVE);
    const destination = resolve(archiveRoot, basename(target));

    if (!existsSync(archiveRoot)) {
        process.stdout.write(archiveRootMissing(target));
        process.exit(2);
    }

    if (existsSync(destination)) {
        process.stdout.write(archiveNameTaken(basename(target), target));
        process.exit(2);
    }

    if (process.argv.includes(NO_FIX_FLAG)) {
        process.stdout.write(convergePreview(target, agent));
        process.exit(0);
    }

    const moved = runArchiveMove(absolute, destination, target);
    if (moved.code !== 0) {
        process.stdout.write(moved.message);
        process.exit(moved.code);
    }

    process.stdout.write(converged(target, agent));
    process.exit(0);
};

main();
```
