# tools/core/runners/surface.runner.ts

> 73 lines of code and 18 definitions.

Tree: Coordination tree
Language: typescript
Canonical: https://banes-lab.com/anatomy/coordination#file-coordination-tools-core-runners-surface-runner-ts
Source text: https://banes-lab.com/assets/sources/source.57d8bd00a8d02c5f6ad1b73ca4d376264502df95f386c07f8b518a05bfa34bd0.generated.txt

## Definitions

- `declaredSubjects` (lexical_declaration, line 36, exported)
- `runSurfaceRaise` (lexical_declaration, line 50, exported)
- `BANNER` (lexical_declaration, line 18)
- `LIVE_SECTION_LEAD` (lexical_declaration, line 20)
- `SurfaceRequest` (interface_declaration, line 22, exported)
- `SurfaceOutcome` (interface_declaration, line 31, exported)
- `raisedFrom` (lexical_declaration, line 40, exported)
- `lines` (lexical_declaration, line 41, exported)
- `live` (lexical_declaration, line 42, exported)
- `seeded` (lexical_declaration, line 43, exported)
- `banner` (lexical_declaration, line 44, exported)
- `out` (lexical_declaration, line 45, exported)
- `subject` (lexical_declaration, line 51, exported)
- `templatePath` (lexical_declaration, line 64, exported)
- `target` (lexical_declaration, line 69, exported)
- `template` (lexical_declaration, line 74, exported)
- `carried` (lexical_declaration, line 75, exported)
- `outcome` (lexical_declaration, line 85, exported)

## Uses

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

## Source

```typescript
import {
    SUBJECT_MISSING,
    contractBlockMissing,
    subjectUndeclared,
    surfaceExists,
    surfaceRaised,
    surfaceRehearsed,
    templateFileMissing,
    templateSeedsNothing,
} from "../strings/surface.strings.ts";
import { existsSync, readFileSync } from "node:fs";

import { seededLifetimeOf, surfacePath } from "../../../config/surface.config.ts";
import { resolve } from "node:path";
import { taxonomy } from "../../../config/taxonomy.config.ts";
import { writeRepair } from "../writers/repair.writer.ts";

const BANNER = "═";

const LIVE_SECTION_LEAD = "**A surface raised from this template";

export interface SurfaceRequest {
    readonly repoRoot: string;
    readonly templateSlot: string;
    readonly rootSlot: string;
    readonly subject: string;
    readonly concern: string;
    readonly rehearse: boolean;
}

export interface SurfaceOutcome {
    readonly code: number;
    readonly message: string;
}

export const declaredSubjects = function declaredSubjects(): readonly string[] {
    return taxonomy.subjects;
};

export const raisedFrom = function raisedFrom(template: string): string {
    const lines = template.split("\n");
    const live = lines.findIndex((line) => line.startsWith(LIVE_SECTION_LEAD));
    const seeded = live === -1 ? lines : lines.slice(0, live);
    const banner = seeded.findIndex((line) => line.startsWith(BANNER));
    const out = banner === -1 ? [] : seeded.slice(banner);

    return `${out.join("\n").trimEnd()}\n`;
};

export const runSurfaceRaise = function runSurfaceRaise(request: SurfaceRequest): SurfaceOutcome {
    const subject = request.subject.trim();
    if (subject.length === 0) {
        return { code: 2, message: SUBJECT_MISSING };
    }

    if (!declaredSubjects().includes(subject)) {
        return { code: 2, message: subjectUndeclared(subject, declaredSubjects()) };
    }

    if (seededLifetimeOf(request.templateSlot) === null) {
        return { code: 2, message: templateSeedsNothing(request.templateSlot) };
    }

    const templatePath = resolve(request.repoRoot, surfacePath(request.templateSlot));
    if (!existsSync(templatePath)) {
        return { code: 2, message: templateFileMissing(request.templateSlot) };
    }

    const target = `${surfacePath(request.rootSlot)}/${subject}.${request.concern}.md`;
    if (existsSync(resolve(request.repoRoot, target))) {
        return { code: 2, message: surfaceExists(target) };
    }

    const template = readFileSync(templatePath, "utf8");
    const carried = raisedFrom(template);

    if (!carried.includes(BANNER)) {
        return { code: 2, message: contractBlockMissing(request.templateSlot) };
    }

    if (request.rehearse) {
        return { code: 0, message: surfaceRehearsed(target, request.templateSlot) };
    }

    const outcome = writeRepair({ declared: "whole", repoRoot: request.repoRoot }, target, carried);
    if (!outcome.written) {
        return { code: 2, message: outcome.refusal ?? "" };
    }

    return { code: 0, message: surfaceRaised(target, request.templateSlot) };
};
```
