tools/core/strings/board.strings.ts

tools/core/strings/board.strings.ts is a file in Coordination Surface. 403 lines of code and 84 definitions.

export const recordContended = function recordContended(
    target: string,
    agent: string,
    changes: readonly string[],
): string {
    return (
        `CONTENDED  ${target}: the record of ${agent} changed between the read and the write, so the operation was ` +
        `not repeated. Read the changes below, then run the command again against the current record.\n${changes.join(
            "",
        )}`
    );
};

export const barrierHeld = function barrierHeld(parked: number, peers: number): string {
    return (
        `HELD  ${String(parked)} of ${String(peers)} peers are waiting, so you are the only seat able to write. A ` +
        "peer counts as able to write while it is waiting on the board or has touched a coordination surface within " +
        "the configured activity window.\n"
    );
};

export const barrierOpen = function barrierOpen(parked: number, peers: number): string {
    return (
        `OPEN  ${String(parked)} of ${String(peers)} peers are waiting. A peer that is not waiting can write at the ` +
        "same time, so an exclusive write is not held.\n"
    );
};

export const kindEcho = function kindEcho(kind: string, judgment: boolean): string {
    const closure = judgment
        ? "it asks for a reading, so an addressee closes it by acknowledging it, with no reference"
        : "it asks for something that can exist, so it closes with a reference to where that thing landed";
    return (
        `  kind:${kind} — ${closure}. If that does not describe what you wrote, change the kind on the item's ` +
        "marker.\n"
    );
};

export const surfaceAbsent = function surfaceAbsent(target: string): string {
    return `ABSENT  ${target} does not exist.\n`;
};

export const noOwnRecord = function noOwnRecord(agent: string): string {
    return (
        `REFUSED  There is no single record for ${agent} on this surface (one opening marker and one closing ` +
        "marker). Add your record first, or correct a duplicated marker.\n"
    );
};

export const itemFieldMissing = function itemFieldMissing(agent: string, field: string, target: string): string {
    return (
        `REFUSED  The record of ${agent} on ${target} has no ${field} field to add the item to. A board record ` +
        "holds items in its Flags field and a venue record holds positions, so the field comes from the surface's " +
        "own template.\n"
    );
};

export const positionOnBoard = function positionOnBoard(labels: readonly string[]): string {
    return (
        `REFUSED  This item has the structure of a venue position (${labels.join(", ")}), and its target is the ` +
        "board. The board is cleared as items are handled, so an argument written there is lost. Post it to the " +
        "venue instead with `--file <venue>`.\n"
    );
};

export const positionUnsigned = function positionUnsigned(signedLead: string): string {
    return (
        `REFUSED  This position has no ${signedLead} line. A position ends with its author's signature, so a ` +
        "missing signature usually means the body was cut short on the way in, often at a blank line in a " +
        "command-line argument. If the body is complete, sign it; if it was cut, pass it from a file or on " +
        "standard input instead.\n"
    );
};

export const itemAdded = function itemAdded(key: string, target: string): string {
    return `ITEM  ${key} was added to ${target}.\n`;
};

export const fieldUndeclared = function fieldUndeclared(
    agent: string,
    field: string,
    target: string,
    declared: readonly string[],
): string {
    return (
        `REFUSED  The record of ${agent} on ${target} has no ${field} field. This command rewrites a field the ` +
        "record already has and never adds one, because the fields come from the surface's template. Fields in " +
        `this record: ${declared.join(", ")}\n`
    );
};

export const fieldUnchanged = function fieldUnchanged(field: string, target: string): string {
    return `CLEAR  ${field} already says that on ${target}. Nothing was written.\n`;
};

export const fieldRewritten = function fieldRewritten(field: string, agent: string, target: string): string {
    return `FIELD  ${field} in the record of ${agent} on ${target} now holds the new text.\n`;
};

export const nothingToCompress = function nothingToCompress(target: string): string {
    return `ABSENT  ${target} does not exist, so there is nothing to compress.\n`;
};

export const COMPRESS_NEEDS_AGENT =
    "REFUSED  `--compress` needs `--agent <LETTER>`. It deletes every field labeled with the marker, so without an " +
    "agent it would reach into other seats' records.\n";

export const itemFenceMalformed = function itemFenceMalformed(marker: string): string {
    return (
        `REFUSED  Item ${marker} does not have exactly one opening and one closing marker, so the tool cannot tell ` +
        "which lines to remove. Correct the markers by hand.\n"
    );
};

export const surfaceContended = function surfaceContended(target: string): string {
    return `CONTENDED  ${target} changed between the read and the write. Nothing was removed; run the command again.\n`;
};

export const itemDropped = function itemDropped(marker: string, bytes: number, heal: boolean): string {
    return heal
        ? `DROPPED  Item ${marker} was removed (${String(bytes)} bytes).\n`
        : `PREVIEW  Item ${marker} would be removed (${String(bytes)} bytes). Nothing was written.\n`;
};

export const compressionNoRecord = function compressionNoRecord(agent: string): string {
    return (
        `REFUSED  There is no single record for ${agent} on this surface, so compression has no span of yours to ` +
        "work on.\n"
    );
};

export const noMarkedField = function noMarkedField(target: string): string {
    return `CLEAR  No field in ${target} carries that marker. Nothing was written.\n`;
};

export const fieldsCompressed = function fieldsCompressed(
    target: string,
    fields: number,
    bytes: number,
    heal: boolean,
): string {
    return heal
        ? `COMPRESSED  ${String(fields)} field(s) in ${target} were removed (${String(bytes)} bytes).\n`
        : `PREVIEW  ${String(fields)} field(s) in ${target} would be removed (${String(bytes)} bytes). Nothing was written.\n`;
};

export const fieldEmptied = function fieldEmptied(field: string, target: string, bytes: number, heal: boolean): string {
    return heal
        ? `COMPRESSED  ${field} in ${target} now holds \`—\` (${String(bytes)} bytes removed).\n`
        : `PREVIEW  ${field} in ${target} would hold \`—\` (${String(bytes)} bytes removed). Nothing was written.\n`;
};

export const closureSettled = function closureSettled(closes: string, target: string): string {
    return (
        `SETTLED  ${closes} is no longer on ${target}, so there is nothing to close. This call only saw that the ` +
        "item is gone; it cannot say who removed it.\n"
    );
};

export const readersOutstanding = function readersOutstanding(closes: string, held: readonly string[]): string {
    return (
        `REFUSED  ${closes} has a read list, and ${held.join(", ")} has not marked it yet. Closing it now would ` +
        "remove it before every named seat has read it. Mark your own letter with `--mark`; the item is removed " +
        "when its last active reader marks it.\n"
    );
};

export const emptyExtractionCheck = function emptyExtractionCheck(filed: string): string {
    return (
        "CHECK  Closing with no extraction states that none of the filed classes covers this item. Look through " +
        `the headings first, open the one that fits, and confirm its population matches what the item said.\n${filed}`
    );
};

export const dischargeNotVenue = function dischargeNotVenue(target: string): string {
    return (
        `REFUSED  ${target} is not a venue. Directives live in a venue's DIRECTIVES section, so only a venue has ` +
        "one to discharge.\n"
    );
};

export const DISCHARGE_NEEDS_REF =
    "REFUSED  A discharge needs `--ref changelog:<heading>`, naming the history entry the directive was " +
    "extracted to. Without it, removing the directive would lose its only record.\n";

export const dischargeRefUntyped = function dischargeRefUntyped(ref: string): string {
    return (
        `REFUSED  ${ref} is not a reference this command reads. Write it as \`changelog:<heading>\`, where the ` +
        "heading is the history entry the directive was extracted to.\n"
    );
};

export const dischargeRefUnresolved = function dischargeRefUnresolved(ref: string): string {
    return (
        `REFUSED  ${ref} does not resolve: the history file has no such heading. Extract the directive first, then ` +
        "discharge it. The check confirms that the heading exists, not that it says the same thing.\n"
    );
};

export const dischargeSettled = function dischargeSettled(target: string, clause: string): string {
    return `SETTLED  No live directive on ${target} contains "${clause}". Nothing was written.\n`;
};

export const dischargeContended = function dischargeContended(target: string): string {
    return (
        `CONTENDED  ${target} changed between the read and the write, so the directive was not removed. Run the ` +
        "command again.\n"
    );
};

export const discharged = function discharged(clause: string, target: string, ref: string): string {
    return (
        `DISCHARGED  The directive containing "${clause}" was removed from ${target}. Its content is kept at ` +
        `${ref}. A directive is removed once it has been carried out, rather than archived with the venue.\n`
    );
};

export const compressSettled = function compressSettled(marker: string, target: string): string {
    return `SETTLED  ${marker} is no longer on ${target}. Nothing was removed.\n`;
};

export const claimNoRecord = function claimNoRecord(board: string, agent: string): string {
    return (
        `YOUR CLAIM  ${board} has no record for ${agent}, so peers cannot address you or close an item you ` +
        "handled.\n"
    );
};

export const claimFieldAbsent = function claimFieldAbsent(field: string): string {
    return `  ${field}: absent (the board has no ${field} field for this seat)`;
};

export const claimEcho = function claimEcho(board: string, lines: readonly string[]): string {
    return (
        `YOUR CLAIM ON ${board}, shown because you just wrote elsewhere:\n${lines.join("\n")}\n` +
        "  Every seat reads the board each round, so correct any field that describes work you have moved past.\n"
    );
};

export const awaitingMark = function awaitingMark(items: readonly string[]): string {
    return `  Awaiting your mark: ${items.join(", ")}`;
};

export const closableByYou = function closableByYou(items: readonly string[]): string {
    return `  You can close now: ${items.join(", ")}`;
};

export const dischargeEcho = function dischargeEcho(lines: readonly string[]): string {
    return (
        "ITEMS YOU CAN DISCHARGE, from the same check the close command runs:\n" +
        `${lines.join("\n")}\n` +
        "  An item addressed to you waits on your mark or your close; its author cannot remove it.\n"
    );
};

export const venueWritingTo = function venueWritingTo(venue: string): string {
    return `  ${venue} (the surface you are writing to)`;
};

export const venueRosterRow = function venueRosterRow(venue: string, unmarked: boolean): string {
    return `  ${venue} (${unmarked ? "you have not marked it as read" : "you have marked it as read"})`;
};

export const openVenuesEcho = function openVenuesEcho(lines: readonly string[]): string {
    return (
        "OPEN VENUES, listed from the venue folder and each venue's roster:\n" +
        `${lines.join("\n")}\n` +
        "  Arguments go to a venue, not to the board.\n"
    );
};

export const venueNoRecord = function venueNoRecord(target: string, agent: string): string {
    return (
        `YOUR RECORD ON ${target}  There is no record for ${agent}, so this venue has no Needs, Durable or ` +
        "signature from you, and it cannot converge without them.\n"
    );
};

export const venueFieldAbsent = function venueFieldAbsent(field: string): string {
    return `  ${field}: absent (the record has no ${field} field)`;
};

export const venueFieldEmpty = function venueFieldEmpty(field: string): string {
    return `  ${field}: empty (write \`—\` if there is nothing to state)`;
};

export const venueRecordEcho = function venueRecordEcho(target: string, lines: readonly string[]): string {
    return (
        `YOUR RECORD ON ${target}, shown because these fields decide when the venue can close:\n${lines.join("\n")}\n` +
        "  Convergence reads them for every active seat, so correct any that describe work you have moved past.\n"
    );
};

export const venueTemplateUnreadable = function venueTemplateUnreadable(template: string): string {
    return `  The venue record fields cannot be listed: ${template} does not exist.\n\n`;
};

export const venueTemplateFieldless = function venueTemplateFieldless(template: string): string {
    return `  The venue template at ${template} declares no record fields, so a venue raised from it accepts no item.\n\n`;
};

export const venueFieldList = function venueFieldList(template: string, fields: readonly string[]): string {
    return `  Venue record fields, read from ${template}: ${fields.join(", ")}\n\n`;
};

export const fixedTarget = function fixedTarget(form: string, surface: string): string {
    return (
        `REFUSED  ${form} always writes ${surface}, so \`--file\` does not apply to it. Remove \`--file\`, or use a ` +
        "command that writes the surface you named.\n"
    );
};

export const forgedBoundary = function forgedBoundary(flag: string, count: number, named: string): string {
    return (
        `REFUSED  ${flag} contains ${String(count)} line(s) that start a record or item marker: ${named}. A body ` +
        "cannot contain a marker, because the markers decide which lines belong to which record. To mention a " +
        "marker, write it inside a sentence.\n"
    );
};

export const stdinEmpty = function stdinEmpty(flag: string, operand: string): string {
    return `REFUSED  \`${flag} ${operand}\` reads the body from standard input, and nothing arrived there.\n`;
};

export const bodyInline = function bodyInline(
    inlineFlag: string,
    fileFlag: string,
    operand: string,
    tokens: number,
): string {
    return (
        `REFUSED  A body is not accepted as an argument. Pass \`${inlineFlag} ${operand}\` and pipe the text in, or ` +
        `pass \`${fileFlag} <path>\`. The shell changes an argument before the tool sees it: a quote ends it, and ` +
        "backticks and `$` are substituted, so the text would be recorded with parts missing. Field values can still " +
        `be passed inline. Tokens received after ${inlineFlag}: ${String(tokens)}\n`
    );
};

export const bodyFileMissing = function bodyFileMissing(fileFlag: string, path: string): string {
    return `REFUSED  ${fileFlag} names ${path}, which does not exist.\n`;
};

export const argumentsUnknown = function argumentsUnknown(
    unknown: readonly string[],
    known: readonly string[],
): string {
    return (
        `REFUSED  ${unknown.join(", ")} ${unknown.length > 1 ? "are not arguments" : "is not an argument"} this ` +
        `tool reads, so nothing was run. The arguments it reads: ${known.join(" ")}\n`
    );
};

export const exclusiveCombined = function exclusiveCombined(exclusive: readonly string[], others: string): string {
    return (
        `REFUSED  ${exclusive.join(" and ")} cannot be combined with ${others} in one call, because the tool would ` +
        "run the first and drop the rest. Nothing was written; run them as separate commands.\n"
    );
};

export const ANOTHER_EXCLUSIVE = "another command that runs on its own";

export const REHEARSED =
    "REHEARSED  Every argument of every requested command was checked, and nothing was written. A command's own " +
    "refusals run only when it acts, so this check does not show them.\n";

export const AGENDA_NEEDS_ESTABLISHES =
    "REFUSED  `--agenda` needs `--establishes` or `--establishes-file`, saying what the venue must establish. The " +
    "row's state is not an argument; the tool derives it from the venue folders on every run.\n";

export const APPEND_NEEDS_LEAD =
    "REFUSED  `--append` needs `--lead`, naming which clause of the entry to extend, and `--body` or `--body-file` " +
    "with the text to add.\n";

export const EXTRACT_NEEDS_BODY =
    "REFUSED  `--extract` needs `--body` or `--body-file` with the entry text. A heading without a body gives a " +
    "closure a reference that points to nothing.\n";

export const FIXTURE_NEEDS_BODY =
    "REFUSED  `--fixture` needs `--body` or `--body-file` with two samples: one that fires the rule, with its path " +
    "and text, and one the rule accepts. The tool places the entry; the samples come from you.\n";

export const MEMBER_NEEDS_BODY =
    "REFUSED  `--member` needs `--body` or `--body-file` with the member text. A heading without a body gives a " +
    "citation a target that states nothing.\n";

export const DEFER_NEEDS_RECEIVER =
    "REFUSED  `--defer` needs `--to`, naming who receives the question: a venue, an active seat or a planned " +
    "agenda row.\n";

export const kindRequired = function kindRequired(kinds: readonly string[]): string {
    return (
        `--kind must be one of ${kinds.join(" or ")}. The kind decides how the item closes: an artifact item closes ` +
        "with a reference to what was made, and a judgment item closes when an addressee acknowledges it"
    );
};

export const FIELD_NEEDS_VALUE =
    "--field needs --value with the new text. To state that a field has nothing, write `—` rather than leaving it " +
    "empty";

export const operandsMissing = function operandsMissing(refusals: readonly string[]): string {
    return (
        `REFUSED  ${refusals.join("\nREFUSED  ")}\n` +
        "Every argument is checked before anything is written, so nothing was written.\n"
    );
};

export const twinAdmitted = function twinAdmitted(closes: string, twin: string): string {
    return `ADMITTED  ${closes} is an exact copy of ${twin} in the same record, so removing it loses nothing.\n`;
};

export const venueNoRemoval = function venueNoRemoval(target: string): string {
    return (
        `REFUSED  Nothing is removed from ${target} while it is open. A venue keeps every position until it ` +
        "converges, then moves whole to the archive.\n"
    );
};

export const venueNoSweep = function venueNoSweep(target: string): string {
    return `HELD  ${target} is a venue, so it is not swept. Its positions stay until the venue converges.\n`;
};

export const POST_LANDED =
    "HELD  The item was posted, and the removal in the same call was refused. The refusal is shown above.\n";

export const watchAbsent = function watchAbsent(target: string): string {
    return `ABSENT  ${target} does not exist, so there is nothing to wait on.\n`;
};

export const watchRemoved = function watchRemoved(target: string): string {
    return `REMOVED  ${target} was deleted during the wait.\n`;
};

export const watchChanged = function watchChanged(target: string, seconds: number): string {
    return `CHANGED  ${target} was updated after ${String(seconds)}s.\n`;
};

export const firstSnapshot = function firstSnapshot(agent: string): string {
    return `SNAPSHOT  First read for ${agent}. The next call reports everything that changed since.\n`;
};

export const surfaceUnchanged = function surfaceUnchanged(target: string, agent: string): string {
    return `UNCHANGED  Nothing on ${target} changed since ${agent} last looked.\n`;
};

export const changedSince = function changedSince(agent: string, count: number): string {
    return `SINCE ${agent} LAST LOOKED  ${String(count)} changed line(s)\n`;
};

export const degradedHead = function degradedHead(agent: string, count: number, size: number, target: string): string {
    return (
        `SINCE ${agent} LAST LOOKED  ${String(count)} changed line(s), ${String(size)} characters, which is more ` +
        `than one read holds. Each changed item is listed by its marker below; read ${target} for the full text.\n`
    );
};

export const degradedInsideRecords = function degradedInsideRecords(target: string): string {
    return `  No item opened or closed; the changes are inside existing records. Read ${target} directly.\n`;
};

export const waitSolitary = function waitSolitary(able: number, waiting: number): string {
    return (
        "BLOCKED  No other seat is able to write, so a wait would never end. Carry on with your own work. " +
        `${String(able)} able to write, ${String(waiting)} waiting.\n`
    );
};

export const waitAllParked = function waitAllParked(able: number, waiting: number): string {
    return (
        "BLOCKED  Every other active seat is waiting for an update, so a wait now would leave every seat waiting. " +
        "Read what changed and post your response before you wait. " +
        `${String(waiting)} of ${String(able)} able to write are waiting.\n`
    );
};

export const watching = function watching(target: string, seconds: number, waiting: number, able: number): string {
    return (
        `WATCHING  ${target} for up to ${String(seconds)}s (${String(waiting)} of ${String(able)} able to write ` +
        "are waiting).\n"
    );
};

export const watchQuiet = function watchQuiet(target: string): string {
    return `QUIET  No other seat wrote to ${target} before the wait ended.\n`;
};