tools/core/validators/converge.validator.ts

tools/core/validators/converge.validator.ts is a file in Coordination Surface. 174 lines of code and 42 definitions.

import {
    CHECK_DIRECTIVES,
    CHECK_DURABLE,
    CHECK_INHERITANCE,
    CHECK_NEEDS,
    CHECK_SIGNATURES,
    CHECK_SUCCESSOR,
    DIRECTIVES_HOLD,
    INHERITANCE_HOLDS,
    NOBODY_TAKING_PART,
    NO_SUCCESSOR,
    SIGNATURES_HOLD,
    deferredUnanswered,
    deferredUndeclared,
    durableHold,
    durableUndeclared,
    durableUnresolved,
    needsHold,
    needsMissing,
    successorArrived,
    successorMissing,
    successorScheduled,
    unarrivedClauses,
    undischarged,
    unoriginated as unoriginatedMessage,
    unsigned,
} from "../strings/converge.strings.ts";
import {
    DEFERRED_SECTION,
    SIGN_OFF_ABSENT,
    clauseLines,
    declaredHeading,
    headingIsWhole,
} from "../analyzers/converge.analyzer.ts";
import type { Edge, SuccessorView } from "../types/converge.types.ts";
import { signOffLines, venueRecords } from "../readers/venue.reader.ts";
import { successorView, unoriginatedInheritance } from "../resolvers/venue.resolver.ts";
import { absorptionEdge } from "../resolvers/converge.resolver.ts";
import { activeSeats } from "../analyzers/board.analyzer.ts";

const NEEDS_FIELD = "Needs";

const DURABLE_FIELD = "Durable";

const INHERITED_HEADING = "INHERITED";

const DIRECTIVES_HEADING = "DIRECTIVES";

export const CONVERGENCE_STEPS = [
    "needs",
    "signatures",
    "durable",
    "directives",
    "absorption",
    "inheritance",
    "successor",
] as const;

export const ARCHIVE_STEP = "archive";

export const DESTRUCTIVE_STEPS: readonly string[] = [...CONVERGENCE_STEPS, ARCHIVE_STEP];

type Records = ReadonlyMap<string, ReadonlyMap<string, string>>;

const fieldOf = function fieldOf(records: Records, letter: string, field: string): string {
    return (records.get(letter)?.get(field) ?? "").trim();
};

const needsEdge = function needsEdge(letters: readonly string[], uncovened: readonly string[], records: Records): Edge {
    const unstated = letters.filter((letter) => fieldOf(records, letter, NEEDS_FIELD).length === 0);
    const vacuous = letters.length === 0;
    const holds = !vacuous && unstated.length === 0;
    const failing = vacuous ? NOBODY_TAKING_PART : needsMissing(unstated);
    return { detail: holds ? needsHold(letters.length, uncovened) : failing, edge: CHECK_NEEDS, holds, step: "needs" };
};

const signaturesEdge = function signaturesEdge(letters: readonly string[], venue: string): Edge {
    const signatures = signOffLines(venue);
    const outstanding = letters.filter((letter) => {
        const signed = (signatures.get(letter) ?? "").trim();
        return signed.length === 0 || signed === SIGN_OFF_ABSENT;
    });
    const vacuous = letters.length === 0;
    const holds = !vacuous && outstanding.length === 0;
    const failing = vacuous ? NOBODY_TAKING_PART : unsigned(outstanding);
    return { detail: holds ? SIGNATURES_HOLD : failing, edge: CHECK_SIGNATURES, holds, step: "signatures" };
};

const durableDeclared = function durableDeclared(records: Records, letter: string): boolean {
    return records.get(letter)?.has(DURABLE_FIELD) === true && fieldOf(records, letter, DURABLE_FIELD).length > 0;
};

const durableFailure = function durableFailure(undeclared: readonly string[], unresolved: readonly string[]): string {
    return [
        undeclared.length === 0 ? "" : durableUndeclared(undeclared),
        unresolved.length === 0 ? "" : durableUnresolved(unresolved),
    ]
        .filter((part) => part.length > 0)
        .join("; ");
};

const durableEdge = function durableEdge(letters: readonly string[], records: Records, archive: string): Edge {
    const undeclared = letters.filter((letter) => !durableDeclared(records, letter));
    const stated = letters.filter((letter) => durableDeclared(records, letter));
    const headingOf = (letter: string): string => declaredHeading(fieldOf(records, letter, DURABLE_FIELD));

    const headings = stated.map((letter) =>
        headingOf(letter) === SIGN_OFF_ABSENT ? `${letter} → none` : headingOf(letter),
    );
    const unresolved = stated
        .filter((letter) => headingOf(letter) !== SIGN_OFF_ABSENT)
        .filter((letter) => !headingIsWhole(headingOf(letter)) || !archive.includes(headingOf(letter)))
        .map((letter) => `${letter} → ${headingOf(letter)}`);

    const vacuous = letters.length === 0;
    const holds = !vacuous && undeclared.length === 0 && unresolved.length === 0;
    const failing = vacuous ? NOBODY_TAKING_PART : durableFailure(undeclared, unresolved);
    return { detail: holds ? durableHold(headings) : failing, edge: CHECK_DURABLE, holds, step: "durable" };
};

const inheritsIntoSuccessor = function inheritsIntoSuccessor(view: SuccessorView): boolean {
    return view.successor.length > 0 && view.successorText.includes(INHERITED_HEADING) && view.unarrived.length === 0;
};

const successorHolds = function successorHolds(view: SuccessorView): boolean {
    return view.deferred.declared && view.deferred.answered && (view.scheduled || inheritsIntoSuccessor(view));
};

const successorDetail = function successorDetail(view: SuccessorView, holds: boolean): string {
    if (holds && view.scheduled && view.successor.length === 0) {
        return successorScheduled(view.declared);
    }
    if (holds) {
        return successorArrived(view.successor, view.elsewhere, view.deferred.clauses);
    }
    if (!view.deferred.declared) {
        return deferredUndeclared(DEFERRED_SECTION);
    }
    if (!view.deferred.answered) {
        return deferredUnanswered(DEFERRED_SECTION);
    }
    const inherited = view.successor.length > 0 && view.successorText.includes(INHERITED_HEADING);
    return inherited ? unarrivedClauses(view.unarrived) : successorMissing(INHERITED_HEADING, view.declared);
};

const successorEdge = function successorEdge(view: SuccessorView): Edge {
    const holds = successorHolds(view);
    return { detail: successorDetail(view, holds), edge: CHECK_SUCCESSOR, holds, step: "successor" };
};

const directivesEdge = function directivesEdge(venue: string): Edge {
    const live = clauseLines(venue, DIRECTIVES_HEADING).map((entry) => entry.clause);
    const holds = live.length === 0;
    return { detail: holds ? DIRECTIVES_HOLD : undischarged(live), edge: CHECK_DIRECTIVES, holds, step: "directives" };
};

const inheritanceDetail = function inheritanceDetail(successor: string, unoriginated: readonly string[]): string {
    if (successor.length === 0) {
        return NO_SUCCESSOR;
    }
    return unoriginated.length === 0 ? INHERITANCE_HOLDS : unoriginatedMessage(unoriginated);
};

const inheritanceEdge = function inheritanceEdge(view: SuccessorView, venue: string): Edge {
    const unoriginated = unoriginatedInheritance(venue, view.successorText);
    return {
        detail: inheritanceDetail(view.successor, unoriginated),
        edge: CHECK_INHERITANCE,
        holds: view.successor.length === 0 || unoriginated.length === 0,
        step: "inheritance",
    };
};

export const convergenceEdges = function convergenceEdges(
    repoRoot: string,
    target: string,
    venue: string,
    board: string,
    index: string,
    archive: string,
    siblings: readonly string[],
    plannedInvariants: readonly string[] = [],
): Edge[] {
    const records = venueRecords(venue);
    const convened = activeSeats(board, index);
    const letters = convened.filter((letter) => records.has(letter));
    const uncovened = convened.filter((letter) => !records.has(letter));
    const view = successorView(repoRoot, target, venue, siblings, plannedInvariants);

    return [
        needsEdge(letters, uncovened, records),
        signaturesEdge(letters, venue),
        durableEdge(letters, records, archive),
        successorEdge(view),
        directivesEdge(venue),
        absorptionEdge(repoRoot, target),
        inheritanceEdge(view, venue),
    ];
};