Skip to content

operation_transcript.kt

src/jvmMain/kotlin/afield/tools/automation/operation_transcript.kt · 2798 lines · cited by What a document is on disk

package and imports — 101 lines, from line 1
package afield.tools.automation

import afield.app.diagnostics.named
import afield.app.protocol.Completion
import afield.app.protocol.handlers
import afield.data.table.div
import afield.data.table.minus
import afield.data.table.plus
import afield.data.table.rem
import afield.data.table.times
import afield.document.graph.nested
import afield.document.workspace.metadata
import afield.runtime.execution.plus
import afield.runtime.lifecycle.end
import afield.runtime.lifecycle.plus
import afield.runtime.lifecycle.rem
import afield.runtime.lifecycle.then
import afield.tools.docs.screenshot
import afield.ui.notation.Mark
import afield.ui.notation.string
import afield.ui.notation.with
import afield.ui.output.transcript
import afield.ui.output.tree

import afield.app.notifications.notify
import afield.app.protocol.AgentBoxScreenshot
import afield.app.protocol.AgentWindowScreenshot
import afield.app.protocol.ClearEditorOutputs
import afield.app.protocol.Execute
import afield.app.protocol.ExecutionReport
import afield.app.protocol.MacroOutputLine
import afield.app.protocol.Message
import afield.app.protocol.Notify
import afield.app.protocol.Rect
import afield.app.protocol.TranscriptEntry
import afield.app.protocol._send
import afield.app.protocol.computeIfAbsent
import afield.app.protocol.payload
import afield.app.protocol.send
import afield.app.server.PLAYWRIGHT_VIEWPORT_HEIGHT
import afield.app.server.PLAYWRIGHT_VIEWPORT_WIDTH
import afield.app.server.Server
import afield.app.server.SessionInformation
import afield.app.server.ReadOnlyDocuments
import afield.app.server.documents
import afield.app.server.ensurePlaywrightForSessionIfNeeded
import afield.app.server.globalPlaywriteContext
import afield.app.server.playwrightDispatcher
import afield.app.server.thisSessionInfo
import afield.audio.synth.*
import afield.data.table.get
import afield.document.graph.Box
import afield.document.graph.METAROOT_ID
import afield.document.graph.box
import afield.document.graph.doResync
import afield.document.graph.isTrue
import afield.document.graph.needsResync
import afield.document.graph.nestedIn
import afield.document.persistence.SavingContext
import afield.document.persistence.safeSave
import afield.document.workspace.ProjectEntry
import afield.document.workspace.listWorkspaceProjects
import afield.document.workspace.projectsDir
import afield.graphics.vulkan.*
import afield.media.stream.*
import afield.media.video.*
import afield.runtime.execution.ExecutionVerdict
import afield.runtime.execution.KotlinExecution
import afield.runtime.execution.launches
import afield.runtime.execution.sourceRevision
import afield.runtime.lifecycle.Runloop
import afield.runtime.lifecycle.frames
import afield.runtime.lifecycle.inMain
import afield.runtime.lifecycle.map
import afield.tools.docs.DocsUiDriver
import afield.tools.docs.DocsUiRecorder
import afield.tools.docs.captureBoxScreenshot
import afield.tools.docs.captureClippedScreenshot
import afield.tools.docs.captureWindowScreenshot
import afield.tools.docs.computeDriveClip
import afield.tools.docs.computeSelectorClip
import afield.ui.output.templates.filter
import afield.ui.visualization.h

import afield.app.diagnostics.logging.lprintln
import afield.runtime.refreshMainLanguageRuntimes
import afield.runtime.execution._currentlyExecutingFragment
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.intOrNull
import org.yaml.snakeyaml.Yaml
import java.io.File
import java.time.Instant
import java.util.UUID
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ConcurrentHashMap
import kotlin.system.measureTimeMillis

Records the operations a person or agent performs on a document and replays them as named macros.

OperationTranscript logs edits, moves, executions, launches and stops as they happen (recordEdit, recordMove, recordExecuteFragment, recordLaunch, recordStop), and stores macros as YAML files in a macros/ folder at document, project or workspace scope (listMacros, writeMacro, runMacro). The backdoor's macro write and macro run commands use this; the YAML format and examples are in dev_docs/agents/OPERATION_TRANSCRIPT.md.

internal class InFlightOperationCoalescer<K, V>

Runs one operation per key at a time; a caller arriving while it runs waits for the same result.

internal class InFlightOperationCoalescer<K, V> {
    private val active = ConcurrentHashMap<K, CompletableFuture<V>>()

fun run(key: K, onJoin: (() -> Unit)?

    fun run(key: K, onJoin: (() -> Unit)? = null, operation: () -> V): V {
        val mine = CompletableFuture<V>()
        val existing = active.putIfAbsent(key, mine)
        if (existing != null) {
            onJoin?.invoke()
            return existing.join()
        }

        try {
            return operation().also(mine::complete)
        } catch (failure: Throwable) {
            mine.completeExceptionally(failure)
            throw failure
        } finally {
            active.remove(key, mine)
        }
    }
}

object OperationTranscript

object OperationTranscript {
    private const val COALESCE_FRAMES = 12L
    private const val WAIT_THRESHOLD_FRAMES = 2L
    private const val MACROS_DIR = "macros"

data class MacroInfo(val name: String, val path: String, val operationCount: Int)

data class MacroResult

    data class MacroResult(
        val success: Boolean,
        val message: String,
        val name: String = "",
        val path: String = "",
        val operationCount: Int = 0,
        val macros: List<String> = emptyList(),
        val content: String = "",
        val recording: Boolean = false,
        val draft: String = "",
        val selection: List<String> = emptyList(),
        val documentMacros: List<String> = emptyList(),
        val projectMacros: List<String> = emptyList(),
        val workspaceMacros: List<String> = emptyList(),
        val projectName: String = "",
        val scope: String = "document",
        val direction: String = "",
        val applied: Int = 0,
        val skipped: Int = 0,
        val errors: List<String> = emptyList(),
        val entries: List<TranscriptEntry> = emptyList(),
        val offset: Int = 0,
        val limit: Int = 0,
        val total: Int = 0,
        val hasMore: Boolean = false,
        val prompt: String = "",
        val output: List<MacroOutputLine> = emptyList(),
        val setupVerified: Boolean = true
    )

data class MacroRunResult

body — 68 lines, from line 172
    data class MacroRunResult(
        val success: Boolean,
        val message: String,
        val name: String,
        val direction: String,
        val targetBoxes: List<String>,
        val applied: Int,
        val skipped: Int,
        val errors: List<String> = emptyList(),
        // Box output/errors emitted while executing/launching boxes during this run,
        // so an agent driving a transcript can see println/_print output and errors.
        val output: List<MacroOutputLine> = emptyList(),
        val setupVerified: Boolean = true
    )

    private data class DocumentState(
        val documentPath: String,
        val lock: Any = Any(),
        val entries: MutableList<LinkedHashMap<String, Any?>> = mutableListOf(),
        var pendingEdit: PendingEdit? = null,
        var lastRecordedFrame: Long? = null,
        var loaded: Boolean = false,
        var dirty: Boolean = false,
        /** Entries before this index are never merged into (an AI turn's boundary; in memory only). */
        var mergeBarrier: Int = 0
    )

    private data class PendingEdit(
        val box: String,
        val property: String,
        val from: String,
        var to: String,
        var lastFrame: Long,
        /** Who made it: blank for a person, `ai4:<turn>` for an AI turn's tools. Never merged across. */
        val origin: String = ""
    )

    private data class MacroLocation(
        val scope: String,
        val projectName: String,
        val dir: File
    )

    private fun macroWriteRefusal(documentPath: String, location: MacroLocation, name: String = ""): MacroResult? {
        if (location.scope != "document" || !ReadOnlyDocuments.blocksWritesTo(normalizeDocumentPath(documentPath))) return null
        val target = if (name.isBlank()) location.dir else macroFile(location, name)
        ReadOnlyDocuments.refuseWrite("OperationTranscript.macro", target.absolutePath)
        return MacroResult(false, "The document is read-only; its macros cannot be changed.",
            name = name, path = target.absolutePath, scope = location.scope, projectName = location.projectName)
    }

    private data class MacroReplayContext(
        val macroName: String = "",
        val operationIndex: Int = -1,
        val operationCount: Int = -1,
        val launchIndex: Int = -1,
        val launchCount: Int = -1,
        val initializeCreatedBoxes: Boolean = true,
    )

    private data class MacroRunKey(
        val file: String,
        val targets: List<String>,
        val direction: String,
        val strict: Boolean,
        val initializeCreatedBoxes: Boolean,
        val replay: MacroReplayOptions = MacroReplayOptions(),
    )

data class MacroReplayOptions

How a run places what it replays. asCopy gives the boxes the macro creates fresh uids, so a second run makes a second set; offsetX/offsetY shift their frames; step replays one operation (0-based) of the macro and nothing else, which is how the panel steps through one.

    data class MacroReplayOptions(
        val asCopy: Boolean = false,
        val offsetX: Double = 0.0,
        val offsetY: Double = 0.0,
        val step: Int = -1,
    )

    private val activeMacroRuns = InFlightOperationCoalescer<MacroRunKey, MacroRunResult>()

    private data class MacroLaunchRequest(
        val target: Box,
        val exec: Execute,
        val context: MacroReplayContext
    )

    private val states = java.util.concurrent.ConcurrentHashMap<String, DocumentState>()

fun markStart(label: String = "", selection: List<String> = emptyList()): MacroResult

    fun markStart(label: String = "", selection: List<String> = emptyList()): MacroResult {
        val documentPath = currentDocumentPath() ?: return MacroResult(false, "No current document for macro start.")
        val markerName = label.ifBlank { "macro-${Instant.now()}" }
        val cleanSelection = selection.filter { it.isNotBlank() }.distinct()
        appendMarker(documentPath, "start", markerName, cleanSelection)
        checkpoint(documentPath)
        return MacroResult(
            true,
            "Started macro recording marker '$markerName'.",
            name = markerName,
            selection = cleanSelection,
            recording = true
        )
    }

fun markEndAndSave(name: String, label: String = "", scope: String = "document", projectName: String = ""): MacroResult

body — 54 lines, from line 278
    fun markEndAndSave(name: String, label: String = "", scope: String = "document", projectName: String = ""): MacroResult {
        val documentPath = currentDocumentPath() ?: return MacroResult(false, "No current document for macro end.")
        val cleanName = sanitizeMacroName(name)
        if (cleanName.isBlank()) return MacroResult(false, "Macro name cannot be empty.")

        val location = macroLocation(documentPath, scope, projectName)
            ?: return MacroResult(false, "No project macro scope is available for this document.")
        macroWriteRefusal(documentPath, location, cleanName)?.let { return it }

        val state = stateFor(documentPath)
        val frame = Runloop.runLoop.frame
        val endId = UUID.randomUUID().toString()
        val sliceAndSelection = synchronized(state.lock) {
            ensureLoaded(state)
            flushPendingEdit(state)
            val endEntry = markerEntry("end", label.ifBlank { cleanName }, endId, frame)
            state.entries += endEntry
            state.dirty = true

            val endIndex = state.entries.lastIndex
            val startIndex = state.entries
                .subList(0, endIndex)
                .indexOfLast { markerKind(it) == "start" }
            if (startIndex < 0) {
                return@synchronized null
            }
            val startSelection = markerSelection(state.entries[startIndex])
            val slice = state.entries
                .subList(startIndex + 1, endIndex)
                .filterNot { it.containsKey("marker") }
                .map { deepLinkedMap(it) }
            withoutIdleWaits(coalesceOperationRuns(slice)) to startSelection
        } ?: run {
            checkpoint(documentPath)
            return MacroResult(false, "No macro start marker found.")
        }

        val (slice, sourceSelection) = sliceAndSelection
        val macroPath = macroFile(location, cleanName)
        val text = writeMacroYaml(cleanName, documentPath, slice, sourceSelection)
        macroPath.parentFile?.mkdirs()
        val wrote = macroPath.safeSave(text, createBackup = true, maxBackups = 10, atomic = true)
        checkpoint(documentPath)
        return MacroResult(
            success = wrote,
            message = if (wrote) "Saved macro '$cleanName' with ${slice.size} operation(s)." else "Macro '$cleanName' was unchanged.",
            name = cleanName,
            path = macroPath.absolutePath,
            operationCount = slice.size,
            selection = sourceSelection.mapNotNull { it["uid"]?.toString() },
            scope = location.scope,
            projectName = location.projectName
        )
    }

fun listMacros

    fun listMacros(
        documentPath: String = currentDocumentPath().orEmpty(),
        scope: String = "document",
        projectName: String = ""
    ): MacroResult {
        if (documentPath.isBlank()) return MacroResult(false, "No document path available.")
        val location = macroLocation(documentPath, scope, projectName)
            ?: return MacroResult(false, "No project macro scope is available for this document.")
        val names = macroNames(location.dir)
        return MacroResult(
            true,
            "Found ${names.size} macro(s).",
            macros = names,
            scope = location.scope,
            projectName = location.projectName
        )
    }

fun readMacro(documentPath: String, name: String, scope: String = "document", projectName: String = ""): MacroResult

    fun readMacro(documentPath: String, name: String, scope: String = "document", projectName: String = ""): MacroResult {
        val location = macroLocation(documentPath, scope, projectName)
            ?: return MacroResult(false, "No project macro scope is available for this document.", name = sanitizeMacroName(name))
        val file = macroFile(location, sanitizeMacroName(name))
        if (!file.exists()) return MacroResult(false, "No macro named '${sanitizeMacroName(name)}'.", name = sanitizeMacroName(name))
        val operations = loadMacroOperations(file)
        return MacroResult(
            true,
            "Loaded macro '${file.nameWithoutExtension}'.",
            name = file.nameWithoutExtension,
            path = file.absolutePath,
            operationCount = operations.size,
            content = file.readText(),
            scope = location.scope,
            projectName = location.projectName
        )
    }

fun writeMacro

    fun writeMacro(
        documentPath: String,
        name: String,
        contents: String,
        scope: String = "document",
        projectName: String = ""
    ): MacroResult {
        val cleanName = sanitizeMacroName(name)
        if (cleanName.isBlank()) return MacroResult(false, "Macro name cannot be empty.")
        val location = macroLocation(documentPath, scope, projectName)
            ?: return MacroResult(false, "No project macro scope is available for this document.", name = cleanName)
        macroWriteRefusal(documentPath, location, cleanName)?.let { return it }
        val file = macroFile(location, cleanName)
        file.parentFile?.mkdirs()
        val wrote = file.safeSave(contents.trimEnd() + "\n", createBackup = true, maxBackups = 10, atomic = true)
        val count = runCatching { loadMacroOperations(file).size }.getOrDefault(0)
        return MacroResult(
            // safeSave returns false when the requested contents are already on disk.
            success = true,
            message = if (wrote) "Wrote macro '$cleanName'." else "Macro '$cleanName' was unchanged.",
            name = cleanName,
            path = file.absolutePath,
            operationCount = count,
            content = file.readText(),
            scope = location.scope,
            projectName = location.projectName
        )
    }

fun promoteMacro

Promote a macro to a broader scope so more documents can share it. The destination is the project when this document belongs to one, otherwise the workspace. The source is copied verbatim (a backup of any existing destination copy is kept), leaving the original in place.

body — 68 lines, from line 403
    fun promoteMacro(
        documentPath: String,
        name: String,
        scope: String = "document",
        projectName: String = ""
    ): MacroResult {
        if (documentPath.isBlank()) return MacroResult(false, "No document path available.")
        val cleanName = sanitizeMacroName(name)
        if (cleanName.isBlank()) return MacroResult(false, "Choose a macro to promote.", name = cleanName)
        val source = macroLocation(documentPath, scope, projectName)
            ?: return MacroResult(false, "No macro scope is available for this document.", name = cleanName)
        val sourceFile = macroFile(source, cleanName)
        if (!sourceFile.exists()) {
            return MacroResult(
                false,
                "No macro named '$cleanName' in the ${source.scope} scope.",
                name = cleanName,
                scope = source.scope,
                projectName = source.projectName
            )
        }
        // Escalate one step up the sharing hierarchy: document -> project (when in one) -> workspace.
        // Workspace is the broadest scope, so it is the terminus.
        val project = projectForDocument(documentPath, projectName)
        val targetScope = when {
            source.scope.equals("workspace", ignoreCase = true) -> "workspace"
            source.scope.equals("project", ignoreCase = true) -> "workspace"
            project != null -> "project"
            else -> "workspace"
        }
        val target = macroLocation(documentPath, targetScope, project?.name.orEmpty())
            ?: return MacroResult(
                false,
                "No $targetScope macro scope is available for this document.",
                name = cleanName,
                scope = source.scope,
                projectName = source.projectName
            )
        val destName = if (target.scope == "project") "project '${target.projectName}'" else "workspace"
        if (target.dir.canonicalFile == source.dir.canonicalFile) {
            return MacroResult(
                false,
                "Macro '$cleanName' is already in the $destName.",
                name = cleanName,
                scope = target.scope,
                projectName = target.projectName
            )
        }
        val targetFile = macroFile(target, cleanName)
        val contents = sourceFile.readText().trimEnd() + "\n"
        targetFile.parentFile?.mkdirs()
        val wrote = targetFile.safeSave(contents, createBackup = true, maxBackups = 10, atomic = true)
        val count = runCatching { loadMacroOperations(targetFile).size }.getOrDefault(0)
        return MacroResult(
            success = wrote || targetFile.exists(),
            message = if (wrote) {
                "Promoted macro '$cleanName' to the $destName."
            } else {
                "Macro '$cleanName' is already up to date in the $destName."
            },
            name = cleanName,
            path = targetFile.absolutePath,
            operationCount = count,
            content = contents,
            scope = target.scope,
            projectName = target.projectName
        )
    }

fun renameMacro

Rename a saved macro within its scope. The YAML's own name: line follows the file name, so the panel and the palette never disagree about what the macro is called. Refuses to replace an existing macro of the new name.

    fun renameMacro(
        documentPath: String,
        name: String,
        newName: String,
        scope: String = "document",
        projectName: String = ""
    ): MacroResult {
        val cleanName = sanitizeMacroName(name)
        val cleanNew = sanitizeMacroName(newName)
        if (cleanName.isBlank() || cleanNew.isBlank()) return MacroResult(false, "Macro names cannot be empty.")
        val location = macroLocation(documentPath, scope, projectName)
            ?: return MacroResult(false, "No $scope macro scope is available for this document.", name = cleanName)
        macroWriteRefusal(documentPath, location, cleanName)?.let { return it }
        val source = macroFile(location, cleanName)
        if (!source.exists()) return MacroResult(false, "No macro named '$cleanName'.", name = cleanName, scope = location.scope)
        if (cleanNew == cleanName) return MacroResult(true, "Macro '$cleanName' already has that name.", name = cleanName, scope = location.scope)
        val target = macroFile(location, cleanNew)
        if (target.exists()) return MacroResult(false, "A macro named '$cleanNew' already exists.", name = cleanName, scope = location.scope)
        val text = renameMacroYaml(source.readText(), cleanNew)
        val wrote = target.safeSave(text, createBackup = false, atomic = true)
        if (!wrote && !target.exists()) return MacroResult(false, "Could not write '$cleanNew'.", name = cleanName, scope = location.scope)
        source.delete()
        return MacroResult(
            true,
            "Renamed macro '$cleanName' to '$cleanNew'.",
            name = cleanNew,
            path = target.absolutePath,
            content = target.readText(),
            operationCount = runCatching { loadMacroOperations(target).size }.getOrDefault(0),
            scope = location.scope,
            projectName = location.projectName
        )
    }

internal fun renameMacroYaml(text: String, name: String): String

The YAML of a macro with its top-level name: set to name (added when it has none).

    internal fun renameMacroYaml(text: String, name: String): String {
        val lines = text.lines().toMutableList()
        val index = lines.indexOfFirst { it.startsWith("name:") }
        val line = "name: ${formatScalar(name)}"
        if (index >= 0) lines[index] = line else lines.add(0, line)
        return lines.joinToString("\n").trimEnd() + "\n"
    }

fun deleteMacro

Delete a saved macro. The file is moved to the scope's .deleted/ folder with a timestamp, not erased, so a deletion from the panel can be recovered by hand; the macro lists only read the scope folder itself.

    fun deleteMacro(
        documentPath: String,
        name: String,
        scope: String = "document",
        projectName: String = ""
    ): MacroResult {
        val cleanName = sanitizeMacroName(name)
        if (cleanName.isBlank()) return MacroResult(false, "Choose a macro to delete.")
        val location = macroLocation(documentPath, scope, projectName)
            ?: return MacroResult(false, "No $scope macro scope is available for this document.", name = cleanName)
        macroWriteRefusal(documentPath, location, cleanName)?.let { return it }
        val source = macroFile(location, cleanName)
        if (!source.exists()) return MacroResult(false, "No macro named '$cleanName'.", name = cleanName, scope = location.scope)
        val trash = File(location.dir, ".deleted").also { it.mkdirs() }
        val stamp = Instant.now().toString().replace(":", "-")
        val target = File(trash, "$cleanName-$stamp.yaml")
        val moved = source.renameTo(target) || run {
            target.writeText(source.readText())
            source.delete()
        }
        return MacroResult(
            moved,
            if (moved) "Deleted macro '$cleanName' (kept in ${trash.name}/${target.name})." else "Could not delete '$cleanName'.",
            name = cleanName,
            path = target.absolutePath,
            scope = location.scope,
            projectName = location.projectName
        )
    }

fun saveTranscriptSelectionAsMacro

body — 50 lines, from line 555
    fun saveTranscriptSelectionAsMacro(
        documentPath: String,
        name: String,
        indices: List<Int>,
        selection: List<String> = emptyList(),
        scope: String = "document",
        projectName: String = ""
    ): MacroResult {
        if (documentPath.isBlank()) return MacroResult(false, "No document path available.")
        val cleanName = sanitizeMacroName(name)
        if (cleanName.isBlank()) return MacroResult(false, "Macro name cannot be empty.")
        val snapshot = transcriptSnapshot(documentPath)
        val cleanIndices = indices.distinct().filter { it in snapshot.indices }.sorted()
        if (cleanIndices.isEmpty()) {
            return MacroResult(false, "Select one or more transcript operations to save.")
        }
        val operations = cleanIndices
            .map { snapshot[it] }
            .filter { entry ->
                entry.keys.firstOrNull()?.lowercase() !in setOf("wait", "marker")
            }
            .map { deepLinkedMap(it) }
        if (operations.isEmpty()) {
            return MacroResult(false, "Selected transcript entries do not contain any macro operations.")
        }
        val coalesced = coalesceOperationRuns(operations)
        val location = macroLocation(documentPath, scope, projectName)
            ?: return MacroResult(false, "No project macro scope is available for this document.", name = cleanName)
        macroWriteRefusal(documentPath, location, cleanName)?.let { return it }
        val file = macroFile(location, cleanName)
        val sourceSelection = selectionEntries(selection)
        val text = writeMacroYaml(cleanName, documentPath, coalesced, sourceSelection)
        file.parentFile?.mkdirs()
        val wrote = file.safeSave(text, createBackup = true, maxBackups = 10, atomic = true)
        return MacroResult(
            success = wrote,
            message = if (wrote) {
                "Saved selected transcript as macro '$cleanName' with ${coalesced.size} operation(s)."
            } else {
                "Macro '$cleanName' was unchanged."
            },
            name = cleanName,
            path = file.absolutePath,
            operationCount = coalesced.size,
            content = file.readText(),
            selection = sourceSelection.mapNotNull { it["uid"]?.toString() },
            scope = location.scope,
            projectName = location.projectName
        )
    }

fun macroDirectory(documentPath: String, scope: String = "document", projectName: String = ""): MacroResult

    fun macroDirectory(documentPath: String, scope: String = "document", projectName: String = ""): MacroResult {
        if (documentPath.isBlank()) return MacroResult(false, "No document path available.")
        val location = macroLocation(documentPath, scope, projectName)
            ?: return MacroResult(false, "No macro scope is available for this document.")
        if (!location.dir.isDirectory) macroWriteRefusal(documentPath, location)?.let { return it }
        location.dir.mkdirs()
        return MacroResult(
            true,
            "Macro folder is ${location.dir.absolutePath}.",
            path = location.dir.absolutePath,
            scope = location.scope,
            projectName = location.projectName
        )
    }

fun runMacro

body — 226 lines, from line 621
    fun runMacro(
        documentPath: String,
        name: String,
        targetBoxes: List<String> = emptyList(),
        direction: String = "do",
        strict: Boolean = false,
        scope: String = "document",
        projectName: String = "",
        initializeCreatedBoxes: Boolean = true,
        replay: MacroReplayOptions = MacroReplayOptions(),
    ): MacroRunResult {
        val cleanName = sanitizeMacroName(name)
        val location = macroLocation(documentPath, scope, projectName)
        if (location == null) {
            return MacroRunResult(false, "No project macro scope is available for this document.", cleanName, direction, targetBoxes, 0, 0)
        }
        val file = macroFile(location, cleanName)
        if (!file.exists()) {
            return MacroRunResult(false, "No macro named '$cleanName'.", cleanName, direction, targetBoxes, 0, 0)
        }
        val normalizedDirection = if (direction.equals("undo", ignoreCase = true)) "undo" else "do"
        val normalizedTargets = targetBoxes.filter { it.isNotBlank() }
        val key = MacroRunKey(
            file = file.canonicalPath,
            targets = normalizedTargets,
            direction = normalizedDirection,
            strict = strict,
            initializeCreatedBoxes = initializeCreatedBoxes,
            replay = replay,
        )
        // Box code calling this (a box that replays a macro) runs on a thread with no session
        // bound; the document's own session is the one the macro's operations act on.
        val bound = runCatching { thisSessionInfo.get() }.getOrNull()
        val session = if (bound != null) null else documents.values.firstOrNull {
            normalizeDocumentPath(it.filename) == normalizeDocumentPath(documentPath)
        }
        if (session != null) thisSessionInfo.set(session)
        try {
            return activeMacroRuns.run(key) {
                afield.app.diagnostics.LatencySpans.time("transcript.run", detail = cleanName) {
                    runMacroOnce(
                        documentPath = documentPath,
                        name = cleanName,
                        targetBoxes = normalizedTargets,
                        direction = normalizedDirection,
                        strict = strict,
                        scope = scope,
                        projectName = projectName,
                        initializeCreatedBoxes = initializeCreatedBoxes,
                        replay = replay,
                    )
                }
            }
        } finally {
            if (session != null) thisSessionInfo.remove()
        }
    }

    private fun runMacroOnce(
        documentPath: String,
        name: String,
        targetBoxes: List<String>,
        direction: String,
        strict: Boolean,
        scope: String,
        projectName: String,
        initializeCreatedBoxes: Boolean,
        replay: MacroReplayOptions = MacroReplayOptions(),
    ): MacroRunResult {
        val cleanName = sanitizeMacroName(name)
        val location = macroLocation(documentPath, scope, projectName)
        if (location == null) {
            return MacroRunResult(false, "No project macro scope is available for this document.", cleanName, direction, targetBoxes, 0, 0)
        }
        val file = macroFile(location, cleanName)
        if (!file.exists()) {
            return MacroRunResult(false, "No macro named '$cleanName'.", cleanName, direction, targetBoxes, 0, 0)
        }
        val loaded = loadMacroOperations(file)
        val relocated = if (replay.asCopy || replay.offsetX != 0.0 || replay.offsetY != 0.0) {
            relocateOperations(loaded, replay.asCopy, replay.offsetX, replay.offsetY)
        } else loaded
        val operations = if (replay.step >= 0) {
            val one = relocated.getOrNull(replay.step)
                ?: return MacroRunResult(
                    false,
                    "Macro '$cleanName' has no step ${replay.step + 1} (it has ${relocated.size}).",
                    cleanName, direction, targetBoxes, 0, 0
                )
            listOf(one)
        } else relocated
        val normalizedDirection = if (direction.equals("undo", ignoreCase = true)) "undo" else "do"
        val ordered = if (normalizedDirection == "undo") operations.asReversed() else operations
        val targets = targetBoxes.filter { it.isNotBlank() }.ifEmpty { listOf("") }
        val launchCount = ordered.count { operationVerb(it) in launchVerbs }
        val errors = java.util.Collections.synchronizedList(mutableListOf<String>())
        var applied = 0
        var skipped = 0
        val collected = java.util.Collections.synchronizedList(mutableListOf<MacroOutputLine>())
        val unverified = java.util.concurrent.ConcurrentHashMap.newKeySet<String>()
        val collect: (Message) -> Unit = { msg ->
            if (msg.name == "execution-dispatched") {
                val payload = msg.payload as? kotlinx.serialization.json.JsonObject
                unverified.add(payload?.get("uid")?.toString().orEmpty())
            }
            // Every engine answers a dispatched execution with a verdict; that is the receipt that
            // turns "dispatched" into "completed" (or into an error) for a non-Kotlin box.
            if (msg.name == "execution-verdict") {
                val payload = msg.payload as? kotlinx.serialization.json.JsonObject
                val uid = payload?.get("uid")?.toString().orEmpty()
                if (unverified.remove(uid)) {
                    val ok = (payload?.get("success") as? kotlinx.serialization.json.JsonPrimitive)?.content == "true"
                    if (!ok) errors += "execution of $uid failed: " +
                        ((payload?.get("error") as? kotlinx.serialization.json.JsonPrimitive)?.content ?: "no message")
                }
            }
            synchronized(collected) { if (collected.size < 200) captureMacroOutput(msg, collected) }
        }

        targets.forEach { target ->
            if (normalizedDirection == "do" && errors.isNotEmpty()) {
                skipped += ordered.size
                return@forEach
            }
            val primarySource = firstOperationBox(relocated)
            val boxMap = if (target.isNotBlank() && primarySource != null) mapOf(primarySource to target) else emptyMap()
            var launchIndex = 0
            var index = 0
            while (index < ordered.size) {
                if (normalizedDirection == "do" && operationVerb(ordered[index]) in launchVerbs) {
                    val launchGroup = mutableListOf<Pair<Map<String, Any?>, MacroReplayContext>>()
                    while (index < ordered.size && operationVerb(ordered[index]) in launchVerbs) {
                        val op = ordered[index]
                        launchGroup += op to MacroReplayContext(
                            macroName = cleanName,
                            operationIndex = index + 1,
                            operationCount = ordered.size,
                            launchIndex = ++launchIndex,
                            launchCount = launchCount,
                            initializeCreatedBoxes = initializeCreatedBoxes,
                        )
                        index++
                    }
                    val groupDiagnostics = mutableListOf<String>()
                    val groupBoxes = launchGroup.joinToString(",") { (op, _) -> operationBoxName(op).orEmpty() }
                    val result = runCatching {
                        afield.app.diagnostics.LatencySpans.time("transcript.launchGroup", detail = "$cleanName: $groupBoxes") {
                            applyMacroLaunchGroup(launchGroup, boxMap, collect, groupDiagnostics)
                        }
                    }
                    if (result.isSuccess) {
                        val (groupApplied, groupSkipped) = result.getOrThrow()
                        applied += groupApplied
                        skipped += groupSkipped
                        // Surface loud launch failures (missing box / empty code) so the run
                        // reports success=false and the message names what went wrong.
                        errors += groupDiagnostics
                    } else {
                        skipped += launchGroup.size
                        errors += result.exceptionOrNull()?.message ?: "Unknown macro launch group failure."
                    }
                    if (errors.isNotEmpty()) {
                        skipped += ordered.size - index
                        break
                    }
                    continue
                }

                val op = ordered[index]
                val verb = operationVerb(op)
                val context = MacroReplayContext(
                    macroName = cleanName,
                    operationIndex = index + 1,
                    operationCount = ordered.size,
                    launchIndex = if (verb in launchVerbs) ++launchIndex else -1,
                    launchCount = launchCount,
                    initializeCreatedBoxes = initializeCreatedBoxes,
                )
                val result = runCatching {
                    afield.app.diagnostics.LatencySpans.time("transcript.op", box = operationBoxName(op), detail = "$cleanName: $verb") {
                        applyMacroOperation(op, boxMap, normalizedDirection, strict, context, collect)
                    }
                }
                if (result.isSuccess) {
                    if (result.getOrDefault(false)) applied++ else skipped++
                } else {
                    skipped++
                        errors += result.exceptionOrNull()?.let(::describeMacroFailure)
                            ?: "Unknown macro operation failure."
                }
                index++
                // A failed prerequisite must not launch dependent code. Undo remains
                // best-effort so a broken box cannot prevent later cleanup operations.
                if (normalizedDirection == "do" && errors.isNotEmpty()) {
                    skipped += ordered.size - index
                    break
                }
            }
        }
        // Give non-Kotlin executions a bounded moment to report their verdicts before the receipt is written.
        val verdictDeadline = System.nanoTime() + 10_000_000_000L
        // Only off the Runloop: verdicts are delivered through it, so waiting on it would only stall.
        if (!afield.runtime.lifecycle.Runloop.isMainThread) {
            while (unverified.isNotEmpty() && System.nanoTime() < verdictDeadline) Thread.sleep(20)
        }
        if (applied > 0) runCatching { doResync() }
        val noChangeMessage = if (errors.isEmpty() && applied == 0) {
            " No operations changed anything; check the target selection and source uid mapping."
        } else {
            ""
        }
        val dispatchMessage = if (unverified.isEmpty()) "" else
            " ${unverified.size} non-Kotlin execution(s) dispatched; setup completion is unverified."
        return MacroRunResult(
            success = errors.isEmpty(),
            message = "Ran macro '$cleanName': applied=$applied skipped=$skipped errors=${errors.size}.$noChangeMessage$dispatchMessage",
            name = cleanName,
            direction = normalizedDirection,
            targetBoxes = targetBoxes,
            applied = applied,
            skipped = skipped,
            errors = errors,
            output = collected.toList(),
            setupVerified = unverified.isEmpty() && errors.isEmpty()
        )
    }

fun macroState(documentPath: String = currentDocumentPath().orEmpty(), scope: String = "document", projectName: String = ""): MacroResult

body — 42 lines, from line 848
    fun macroState(documentPath: String = currentDocumentPath().orEmpty(), scope: String = "document", projectName: String = ""): MacroResult {
        if (documentPath.isBlank()) return MacroResult(false, "No document path available.")
        val documentMacroNames = macroNames(documentMacrosDir(documentPath))
        val projectEntry = projectForDocument(documentPath, projectName)
        val projectMacroNames = projectEntry?.let { macroNames(projectMacrosDir(documentPath, it.name)) }.orEmpty()
        val workspaceMacroNames = macroNames(workspaceMacrosDir(documentPath))
        val requestedLocation = macroLocation(documentPath, scope, projectName)
        val state = stateFor(documentPath)
        val draftPair = synchronized(state.lock) {
            ensureLoaded(state)
            flushPendingEdit(state)
            val lastMarkerIndex = state.entries.indexOfLast { it.containsKey("marker") }
            if (lastMarkerIndex < 0 || markerKind(state.entries[lastMarkerIndex]) != "start") {
                false to (emptyList<LinkedHashMap<String, Any?>>() to emptyList<LinkedHashMap<String, Any?>>())
            } else {
                val selection = markerSelection(state.entries[lastMarkerIndex])
                val ops = state.entries
                    .subList(lastMarkerIndex + 1, state.entries.size)
                    .filterNot { it.containsKey("marker") }
                    .map { deepLinkedMap(it) }
                true to (coalesceOperationRuns(ops) to selection)
            }
        }
        val recording = draftPair.first
        val operations = draftPair.second.first
        val sourceSelection = draftPair.second.second
        return MacroResult(
            success = true,
            message = if (recording) "Recording ${operations.size} operation(s)." else "Macro recorder is idle.",
            operationCount = operations.size,
            macros = requestedLocation?.let { macroNames(it.dir) } ?: documentMacroNames,
            content = "",
            recording = recording,
            draft = "",
            selection = sourceSelection.mapNotNull { it["uid"]?.toString() },
            documentMacros = documentMacroNames,
            projectMacros = projectMacroNames,
            workspaceMacros = workspaceMacroNames,
            projectName = projectEntry?.name.orEmpty(),
            scope = requestedLocation?.scope ?: "document"
        )
    }

fun transcriptPage(documentPath: String, offset: Int = 0, limit: Int = 80, includeWaits: Boolean = true): MacroResult

    fun transcriptPage(documentPath: String, offset: Int = 0, limit: Int = 80, includeWaits: Boolean = true): MacroResult {
        if (documentPath.isBlank()) return MacroResult(false, "No document path available.")
        val cleanLimit = limit.coerceIn(1, 250)
        val snapshot = transcriptSnapshot(documentPath)
            .mapIndexed { index, entry -> index to entry }
            .filter { (_, entry) -> includeWaits || entry.keys.firstOrNull()?.lowercase() != "wait" }
        val cleanOffset = if (offset < 0) {
            (snapshot.size - cleanLimit).coerceAtLeast(0)
        } else {
            offset.coerceIn(0, snapshot.size)
        }
        val page = snapshot
            .drop(cleanOffset)
            .take(cleanLimit)
            .map { (entryIndex, entry) -> transcriptEntry(entryIndex, entry) }
        val pageLog =
            "page document=${File(documentPath).name} offset=$cleanOffset limit=$cleanLimit total=${snapshot.size} entries=${page.size} includeWaits=$includeWaits"
        println("[operation-transcript] $pageLog")
        lprintln("info,operation-transcript", pageLog)
        return MacroResult(
            success = true,
            message = "Loaded transcript entries ${if (page.isEmpty()) 0 else cleanOffset + 1}-${cleanOffset + page.size} of ${snapshot.size}.",
            entries = page,
            offset = cleanOffset,
            limit = cleanLimit,
            total = snapshot.size,
            hasMore = cleanOffset + page.size < snapshot.size
        )
    }

fun undoTranscriptSelection

    fun undoTranscriptSelection(
        documentPath: String,
        indices: List<Int>,
        strict: Boolean = true
    ): MacroResult {
        if (documentPath.isBlank()) return MacroResult(false, "No document path available.")
        val snapshot = transcriptSnapshot(documentPath)
        val cleanIndices = indices.distinct().filter { it in snapshot.indices }.sortedDescending()
        if (cleanIndices.isEmpty()) {
            return MacroResult(false, "Select one or more transcript operations to undo.")
        }
        val errors = mutableListOf<String>()
        var applied = 0
        var skipped = 0
        cleanIndices.forEach { index ->
            val entry = snapshot[index]
            val result = runCatching { applyMacroOperation(entry, emptyMap(), "undo", strict) }
            if (result.isSuccess) {
                if (result.getOrDefault(false)) applied++ else skipped++
            } else {
                skipped++
                errors += "#$index ${entry.keys.firstOrNull().orEmpty()}: ${result.exceptionOrNull()?.message ?: "Unknown undo failure."}"
            }
        }
        if (applied > 0) runCatching { doResync() }
        val noChangeMessage = if (errors.isEmpty() && applied == 0) {
            " No operations changed anything; later edits may already have removed the recorded change."
        } else {
            ""
        }
        return MacroResult(
            success = errors.isEmpty(),
            message = "Undid ${cleanIndices.size} transcript entr${if (cleanIndices.size == 1) "y" else "ies"}: applied=$applied skipped=$skipped errors=${errors.size}.$noChangeMessage",
            operationCount = cleanIndices.size,
            direction = "undo",
            applied = applied,
            skipped = skipped,
            errors = errors
        )
    }

fun aiUndoPrompt(documentPath: String, indices: List<Int>, selection: List<String> = emptyList()): MacroResult

body — 44 lines, from line 962
    fun aiUndoPrompt(documentPath: String, indices: List<Int>, selection: List<String> = emptyList()): MacroResult {
        if (documentPath.isBlank()) return MacroResult(false, "No document path available.")
        val snapshot = transcriptSnapshot(documentPath)
        val cleanIndices = indices.distinct().filter { it in snapshot.indices }.sorted()
        if (cleanIndices.isEmpty()) {
            return MacroResult(false, "Select one or more transcript operations for AI4 to reason about.")
        }
        val selectedEntries = cleanIndices.map { it to snapshot[it] }
        val operationYaml = writeYamlList(selectedEntries.map { it.second })
        val summaries = selectedEntries.joinToString("\n") { (index, entry) ->
            val summary = transcriptEntry(index, entry).summary
            "- #$index $summary"
        }
        val contextSelection = selection.filter { it.isNotBlank() }.distinct()
        val promptText = buildString {
            appendLine("You are helping undo a selected slice of Field's front-end operation transcript.")
            appendLine()
            appendLine("Goal:")
            appendLine("- Undo the intent of the selected transcript entries while preserving unrelated later work in the document.")
            appendLine("- Prefer the established AI4 proposed-changes workflow for text/property edits, so the user can inspect and accept/reject changes.")
            appendLine("- If you need to run a macro or transcript operation and it errors, undo your attempted changes, report the error, and ask what the user wants to do next.")
            appendLine("- Be generous: boxes may have changed since these entries were recorded, so use the from/to pair as context rather than blindly overwriting current values.")
            appendLine()
            appendLine("Current selected boxes in the UI:")
            if (contextSelection.isEmpty()) appendLine("- none") else contextSelection.forEach { appendLine("- $it") }
            appendLine()
            appendLine("Selected transcript entries:")
            appendLine(summaries)
            appendLine()
            appendLine("YAML context:")
            appendLine("```yaml")
            append(operationYaml.trimEnd())
            appendLine()
            appendLine("```")
            appendLine()
            appendLine("Please inspect the affected boxes/properties as needed, propose the undo as AI4 provisional changes when possible, and explain any uncertainty before applying irreversible operations.")
        }
        return MacroResult(
            success = true,
            message = "Prepared AI4 undo prompt for ${cleanIndices.size} transcript entr${if (cleanIndices.size == 1) "y" else "ies"}.",
            operationCount = cleanIndices.size,
            prompt = promptText
        )
    }

fun recordEdit(box: Box, property: String, from: String?, to: String?, origin: String = "")

    fun recordEdit(box: Box, property: String, from: String?, to: String?, origin: String = "") {
        if (from == to) return
        if (property.endsWith("_editorState")) return
        val documentPath = documentPathFor(box) ?: return
        val frame = Runloop.runLoop.frame
        val state = stateFor(documentPath)
        synchronized(state.lock) {
            ensureLoaded(state)
            val pending = state.pendingEdit
            if (
                pending != null &&
                    pending.box == box.id &&
                    pending.property == property &&
                    pending.origin == origin &&
                    frame - pending.lastFrame <= COALESCE_FRAMES
            ) {
                pending.to = to.orEmpty()
                pending.lastFrame = frame
                state.dirty = true
                return
            }
            flushPendingEdit(state)
            state.pendingEdit = PendingEdit(
                box = box.id,
                property = property,
                from = from.orEmpty(),
                to = to.orEmpty(),
                lastFrame = frame,
                origin = origin
            )
            state.dirty = true
        }
    }

fun turnBoundary(documentPath: String): Int

Mark an AI turn's start or end: flush the pending edit and forbid merging into anything recorded so far. Returns the cursor (the number of entries), which the session tree keeps as the turn's op.from/op.to.

    fun turnBoundary(documentPath: String): Int {
        if (documentPath.isBlank()) return -1
        val state = stateFor(documentPath)
        return synchronized(state.lock) {
            ensureLoaded(state)
            flushPendingEdit(state)
            state.mergeBarrier = state.entries.size
            state.entries.size
        }
    }

fun countOrigins(documentPath: String, origins: Set<String>): Int

How many recorded edits were made under one of origins.

    fun countOrigins(documentPath: String, origins: Set<String>): Int {
        if (documentPath.isBlank() || origins.isEmpty()) return 0
        return transcriptSnapshot(documentPath).count { ((it["edit"] as? Map<*, *>)?.get("origin")?.toString()) in origins }
    }

fun undoOrigins(documentPath: String, origins: Set<String>): MacroResult

Undo every recorded edit made under one of origins (AI turns being rewound), newest first, strictly: an edit whose property has changed since is skipped and reported, never overwritten.

    fun undoOrigins(documentPath: String, origins: Set<String>): MacroResult {
        if (documentPath.isBlank() || origins.isEmpty()) return MacroResult(false, "Nothing to undo.")
        val snapshot = transcriptSnapshot(documentPath)
        val indices = snapshot.indices.filter { i -> ((snapshot[i]["edit"] as? Map<*, *>)?.get("origin")?.toString()) in origins }
        if (indices.isEmpty()) return MacroResult(true, "Those turns recorded no document edits.", direction = "undo")
        return undoTranscriptSelection(documentPath, indices, strict = true)
    }

fun recordMove(box: Box, from: Rect, to: Rect)

    fun recordMove(box: Box, from: Rect, to: Rect) {
        if (from == to) return
        val documentPath = documentPathFor(box) ?: return
        val frame = Runloop.runLoop.frame
        val state = stateFor(documentPath)
        synchronized(state.lock) {
            ensureLoaded(state)
            flushPendingEdit(state)
            if (foldIntoPreviousCreate(state.entries, box.id, "frame", rectMap(to))) {
                state.lastRecordedFrame = frame
                state.dirty = true
                return
            }
            if (mergeMoveIntoPrevious(state, box.id, to)) {
                state.lastRecordedFrame = frame
                state.dirty = true
                return
            }
            appendWaitIfNeeded(state, frame)
            if (mergeMoveIntoPrevious(state, box.id, to)) {
                state.lastRecordedFrame = frame
                state.dirty = true
                return
            }
            state.entries += moveEntry(box.id, from, to)
            state.lastRecordedFrame = frame
            state.dirty = true
        }
    }

fun recordExecuteFragment(box: Box, execute: Execute)

Recorded executions name the box and where in it, not a copy of its code: a replay runs the box as it is then (MacroReplayCode). A fragment keeps its text as recordedCode, which the replay looks for in the box's current code; a whole-box launch keeps one only when what ran was not the box's stored code.

    fun recordExecuteFragment(box: Box, execute: Execute) {
        recordExecutionEvent(
            box,
            "execute",
            linkedMapOf<String, Any?>(
                "box" to box.id,
                "property" to execute.property,
                "line" to execute.line,
                "recordedCode" to execute.code,
                "singleLine" to execute.singleLine,
                "type" to execute.type
            )
        )
    }

fun recordLaunch(box: Box, execute: Execute, strand: String = execute.strand)

    fun recordLaunch(box: Box, execute: Execute, strand: String = execute.strand) {
        val payload = linkedMapOf<String, Any?>(
            "box" to box.id,
            "property" to execute.property,
            "line" to execute.line
        )
        val stored = box.getPropertyRaw(execute.property) as? String
        if (execute.type == "fragment" || stored?.trim() != execute.code.trim()) payload["recordedCode"] = execute.code
        payload["singleLine"] = execute.singleLine
        payload["type"] = execute.type
        payload["strand"] = strand.ifBlank { "default" }
        recordExecutionEvent(box, "launch", payload)
    }

fun recordStop(box: Box)

    fun recordStop(box: Box) {
        recordExecutionEvent(
            box,
            "stop",
            linkedMapOf(
                "box" to box.id
            )
        )
    }

fun recordCreate(box: Box)

A box the person just made on the canvas. The frontend creates a box by sending its name and then its frame (createBox in Main.kt), so the box's first property message is where the server learns of it; the handlers call this once the value is applied. The entry carries the box's name and frame, and the frame / first-value edits that follow are folded into it (see foldIntoPreviousCreate), so a recording reads create {box, name, frame, properties} rather than an edit from nothing. Without it a recording replayed into a fresh document edited boxes that did not exist (audit, 2026-10-20: applied=2 skipped=5, no boxes).

body — 57 lines, from line 1156
    fun recordCreate(box: Box) {
        if (box.id == "root" || box.id == METAROOT_ID) return
        val documentPath = documentPathFor(box) ?: return
        val frame = Runloop.runLoop.frame
        val state = stateFor(documentPath)
        synchronized(state.lock) {
            ensureLoaded(state)
            // The handlers for one new box run concurrently, so its frame, code or even a
            // connection can be recorded a moment before its create. The create goes where the box
            // is first named in this recording (it existed by then), and the moves and first
            // values of it that follow fold into it. A pending edit of this box stays pending and
            // folds once flushed.
            if (state.pendingEdit?.box != box.id) flushPendingEdit(state)
            val payload = linkedMapOf<String, Any?>("box" to box.id, "name" to box.name)
            val rect = runCatching { box.frame }.getOrNull()
            if (rect != null && !(rect.w == 0.0 && rect.h == 0.0)) payload["frame"] = rectMap(rect)
            val createEntry = linkedMapOf<String, Any?>("create" to payload)
            val since = state.entries.indexOfLast { it.containsKey("marker") } + 1
            val firstMention = (since until state.entries.size).firstOrNull { entryNames(state.entries[it], box.id) }
            if (firstMention == null) {
                appendWaitIfNeeded(state, frame)
                state.entries += createEntry
            } else {
                state.entries.add(firstMention, createEntry)
                var index = firstMention + 1
                while (index < state.entries.size) {
                    val entry = state.entries[index]
                    val verb = entry.keys.firstOrNull()?.lowercase().orEmpty()
                    if (verb in launchVerbs || verb == "execute" || verb == "execute-fragment") break
                    if (!entryNames(entry, box.id)) { index++; continue }
                    val move = entry["move"] as? Map<*, *>
                    val edit = entry["edit"] as? Map<*, *>
                    when {
                        move != null -> { payload["frame"] = move["to"]; state.entries.removeAt(index) }
                        edit != null && edit["origin"] == null &&
                            (edit["from"]?.toString().isNullOrEmpty() || edit["property"] == "name") -> {
                            val property = edit["property"]?.toString().orEmpty()
                            if (property == "name") payload["name"] = edit["to"]
                            else {
                                @Suppress("UNCHECKED_CAST")
                                val properties = (payload["properties"] as? MutableMap<String, Any?>)
                                    ?: linkedMapOf<String, Any?>().also { payload["properties"] = it }
                                properties[property] = edit["to"]
                            }
                            state.entries.removeAt(index)
                        }
                        else -> index++
                    }
                }
                // The box's current name and frame are the latest of all of these.
                payload["name"] = box.name
                if (rect != null && !(rect.w == 0.0 && rect.h == 0.0)) payload["frame"] = rectMap(rect)
            }
            state.lastRecordedFrame = frame
            state.dirty = true
        }
    }

Whether entry names box uid (as its subject, or as either end of a connection).

    private fun entryNames(entry: Map<String, Any?>, uid: String): Boolean {
        val payload = entry.values.firstOrNull() as? Map<*, *> ?: return false
        return listOf("box", "uid", "id", "target", "parent", "child").any { payload[it]?.toString() == uid }
    }

fun recordDelete(box: Box)

A box the person deleted (the -delete-box action). Replays as a tombstone; undoes as a restore.

    fun recordDelete(box: Box) {
        if (box.id == "root" || box.id == METAROOT_ID) return
        recordExecutionEvent(box, "delete", linkedMapOf("box" to box.id, "name" to box.name))
    }

fun recordConnect(parent: Box, child: Box, connected: Boolean)

A connection the person made or removed (the -connect / -disconnect actions, the g key).

    fun recordConnect(parent: Box, child: Box, connected: Boolean) {
        if (child.id == "root" || child.id == METAROOT_ID) return
        recordExecutionEvent(
            child,
            if (connected) "connect" else "disconnect",
            linkedMapOf("parent" to parent.id, "child" to child.id)
        )
    }

Fold a value into the create entry of box: frame sets the create's frame, name its name, anything else lands in its properties. True when folded. The search walks back over waits and over entries that do not name box (another box made in the same burst — the canvas makes boxes faster than their messages arrive), and stops at the first entry that names it (connections aside), which must be its create, or at any execute / launch, whose code might read the box as it was. So an edit made after anything else happened to the box stays an edit.

    private fun foldIntoPreviousCreate(
        entries: MutableList<LinkedHashMap<String, Any?>>,
        box: String,
        property: String,
        value: Any?
    ): Boolean {
        var index = entries.lastIndex
        while (index >= 0) {
            val entry = entries[index]
            val verb = entry.keys.firstOrNull()?.lowercase().orEmpty()
            if (verb == "wait") { index--; continue }
            if (verb in launchVerbs || verb == "execute" || verb == "execute-fragment" || verb == "marker") return false
            val payload = entry.values.firstOrNull() as? Map<*, *> ?: return false
            val names = listOf("box", "uid", "id", "target", "parent", "child").mapNotNull { payload[it]?.toString() }
            // A connection does not read a box's name, frame or code, so a value can fold past it.
            if (box !in names || verb == "connect" || verb == "disconnect") { index--; continue }
            if (verb != "create") return false
            break
        }
        if (index < 0) return false
        @Suppress("UNCHECKED_CAST")
        val payload = entries[index]["create"] as? MutableMap<String, Any?> ?: return false
        when (property) {
            "frame", "name" -> payload[property] = value
            else -> {
                @Suppress("UNCHECKED_CAST")
                val properties = (payload["properties"] as? MutableMap<String, Any?>)
                    ?: linkedMapOf<String, Any?>().also { payload["properties"] = it }
                properties[property] = value
            }
        }
        removeTrailingWaitsAfter(entries, index)
        return true
    }

fun checkpoint(documentPath: String): Boolean

body — 210 lines, from line 1279
    fun checkpoint(documentPath: String): Boolean {
        val state = states[normalizeDocumentPath(documentPath)] ?: return false
        val snapshot = synchronized(state.lock) {
            ensureLoaded(state)
            flushPendingEdit(state)
            if (!state.dirty) return false
            state.entries.map { LinkedHashMap(it) }
        }
        if (ReadOnlyDocuments.blocksWritesTo(normalizeDocumentPath(documentPath))) {
            ReadOnlyDocuments.refuseWrite("OperationTranscript.checkpoint", operationTranscriptFile(documentPath).absolutePath)
            return false
        }
        return try {
            val file = operationTranscriptFile(documentPath)
            file.parentFile?.mkdirs()
            val text = writeYamlList(snapshot)
            val wrote = file.safeSave(text, createBackup = true, maxBackups = 10, atomic = true)
            synchronized(state.lock) {
                state.dirty = false
            }
            wrote
        } catch (t: Throwable) {
            lprintln("warning,operation-transcript", "Failed to checkpoint operation transcript for $documentPath: ${t.message}")
            false
        }
    }

    private fun recordExecutionEvent(box: Box, verb: String, payload: LinkedHashMap<String, Any?>) {
        val documentPath = documentPathFor(box) ?: return
        val frame = Runloop.runLoop.frame
        val state = stateFor(documentPath)
        synchronized(state.lock) {
            ensureLoaded(state)
            flushPendingEdit(state)
            appendWaitIfNeeded(state, frame)
            state.entries += linkedMapOf(verb to payload)
            state.lastRecordedFrame = frame
            state.dirty = true
        }
    }

    private fun flushPendingEdit(state: DocumentState) {
        val pending = state.pendingEdit ?: return
        state.pendingEdit = null
        if (pending.from == pending.to) return
        if (pending.origin.isBlank() && (pending.from.isEmpty() || pending.property == "name") &&
            foldIntoPreviousCreate(state.entries, pending.box, pending.property, pending.to)
        ) {
            state.lastRecordedFrame = pending.lastFrame
            state.dirty = true
            return
        }
        if (mergePendingEditIntoPrevious(state, pending)) {
            state.lastRecordedFrame = pending.lastFrame
            state.dirty = true
            return
        }
        appendWaitIfNeeded(state, pending.lastFrame)
        if (mergePendingEditIntoPrevious(state, pending)) {
            state.lastRecordedFrame = pending.lastFrame
            state.dirty = true
            return
        }
        val index = state.entries.size
        state.entries += editEntry(pending.box, pending.property, pending.from, pending.to, pending.origin)
        state.lastRecordedFrame = pending.lastFrame
        val appendLog =
            "append #$index edit ${pending.box}/${pending.property} from=${pending.from.length} chars to=${pending.to.length} chars frame=${pending.lastFrame}"
        println("[operation-transcript] $appendLog")
        lprintln("info,operation-transcript", appendLog)
    }

    private fun editEntry(box: String, property: String, from: String, to: String, origin: String = ""): LinkedHashMap<String, Any?> =
        linkedMapOf(
            "edit" to linkedMapOf<String, Any?>(
                "box" to box,
                "property" to property,
                "from" to from,
                "to" to to
            ).also { if (origin.isNotBlank()) it["origin"] = origin }
        )

    private fun moveEntry(box: String, from: Rect, to: Rect): LinkedHashMap<String, Any?> =
        linkedMapOf(
            "move" to linkedMapOf(
                "box" to box,
                "from" to rectMap(from),
                "to" to rectMap(to)
            )
        )

    private fun mergePendingEditIntoPrevious(state: DocumentState, pending: PendingEdit): Boolean {
        val editIndex = previousEditableIndexFor(state.entries, pending.box, pending.property) ?: return false
        // Never across a turn boundary, and never across hands: a person's edit and an AI turn's edit of the
        // same property stay two entries, so undoing one (a rewound turn) leaves the other alone.
        if (editIndex < state.mergeBarrier) return false
        @Suppress("UNCHECKED_CAST")
        val payload = state.entries[editIndex]["edit"] as? MutableMap<String, Any?> ?: return false
        if ((payload["origin"]?.toString() ?: "") != pending.origin) return false
        payload["to"] = pending.to
        removeTrailingWaitsAfter(state.entries, editIndex)
        val mergeLog =
            "merge #$editIndex edit ${pending.box}/${pending.property} from=${payload["from"]?.toString()?.length ?: 0} chars to=${pending.to.length} chars frame=${pending.lastFrame}"
        println("[operation-transcript] $mergeLog")
        lprintln("info,operation-transcript", mergeLog)
        return true
    }

    private fun previousEditableIndexFor(
        entries: List<Map<String, Any?>>,
        box: String,
        property: String
    ): Int? {
        var index = entries.lastIndex
        while (index >= 0) {
            val entry = entries[index]
            if (entry.containsKey("wait")) {
                index--
                continue
            }
            val payload = entry["edit"] as? Map<*, *> ?: return null
            val entryBox = payload["box"]?.toString().orEmpty()
            val entryProperty = payload["property"]?.toString().orEmpty()
            return if (entryBox == box && entryProperty == property) index else null
        }
        return null
    }

    private fun mergeMoveIntoPrevious(state: DocumentState, box: String, to: Rect): Boolean {
        val moveIndex = previousMoveIndexFor(state.entries, box) ?: return false
        @Suppress("UNCHECKED_CAST")
        val payload = state.entries[moveIndex]["move"] as? MutableMap<String, Any?> ?: return false
        payload["to"] = rectMap(to)
        removeTrailingWaitsAfter(state.entries, moveIndex)
        val mergeLog = "merge #$moveIndex move $box to=${rectSummary(to)}"
        println("[operation-transcript] $mergeLog")
        lprintln("info,operation-transcript", mergeLog)
        return true
    }

    private fun previousMoveIndexFor(
        entries: List<Map<String, Any?>>,
        box: String
    ): Int? {
        var index = entries.lastIndex
        while (index >= 0) {
            val entry = entries[index]
            if (entry.containsKey("wait")) {
                index--
                continue
            }
            val payload = entry["move"] as? Map<*, *> ?: return null
            val entryBox = payload["box"]?.toString().orEmpty()
            return if (entryBox == box) index else null
        }
        return null
    }

    private fun removeTrailingWaitsAfter(entries: MutableList<LinkedHashMap<String, Any?>>, editIndex: Int) {
        var index = entries.lastIndex
        while (index > editIndex) {
            if (entries[index].containsKey("wait")) entries.removeAt(index) else return
            index--
        }
    }

    private fun coalesceOperationRuns(entries: List<LinkedHashMap<String, Any?>>): List<LinkedHashMap<String, Any?>> {
        val out = mutableListOf<LinkedHashMap<String, Any?>>()
        entries.forEach { entry ->
            val editPayload = entry["edit"] as? Map<*, *>
            if (editPayload != null) {
                val box = editPayload["box"]?.toString().orEmpty()
                val property = editPayload["property"]?.toString().orEmpty()
                val previous = previousEditableIndexFor(out, box, property)
                if (previous == null) {
                    out += deepLinkedMap(entry)
                } else {
                    @Suppress("UNCHECKED_CAST")
                    val previousPayload = out[previous]["edit"] as? MutableMap<String, Any?> ?: run {
                        out += deepLinkedMap(entry)
                        return@forEach
                    }
                    previousPayload["to"] = editPayload["to"]?.toString().orEmpty()
                    removeTrailingWaitsAfter(out, previous)
                }
                return@forEach
            }

            val movePayload = entry["move"] as? Map<*, *>
            if (movePayload != null) {
                val box = movePayload["box"]?.toString().orEmpty()
                val previous = previousMoveIndexFor(out, box)
                if (previous == null) {
                    out += deepLinkedMap(entry)
                } else {
                    @Suppress("UNCHECKED_CAST")
                    val previousPayload = out[previous]["move"] as? MutableMap<String, Any?> ?: run {
                        out += deepLinkedMap(entry)
                        return@forEach
                    }
                    previousPayload["to"] = deepLinkedMap(movePayload["to"])
                    removeTrailingWaitsAfter(out, previous)
                }
                return@forEach
            }

            out += deepLinkedMap(entry)
        }
        return out
    }

internal fun withoutIdleWaits(entries: List<LinkedHashMap<String, Any?>>): List<LinkedHashMap<String, Any?>>

A recording's waits, less the ones that are only the person's pauses. A wait right after an execute or launch is kept — what the code started may need the time — and every other wait goes, so a macro replays at once instead of at the speed it was performed (the 2026-10-20 audit recording opened with 784 frames, thirteen seconds, of nothing).

body — 241 lines, from line 1496
    internal fun withoutIdleWaits(entries: List<LinkedHashMap<String, Any?>>): List<LinkedHashMap<String, Any?>> =
        entries.filterIndexed { index, entry ->
            if (!entry.containsKey("wait")) return@filterIndexed true
            val previous = entries.getOrNull(index - 1)?.keys?.firstOrNull()?.lowercase()
            val next = entries.getOrNull(index + 1)
            next != null && previous != null && (previous in launchVerbs || previous in setOf("execute", "execute-fragment"))
        }

    private fun appendWaitIfNeeded(state: DocumentState, frame: Long) {
        val previous = state.lastRecordedFrame ?: return
        val delta = frame - previous
        if (delta >= WAIT_THRESHOLD_FRAMES) {
            state.entries += linkedMapOf("wait" to linkedMapOf("frames" to delta))
        }
    }

    private fun stateFor(documentPath: String): DocumentState =
        states.computeIfAbsent(normalizeDocumentPath(documentPath)) { DocumentState(documentPath = it) }

    private fun transcriptSnapshot(documentPath: String): List<LinkedHashMap<String, Any?>> {
        val state = stateFor(documentPath)
        return synchronized(state.lock) {
            ensureLoaded(state)
            flushPendingEdit(state)
            state.entries.map { deepLinkedMap(it) }
        }
    }

    private fun transcriptEntry(index: Int, entry: Map<String, Any?>): TranscriptEntry {
        val verb = entry.keys.firstOrNull().orEmpty()
        val payload = entry.values.firstOrNull() as? Map<*, *> ?: emptyMap<Any?, Any?>()
        val boxId = if (verb.lowercase() in setOf("marker", "wait")) {
            ""
        } else {
            (payload["box"] ?: payload["uid"] ?: payload["id"] ?: payload["target"])?.toString().orEmpty()
        }
        val property = (payload["property"] ?: payload["prop"])?.toString().orEmpty()
        // A connection's two ends travel as from/to, so the panel can name both boxes.
        val from = (payload["from"] ?: payload["parent"])?.toString().orEmpty()
        val to = (payload["to"] ?: payload["child"])?.toString().orEmpty()
        val frame = when {
            verb == "wait" -> payload["frames"]?.toString().orEmpty()
            verb == "marker" -> payload["runloopFrame"]?.toString().orEmpty()
            else -> payload["frame"]?.toString().orEmpty()
        }
        val at = payload["at"]?.toString().orEmpty()
        fun compactValue(value: String): String {
            val compact = value
                .lineSequence()
                .map { it.trim() }
                .filter { it.isNotEmpty() }
                .joinToString(" ")
                .ifBlank { "empty" }
            return if (compact.length > 48) compact.take(45).trimEnd() + "..." else compact
        }
        val summary = when (verb.lowercase()) {
            "edit", "set", "set-string" -> {
                buildString {
                    append("edit")
                    if (property.isNotBlank()) append(" ").append(property)
                    if (boxId.isNotBlank()) append(" of ").append(boxId)
                    append(" to ").append(compactValue(to))
                }
            }
            "move", "frame", "set-rect" -> if (boxId.isBlank()) "move" else "move $boxId"
            "execute", "execute-fragment" -> {
                buildString {
                    append("execute")
                    val type = (payload["type"] ?: "fragment").orEmptyString()
                    if (type.isNotBlank() && type != property) append(" ").append(type)
                    if (property.isNotBlank()) append(" ").append(property)
                    if (boxId.isNotBlank()) append(" of ").append(boxId)
                }
            }
            "launch", "launch-all", "launch-fragment" -> {
                buildString {
                    append("launch")
                    val type = (payload["type"] ?: "").orEmptyString()
                    if (type.isNotBlank() && type != "launch" && type != property) append(" ").append(type)
                    if (property.isNotBlank()) append(" ").append(property)
                    if (boxId.isNotBlank()) append(" of ").append(boxId)
                    val strand = (payload["strand"] ?: "").orEmptyString()
                    if (strand.isNotBlank() && strand != "default") append(" strand ").append(strand)
                }
            }
            "stop", "stop-all", "stop-box" -> if (boxId.isBlank()) "stop" else "stop $boxId"
            "connect" -> "connect ${(payload["parent"] ?: payload["from"] ?: payload["source"] ?: payload["box"]).orEmptyString()} -> ${(payload["child"] ?: payload["to"] ?: payload["target"]).orEmptyString()}"
            "disconnect" -> "disconnect ${(payload["parent"] ?: payload["from"] ?: payload["source"] ?: payload["box"]).orEmptyString()} -> ${(payload["child"] ?: payload["to"] ?: payload["target"]).orEmptyString()}"
            "create", "new-box", "box" -> "create ${(payload["box"] ?: payload["uid"] ?: payload["id"] ?: payload["target"]).orEmptyString()} ${(payload["name"] ?: "").orEmptyString()}".trim()
            "delete", "tombstone" -> "delete ${(payload["box"] ?: payload["uid"] ?: payload["id"] ?: payload["target"]).orEmptyString()}".trim()
            "wait" -> {
                val millis = payload["millis"] ?: payload["ms"]
                if (millis != null) {
                    "wait ${millis}ms"
                } else {
                    val frames = payload["frames"]?.toString() ?: "?"
                    "wait $frames ${if (frames.toLongOrNull() == 1L) "frame" else "frames"}"
                }
            }
            "marker" -> "marker ${(payload["kind"] ?: "").orEmptyString()} ${(payload["label"] ?: "").orEmptyString()}".trim()
            "drive", "drive-ui", "playwright" -> {
                val out = (payload["video"] ?: payload["screenshot"] ?: "").orEmptyString()
                if (out.isBlank()) "drive UI" else "drive UI -> $out"
            }
            else -> verb.ifBlank { "entry" }
        }
        return TranscriptEntry(
            index = index,
            verb = verb,
            summary = summary,
            yaml = writeYamlList(listOf(entry)),
            box = boxId,
            property = property,
            from = from,
            to = to,
            frame = frame,
            at = at,
            selectable = verb.lowercase() !in setOf("wait", "marker")
        )
    }

    private fun ensureLoaded(state: DocumentState) {
        if (state.loaded) return
        state.loaded = true
        val file = operationTranscriptFile(state.documentPath)
        if (!file.exists()) return
        runCatching {
            val loaded = Yaml().load<Any?>(file.readText())
            val entries = loaded as? List<*> ?: return@runCatching
            state.entries += entries.mapNotNull { mapOfStringAny(it) }
            state.lastRecordedFrame = null
        }.onFailure {
            lprintln("warning,operation-transcript", "Failed to read operation transcript ${file.absolutePath}: ${it.message}")
        }
    }

    private fun operationTranscriptFile(documentPath: String): File =
        File(normalizeDocumentPath(documentPath), SavingContext.OPERATIONS_YAML)

    private fun appendMarker(documentPath: String, kind: String, label: String, selection: List<String> = emptyList()) {
        val state = stateFor(documentPath)
        synchronized(state.lock) {
            ensureLoaded(state)
            flushPendingEdit(state)
            state.entries += markerEntry(kind, label, UUID.randomUUID().toString(), Runloop.runLoop.frame, selectionEntries(selection))
            state.dirty = true
        }
    }

    private fun markerEntry(
        kind: String,
        label: String,
        id: String,
        frame: Long,
        selection: List<LinkedHashMap<String, Any?>> = emptyList()
    ): LinkedHashMap<String, Any?> {
        val marker = linkedMapOf<String, Any?>(
            "kind" to kind,
            "label" to label,
            "id" to id,
            "runloopFrame" to frame,
            "at" to Instant.now().toString()
        )
        if (selection.isNotEmpty()) marker["selection"] = selection
        return linkedMapOf(
            "marker" to marker
        )
    }

    private fun markerKind(entry: Map<String, Any?>): String? =
        (entry["marker"] as? Map<*, *>)?.get("kind")?.toString()

    private fun markerSelection(entry: Map<String, Any?>): List<LinkedHashMap<String, Any?>> {
        val marker = entry["marker"] as? Map<*, *> ?: return emptyList()
        val raw = marker["selection"] as? List<*> ?: return emptyList()
        return raw.mapNotNull { mapOfStringAny(it) }
    }

    private fun selectionEntries(selection: List<String>): List<LinkedHashMap<String, Any?>> =
        selection.filter { it.isNotBlank() }.distinct().map { uid ->
            val name = runCatching { box(uid, createIfMissing = false).name }.getOrDefault("")
            linkedMapOf(
                "uid" to uid,
                "name" to name
            )
        }

    private fun normalizeDocumentPath(documentPath: String): String =
        File(documentPath).absolutePath

    private fun currentDocumentPath(): String? =
        runCatching { thisSessionInfo.get()?.filename }.getOrNull()?.let(::normalizeDocumentPath)

    private fun documentMacrosDir(documentPath: String): File =
        File(normalizeDocumentPath(documentPath), MACROS_DIR)

    private fun workspaceMacrosDir(documentPath: String): File {
        val documentDir = File(normalizeDocumentPath(documentPath)).canonicalFile
        val workspace = documentDir.parentFile ?: documentDir
        return File(workspace, MACROS_DIR)
    }

    private fun projectMacrosDir(documentPath: String, projectName: String): File {
        val documentDir = File(normalizeDocumentPath(documentPath)).canonicalFile
        val workspace = documentDir.parentFile ?: documentDir
        return File(File(projectsDir(workspace.absolutePath), projectName), MACROS_DIR)
    }

    private fun macroLocation(documentPath: String, scope: String, projectName: String = ""): MacroLocation? {
        return when {
            scope.equals("project", ignoreCase = true) -> {
                val project = projectForDocument(documentPath, projectName) ?: return null
                MacroLocation("project", project.name, projectMacrosDir(documentPath, project.name))
            }
            scope.equals("workspace", ignoreCase = true) -> MacroLocation("workspace", "", workspaceMacrosDir(documentPath))
            else -> MacroLocation("document", "", documentMacrosDir(documentPath))
        }
    }

    private fun projectForDocument(documentPath: String, requestedProject: String = ""): ProjectEntry? {
        val documentDir = File(normalizeDocumentPath(documentPath)).canonicalFile
        val workspace = documentDir.parentFile ?: return null
        val documentName = documentDir.name
        val projects = runCatching { listWorkspaceProjects(workspace.absolutePath) }.getOrDefault(emptyList())
        val cleanRequested = requestedProject.trim()
        return if (cleanRequested.isNotEmpty()) {
            projects.firstOrNull { it.name == cleanRequested }
        } else {
            projects.firstOrNull { project -> project.documents.any { it == documentName } }
        }
    }

    private fun macroNames(dir: File): List<String> =
        dir.takeIf { it.exists() }
            ?.listFiles { file -> file.isFile && file.extension.lowercase() in setOf("yaml", "yml") }
            ?.filterNot { isInternalMacro(it) }
            ?.map { it.nameWithoutExtension }
            ?.sorted()
            .orEmpty()

    private val internalMacroMarker = Regex("""(?m)^internal:\s*true\s*$|^\s*\{.*"internal"\s*:\s*true""")

internal fun isInternalMacro(file: File): Boolean

A macro with a top-level internal: true (in YAML, or "internal":true in a one-line JSON transcript) is plumbing, not something a person saved: the docs runner's capture drives and test fixtures. It still runs by name; it is left out of every macro list (the Macro Recorder panel, the palette's Run macro entries, macro list).

body — 106 lines, from line 1744
    internal fun isInternalMacro(file: File): Boolean =
        runCatching {
            file.bufferedReader().use { reader ->
                val head = CharArray(4096)
                val n = reader.read(head)
                n > 0 && internalMacroMarker.containsMatchIn(String(head, 0, n))
            }
        }.getOrDefault(false)

    private fun macroFile(location: MacroLocation, name: String): File =
        File(location.dir, sanitizeMacroName(name) + ".yaml")

    private fun sanitizeMacroName(name: String): String =
        name.trim()
            .replace(Regex("[^A-Za-z0-9_.-]+"), "-")
            .trim('-', '.', '_')

    private fun writeMacroYaml(
        name: String,
        documentPath: String,
        operations: List<Map<String, Any?>>,
        sourceSelection: List<Map<String, Any?>> = emptyList()
    ): String =
        buildString {
            append("name: ")
            append(formatScalar(name))
            append("\ncreated: ")
            append(formatScalar(Instant.now().toString()))
            append("\ndocument: ")
            append(formatScalar(File(documentPath).name))
            if (sourceSelection.isNotEmpty()) {
                append("\nsourceSelection:\n")
                sourceSelection.forEach { selection ->
                    append("  -\n")
                    appendYamlValue(selection, indent = 4)
                }
            }
            append("\noperations:\n")
            operations.forEach { entry ->
                entry.forEach { (key, value) ->
                    append("  - ")
                    append(key)
                    append(":\n")
                    appendYamlValue(value, indent = 6)
                }
            }
        }

    private fun documentPathFor(box: Box): String? {
        val path = if (box.isInsideInitialized()) {
            box.inside.filename
        } else {
            runCatching { thisSessionInfo.get()?.filename }.getOrNull()
        }
        return path?.let(::normalizeDocumentPath)
    }

    private fun rectMap(rect: Rect): Map<String, Any?> = linkedMapOf(
        "x" to rect.x,
        "y" to rect.y,
        "w" to rect.w,
        "h" to rect.h
    )

    private fun rectSummary(rect: Rect): String =
        "${rect.x},${rect.y}+${rect.w}x${rect.h}"

    private fun mapOfStringAny(value: Any?): LinkedHashMap<String, Any?>? {
        val map = value as? Map<*, *> ?: return null
        val out = linkedMapOf<String, Any?>()
        map.forEach { (key, entryValue) ->
            if (key is String) {
                out[key] = when (entryValue) {
                    is Map<*, *> -> mapOfStringAny(entryValue)
                    is List<*> -> entryValue.map { item -> if (item is Map<*, *>) mapOfStringAny(item) else item }
                    else -> entryValue
                }
            }
        }
        return out
    }

    private fun deepLinkedMap(value: Any?): LinkedHashMap<String, Any?> {
        val source = value as? Map<*, *> ?: return linkedMapOf()
        val out = linkedMapOf<String, Any?>()
        source.forEach { (key, entryValue) ->
            if (key is String) {
                out[key] = when (entryValue) {
                    is Map<*, *> -> deepLinkedMap(entryValue)
                    is List<*> -> entryValue.map { item -> if (item is Map<*, *>) deepLinkedMap(item) else item }
                    else -> entryValue
                }
            }
        }
        return out
    }

    private fun loadMacroOperations(file: File): List<LinkedHashMap<String, Any?>> {
        val loaded = Yaml().load<Any?>(file.readText())
        val rawOps = when (loaded) {
            is List<*> -> loaded
            is Map<*, *> -> (loaded["operations"] as? List<*>) ?: (loaded["ops"] as? List<*>) ?: emptyList<Any?>()
            else -> emptyList()
        }
        return rawOps.mapNotNull { mapOfStringAny(it) }
    }

The box a macro "is about", which a run on a selection maps to the selected box. A box the macro creates itself is never that box: mapping a create onto the selection would rename and move the selected box instead of making a new one.

    private fun firstOperationBox(operations: List<Map<String, Any?>>): String? {
        val created = createdBoxes(operations)
        return operations.asSequence()
            .filter { operationVerb(it) !in createVerbs }
            .mapNotNull { op ->
                val payload = op.values.firstOrNull() as? Map<*, *> ?: return@mapNotNull null
                (payload["box"] ?: payload["uid"] ?: payload["id"] ?: payload["target"])?.toString()
            }
            .firstOrNull { it !in created }
    }

    private val createVerbs = setOf("create", "new-box", "box")

internal fun createdBoxes(operations: List<Map<String, Any?>>): Set<String>

The uids a macro's own create operations make.

    internal fun createdBoxes(operations: List<Map<String, Any?>>): Set<String> =
        operations.asSequence()
            .filter { operationVerb(it) in createVerbs }
            .mapNotNull { op ->
                val payload = op.values.firstOrNull() as? Map<*, *> ?: return@mapNotNull null
                (payload["box"] ?: payload["uid"] ?: payload["id"] ?: payload["target"])?.toString()
            }
            .toSet()

internal fun relocateOperations

The operations of a macro rewritten for a replay "as a copy": every box the macro creates gets a fresh uid (consistently, wherever the macro names it), and every frame those boxes are given — at creation or by a later move — is shifted by (dx, dy). Boxes the macro did not create keep their uids and frames. Replaying the result twice makes two copies side by side instead of re-editing one; replaying it with fresh = false and no offset is the macro as recorded.

body — 42 lines, from line 1887
    internal fun relocateOperations(
        operations: List<Map<String, Any?>>,
        fresh: Boolean,
        dx: Double,
        dy: Double,
        newUid: () -> String = { UUID.randomUUID().toString() },
    ): List<LinkedHashMap<String, Any?>> {
        val created = createdBoxes(operations)
        val renames = if (fresh) created.associateWith { newUid() } else emptyMap()
        fun shifted(rect: Any?): Any? {
            val map = rect as? Map<*, *> ?: return rect
            if (dx == 0.0 && dy == 0.0) return deepLinkedMap(map)
            return deepLinkedMap(map).also {
                it["x"] = (it["x"].asDoubleOrNull() ?: 0.0) + dx
                it["y"] = (it["y"].asDoubleOrNull() ?: 0.0) + dy
            }
        }
        val boxKeys = setOf("box", "uid", "id", "target", "parent", "child", "from", "to", "source")
        return operations.map { op ->
            val verb = op.keys.firstOrNull() ?: return@map deepLinkedMap(op)
            val payload = deepLinkedMap(op.values.firstOrNull())
            val subject = (payload["box"] ?: payload["uid"] ?: payload["id"] ?: payload["target"])?.toString()
            val lowered = verb.lowercase()
            if (lowered in createVerbs) {
                payload["frame"]?.let { payload["frame"] = shifted(it) }
                payload["rect"]?.let { payload["rect"] = shifted(it) }
            } else if (lowered in setOf("move", "frame", "set-rect") && subject in created) {
                listOf("from", "to", "frame", "value").forEach { key -> payload[key]?.let { payload[key] = shifted(it) } }
            }
            val keys = if (lowered == "connect" || lowered == "disconnect") boxKeys else boxKeys - setOf("from", "to")
            keys.forEach { key ->
                val value = payload[key]
                if (value is String) renames[value]?.let { payload[key] = it }
            }
            linkedMapOf<String, Any?>(verb to payload)
        }
    }

    private val launchVerbs = setOf("launch", "launch-all", "launch-fragment")

    private fun operationVerb(operation: Map<String, Any?>): String =
        operation.keys.firstOrNull()?.lowercase().orEmpty()

The box an operation names (a connect's child), for its latency span; null for wait, await, save.

source — 579 lines, from line 1931
    private fun operationBoxName(operation: Map<String, Any?>): String? {
        val payload = operation.values.firstOrNull() as? Map<*, *> ?: return null
        return (payload["box"] ?: payload["uid"] ?: payload["id"] ?: payload["target"] ?: payload["child"])?.toString()
    }

    private fun applyMacroOperation(
        operation: Map<String, Any?>,
        boxMap: Map<String, String>,
        direction: String,
        strict: Boolean,
        context: MacroReplayContext = MacroReplayContext(),
        collect: (Message) -> Unit = {}
    ): Boolean {
        val verb = operation.keys.firstOrNull()?.lowercase() ?: return false
        val payload = operation.values.firstOrNull() as? Map<*, *> ?: return false
        fun mappedBox(): Box? {
            val raw = (payload["box"] ?: payload["uid"] ?: payload["id"] ?: payload["target"])?.toString() ?: return null
            val mapped = boxMap[raw] ?: raw
            return runCatching { box(mapped, createIfMissing = false) }.getOrNull()
        }

        return when (verb) {
            "edit", "set", "set-string" -> {
                val target = mappedBox() ?: return false
                val property = (payload["property"] ?: payload["prop"] ?: "code").toString()
                val recordedFrom = payload["from"]?.toString().orEmpty()
                val recordedTo = payload["to"]?.toString()
                    ?: payload["value"]?.toString()
                    ?: payload["text"]?.toString()
                    ?: return false
                val current = if (property == "name") target.name else target.getPropertyRaw(property)?.toString().orEmpty()
                val next = transformText(
                    current = current,
                    expected = if (direction == "undo") recordedTo else recordedFrom,
                    replacement = if (direction == "undo") recordedFrom else recordedTo,
                    strict = strict
                ) ?: return false
                if (property == "name") target.name = next else target.setPropertyRaw(property, next, doResync = true)
                true
            }
            "move", "frame", "set-rect" -> {
                val target = mappedBox() ?: return false
                val frameValue = payload[if (direction == "undo") "from" else "to"] ?: payload["frame"] ?: payload["value"] ?: return false
                val frameMap = frameValue as? Map<*, *> ?: return false
                target.frame = rectFromMap(frameMap)
                true
            }
            "create", "new-box", "box" -> {
                val raw = (payload["box"] ?: payload["uid"] ?: payload["id"] ?: payload["target"])?.toString() ?: return false
                val mapped = boxMap[raw] ?: raw
                if (mapped == "root" || mapped == METAROOT_ID) return false
                val info = thisSessionInfo.get()
                val target = box(
                    mapped,
                    createIfMissing = true,
                    initIfCreated = context.initializeCreatedBoxes,
                    root = info,
                )
                if (direction == "undo") {
                    tombstoneBox(target)
                    return true
                }
                (payload["name"] ?: payload["title"])?.toString()?.let { target.name = it }
                target.setPropertyRaw("_tombstone", false, doResync = true)
                val frameMap = (payload["frame"] ?: payload["rect"]) as? Map<*, *>
                if (frameMap != null) target.frame = rectFromMap(frameMap)
                (payload["properties"] as? Map<*, *>)?.forEach { (key, value) ->
                    val property = key?.toString()?.takeIf { it.isNotBlank() } ?: return@forEach
                    if (value != null) target.setPropertyRaw(property, value, doResync = true)
                }
                info.root.connect(target)
                needsResync.add(info.root to "children")
                needsResync.add(target to "parents")
                needsResync.add(info.root to "actions")
                needsResync.add(target to "actions")
                target.resyncAll()
                info.topologyGeneration++
                true
            }
            "delete", "tombstone" -> {
                val target = mappedBox() ?: return false
                if (target.id == "root" || target.id == METAROOT_ID) return false
                if (direction == "undo") {
                    val info = thisSessionInfo.get()
                    target.setPropertyRaw("_tombstone", false, doResync = true)
                    info.root.connect(target)
                    target.resyncAll()
                    info.topologyGeneration++
                } else {
                    tombstoneBox(target)
                }
                true
            }
            "connect", "disconnect" -> {
                val parentRaw = (payload["parent"] ?: payload["from"] ?: payload["source"] ?: payload["box"])?.toString() ?: return false
                val childRaw = (payload["child"] ?: payload["to"] ?: payload["target"])?.toString() ?: return false
                val parent = runCatching { box(boxMap[parentRaw] ?: parentRaw, createIfMissing = false) }.getOrNull() ?: return false
                val child = runCatching { box(boxMap[childRaw] ?: childRaw, createIfMissing = false) }.getOrNull() ?: return false
                val action = if (direction == "undo") {
                    if (verb == "connect") "disconnect" else "connect"
                } else verb
                if (action == "connect") {
                    parent.connect(child)
                    if (payload["nested"] == true) child.nestedIn = parent
                } else {
                    if (payload["nested"] == true && child.nestedIn === parent) child.nestedIn = null
                    parent.disconnect(child)
                }
                true
            }
            "execute", "execute-fragment" -> {
                if (direction == "undo") return false
                refreshMainLanguageRuntimes(thisSessionInfo.get().boxes.values)
                val target = mappedBox() ?: return false
                val exec = executeFromPayload(verb, target.id, payload, fallbackType = "fragment")
                // Await completion (like the launch path) so the fragment's output is
                // captured into the run result — fire-and-forget stalls headlessly.
                checkedMacroExecution(target, exec, collect) { reply ->
                    runBlocking { target.ke.executeFragmentAndWait(target, exec, reply) }
                }
                true
            }
            // Drive the attached Playwright page with an arbitrary Kotlin script (the
            // script gets a `ui: DocsUiDriver` in scope via fromContext), optionally
            // recording an .mp4 of the interaction and/or a final still. This is how docs
            // pages regenerate live UI captures (autocomplete, palettes, ...).
            "drive", "drive-ui", "playwright" -> {
                if (direction == "undo") return false
                val script = (payload["script"] ?: payload["code"])?.toString()
                    ?.takeIf { it.isNotBlank() } ?: return false
                val info = thisSessionInfo.get()

                // Attach the headless capture page (no-op if already healthy).
                runBlocking(playwrightDispatcher) { ensurePlaywrightForSessionIfNeeded(info) }
                val page = globalPlaywriteContext
                    ?: throw IllegalStateException("drive: Playwright is not active")

                // Host the script in a stable hidden box (reused across drives), unless
                // the op explicitly targets one. Publish the driver so `fromContext` finds it.
                val target = mappedBox()
                    ?: box("__docs_drive__", createIfMissing = true, initIfCreated = true, root = info)
                val driver = DocsUiDriver { globalPlaywriteContext ?: error("Playwright page unavailable") }
                driver.session = info
                target.properties["__docsUiDriver"] = driver

                // Completion/autocomplete captures trigger a real Ctrl+Space against this freshly
                // created box. The completion runs on the main runloop, but the driver fragment
                // below also runs there and pumps the runloop while it waits — so the K1 completion
                // delegate MUST already be built by the time the scripted completion fires. If its
                // heavy first bootstrap fired from inside the pumped wait it would re-enter the K1
                // engine mid-compile and corrupt it. Warm it here first, on the non-reentrant
                // runloop, so the scripted completion is a light, safe, reused compile. Gated: only
                // completion captures pay the warm-up cost.
                if (payload["warmCompletion"].asBooleanOrDefault(false)) {
                    val warmMs = measureTimeMillis {
                        runCatching {
                            runBlocking { inMain { target.ki.warmCompletion() }.join() }
                        }.onFailure {
                            lprintln("warning,docs", "drive warmCompletion failed: ${it.javaClass.simpleName}: ${it.message}")
                        }
                    }
                    lprintln("info,docs", "drive warmCompletion for box=${target.id} took ${warmMs}ms")
                    // ...and then the backend that will actually SERVE it. Warming K1 alone is how every
                    // completion figure in the docs came to be a picture of the fallback: the AA sidecar
                    // answers "session building" for the first seconds of its life, `complete` falls
                    // through to K1 exactly as designed, and the capture records that. Off the runloop —
                    // this waits on HTTP, and the runloop is what the driver pumps.
                    val backendMs = measureTimeMillis {
                        runCatching {
                            runBlocking { target.ki.warmCompletionBackend() }
                        }.onSuccess {
                            lprintln("info,docs", "drive warmCompletionBackend for box=${target.id}: $it")
                        }.onFailure {
                            lprintln(
                                "warning,docs",
                                "drive warmCompletionBackend failed: ${it.javaClass.simpleName}: ${it.message}"
                            )
                        }
                    }
                    lprintln("info,docs", "drive warmCompletionBackend for box=${target.id} took ${backendMs}ms")
                }

                val videoPath = payload["video"]?.toString()?.takeIf { it.isNotBlank() }
                val screenshotPath = payload["screenshot"]?.toString()?.takeIf { it.isNotBlank() }
                val fps = payload["fps"].asIntOrDefault(30)
                val capture = (payload["capture"] ?: "window-editor").toString().ifBlank { "window-editor" }
                val padding = payload["padding"]?.asDoubleOrNull() ?: 16.0
                val captureUid = (payload["captureUid"] ?: payload["captureBox"])?.toString()?.takeIf { it.isNotBlank() }
                    ?: if (capture == "box" || capture == "editor" || capture == "window-editor") target.id else null
                // Clip to an arbitrary overlay (command palette, popup, AI panel) that is not a box.
                val clipSelector = payload["clipSelector"]?.toString()?.takeIf { it.isNotBlank() }
                // Clip to a fixed CSS-px rectangle of the viewport (a fence's clip="x,y,w,h"), for a
                // frame no single element owns: a box and its editor, or a scene under the drawing
                // layer's toolbar. Used for the recording and, with no clipSelector, for the still,
                // which is then taken as the page stands rather than after a screenshot re-prep.
                val clipRect = (payload["clipRect"] as? List<*>)
                    ?.mapNotNull { (it as? Number)?.toDouble() ?: it?.toString()?.toDoubleOrNull() }
                    ?.takeIf { it.size == 4 && it[2] > 0.0 && it[3] > 0.0 }
                    ?.let { Rect(it[0], it[1], it[2], it[3]) }

                // Prepend the driver binding + resolved output paths (fully-qualified, so no
                // import is required in the doc fence body). Scripts capture transient overlays
                // with `ui.shotClip(out, ".selector")`. The extra prelude lines shift error
                // line numbers, but keep them off the author's first line.
                fun kstr(s: String?) = "\"" + (s ?: "").replace("\\", "\\\\").replace("\"", "\\\"") + "\""
                val prelude = "val ui: afield.tools.docs.DocsUiDriver = afield.document.context.fromContext(); " +
                    "val out: String = ${kstr(screenshotPath)}; val vid: String = ${kstr(videoPath)}; ui.scriptStarted()\n"
                // For an overlay still (clipSelector) capture inside the fragment, while the
                // overlay is still open — it closes on blur before the op's finally runs.
                val trailer = if (clipSelector != null && screenshotPath != null)
                    "\nui.shotClip(out, ${kstr(clipSelector)}, $padding)" else ""
                val exec = Execute(
                    uid = target.id,
                    type = "fragment",
                    line = 0,
                    code = prelude + script + trailer,
                    singleLine = false,
                    property = "code",
                    strand = "default"
                )

                // viewport=[w, h]: lay the page out at this size for the drive (Field's layout follows
                // the window), restored in the finally below, after the still is taken.
                val requestedViewport = (payload["viewport"] as? List<*>)
                    ?.mapNotNull { (it as? Number)?.toInt() ?: it?.toString()?.toDoubleOrNull()?.toInt() }
                    ?.takeIf { it.size == 2 && it[0] > 0 && it[1] > 0 }
                val originalViewport = if (requestedViewport != null) {
                    runBlocking(playwrightDispatcher) {
                        // A page with no fixed viewport is restored to the capture page's own size.
                        val before = page.viewportSize()
                            ?: com.microsoft.playwright.options.ViewportSize(PLAYWRIGHT_VIEWPORT_WIDTH, PLAYWRIGHT_VIEWPORT_HEIGHT)
                        page.setViewportSize(requestedViewport[0], requestedViewport[1])
                        before
                    }.also {
                        // Let the frontend's resize handlers lay the canvas and editor out again.
                        val until = System.currentTimeMillis() + 800L
                        while (System.currentTimeMillis() < until) {
                            if (Runloop.isMainThread) Runloop.runLoop.main.frame()
                            Thread.sleep(5L)
                        }
                    }
                } else null

                // hideToasts: Field's toasts (notify.js) stay on screen once shown, and in the small
                // window a `viewport=` drive uses they stack over the canvas the recording is of,
                // covering the keypress display's caption among other things. Hidden by a style
                // added before the first frame and removed in the finally below; nothing is dismissed.
                val hideToasts = payload["hideToasts"].asBooleanOrDefault(false)
                if (hideToasts) {
                    runCatching {
                        runBlocking(playwrightDispatcher) {
                            page.evaluate(
                                "() => { if (document.getElementById('docs-capture-hide-toasts')) return;" +
                                    " const s = document.createElement('style'); s.id = 'docs-capture-hide-toasts';" +
                                    " s.textContent = '.bubble.field-toast { visibility: hidden !important; }';" +
                                    " document.head.appendChild(s); }"
                            )
                        }
                    }.onFailure { throw IllegalStateException("drive: could not hide the toasts: ${it.message}", it) }
                }

                val recorder = if (videoPath != null) {
                    val clip = runCatching {
                        runBlocking(playwrightDispatcher) {
                            if (clipRect != null) clipRect
                            else if (clipSelector != null) computeSelectorClip(page, clipSelector, padding)
                                ?: computeDriveClip(page, capture, captureUid, padding)
                            else computeDriveClip(page, capture, captureUid, padding)
                        }
                    }.getOrNull()
                    // clipAtEnd: measure the frame when the recording stops, for a box that grows
                    // while the drive runs (a recordToggle opens its curve under the panel).
                    val clipAtEnd = if (payload["clipAtEnd"].asBooleanOrDefault(false) && clipRect == null) {
                        { computeDriveClip(page, capture, captureUid, padding) }
                    } else null
                    DocsUiRecorder(page, clip, fps, clipAtEnd).also { driver.recorder = it; it.start() }
                } else null

                try {
                    checkedMacroExecution(target, exec, collect) { reply ->
                        runBlocking { target.ke.executeFragmentAndWait(target, exec, reply) }
                    }
                    check(driver.clipFailures.isEmpty()) {
                        "drive: clip selector(s) matched nothing visible, so no clipped still was written: " +
                            driver.clipFailures.joinToString(", ")
                    }
                } finally {
                    // A script that filmed its own video (ui.filmCanvasFlight) has written videoPath already.
                    if (recorder != null && videoPath != null && !recorder.discarded) {
                        val frames = runBlocking { recorder.stopAndEncode(java.nio.file.Path.of(videoPath)) }
                        lprintln("info,docs", "drive recorded $frames frames -> $videoPath")
                    }
                    // A clipSelector still is captured by the script itself (ui.shotClip(out, sel))
                    // while the overlay is open — overlays close on blur before this finally runs.
                    if (screenshotPath != null && clipSelector == null) {
                        runBlocking(playwrightDispatcher) {
                            when {
                                clipRect != null -> captureClippedScreenshot(page, java.nio.file.Path.of(screenshotPath), clipRect)
                                capture == "box" -> captureBoxScreenshot(
                                    info,
                                    AgentBoxScreenshot(uid = captureUid ?: target.id, path = screenshotPath, padding = padding)
                                )
                                else -> captureWindowScreenshot(
                                    info,
                                    AgentWindowScreenshot(
                                        path = screenshotPath,
                                        uid = captureUid,
                                        showEditor = capture == "editor" || capture == "window-editor",
                                        editorOnly = capture == "editor",
                                        padding = padding
                                    )
                                )
                            }
                        }
                    }
                    if (hideToasts || driver.keypressDisplayTouched) {
                        runCatching {
                            runBlocking(playwrightDispatcher) {
                                page.evaluate(
                                    "() => { document.getElementById('docs-capture-hide-toasts')?.remove();" +
                                        " window.fieldKeycast?.disable({ quiet: true }); }"
                                )
                            }
                        }.onFailure {
                            lprintln("warning,docs", "drive: could not restore the toasts or keypress display: ${it.message}")
                        }
                    }
                    if (originalViewport != null) {
                        runCatching {
                            runBlocking(playwrightDispatcher) {
                                page.setViewportSize(originalViewport.width, originalViewport.height)
                            }
                        }.onFailure {
                            lprintln("warning,docs", "drive: could not restore the viewport: ${it.message}")
                        }
                    }
                    target.properties.remove("__docsUiDriver")
                }
                true
            }
            "launch", "launch-all", "launch-fragment" -> {
                if (direction == "undo") {
                    val target = mappedBox() ?: return false
                    Server.stop(target, "transcript-undo-launch")
                    return true
                }
                // Route through the group path so an unresolved box / empty code becomes a
                // loud, logged diagnostic instead of a silent skip.
                val (applied, _) = applyMacroLaunchGroup(listOf(operation to context), boxMap, collect)
                applied > 0
            }
            "stop", "stop-all", "stop-box" -> {
                if (direction == "undo") return false
                val target = mappedBox() ?: return false
                Server.stop(target, "transcript-stop")
                true
            }
            "wait" -> {
                if (direction == "undo") return false
                val explicitMillis = payload["millis"]?.asLongOrDefault(-1L)
                    ?: payload["ms"]?.asLongOrDefault(-1L)
                    ?: payload["seconds"]?.asDoubleOrNull()?.let { (it * 1000.0).toLong() }
                val frames = payload["frames"]?.asLongOrDefault(-1L)
                if (explicitMillis != null && explicitMillis >= 0L) {
                    waitForMacroMillis(explicitMillis.coerceIn(0L, 30_000L))
                } else if (frames != null && frames >= 0L) {
                    waitForRunloopFrames(frames.coerceIn(0L, 30_000L))
                }
                if (payload["pending"].asBooleanOrDefault(false)) awaitPending(payload)
                true
            }
            // Barrier op: wait for all previously-fired executeFragments to finish and
            // launches to reach their first frame, so their output is captured/observable.
            "await", "sync", "settle", "wait-pending" -> {
                if (direction == "undo") return false
                awaitPending(payload)
                true
            }
            // Persist the current (transient) document's boxes as a metadata.edn document
            // at the given path, so an agent can save the assembled scene if desired.
            "save", "save-document", "save-as" -> {
                if (direction == "undo") return false
                val path = (payload["path"] ?: payload["to"] ?: payload["fn"] ?: payload["document"])
                    ?.toString()?.takeIf { it.isNotBlank() } ?: return false
                val info = thisSessionInfo.get()
                val boxes = info.boxes.values
                    .filter { it.id != "root" && it.id != METAROOT_ID && !it.getPropertyRaw("_tombstone").isTrue() }
                    .toSet()
                val latch = java.util.concurrent.CountDownLatch(1)
                SavingContext().save(path, boxes, onComplete = { latch.countDown() })
                check(latch.await(30, java.util.concurrent.TimeUnit.SECONDS)) {
                    "`$verb` timed out after 30 seconds waiting for SavingContext to complete `$path`"
                }
                true
            }
            "marker" -> false
            else -> false
        }
    }

    private fun applyMacroLaunchGroup(
        operations: List<Pair<Map<String, Any?>, MacroReplayContext>>,
        boxMap: Map<String, String>,
        collect: (Message) -> Unit = {},
        diagnostics: MutableList<String>? = null
    ): Pair<Int, Int> {
        refreshMainLanguageRuntimes(thisSessionInfo.get().boxes.values)

        // Resolve every op explicitly. A launch that can't find its box or has no code
        // to run is a loud, specific failure (logged + notified + surfaced in `errors`),
        // never a silent skip — this is the documented execution verb, so it must be
        // obvious when it does nothing.
        val launches = mutableListOf<MacroLaunchRequest>()
        var skipped = 0
        operations.forEach { (operation, context) ->
            when (val resolution = resolveLaunch(operation, boxMap, context)) {
                is LaunchResolution.Ready -> launches.add(resolution.request)
                is LaunchResolution.Failed -> {
                    skipped++
                    lprintln("error,operation-transcript", "macro launch failed: ${resolution.reason}")
                    diagnostics?.add(resolution.reason)
                    notify(resolution.reason, "macro-launch-error")
                }
                LaunchResolution.NotLaunch -> skipped++
            }
        }
        if (launches.isEmpty()) return 0 to operations.size

        // Reject unresolved prerequisites before launching anything in the group.
        if (skipped > 0) return 0 to operations.size
        var applied = 0
        for (launch in launches) {
            val result = runCatching {
                send(Message("clear-editor-outputs").payload(ClearEditorOutputs(launch.target.id)))
                notifyMacroLaunch(launch.target, launch.exec, launch.context)
                checkedMacroExecution(launch.target, launch.exec, collect) { reply ->
                    if (launch.target.ke is KotlinExecution) {
                        runBlocking { KotlinExecution.launchBatchAndWait(listOf(launch.target to launch.exec), reply) }
                    } else {
                        // Preserve the ordinary engine's launch path. The result below marks
                        // dispatch separately; only Kotlin currently promises awaited setup.
                        launch.target.ke.launchAll(launch.target, launch.exec, launch.exec.code, launch.exec.strand, reply)
                    }
                }
            }
            if (result.isFailure) {
                val failure = result.exceptionOrNull()!!
                if (diagnostics == null) throw failure
                diagnostics.add(failure.message ?: failure.javaClass.name)
                return applied to operations.size - applied
            }
            applied++
        }
        return applied to skipped
    }

    private fun checkedMacroExecution(
        target: Box,
        exec: Execute,
        collect: (Message) -> Unit,
        execute: ((Message) -> Unit) -> Unit
    ) {
        val verdict = ExecutionVerdict(target.id, exec.property, exec.code)
        execute { message ->
            verdict.observe(message)
            send(message)
            collect(message)
        }
        verdict.check()
        if (target.ke !is KotlinExecution) {
            collect(Message("execution-dispatched").payload(ExecutionReport(
                target.id, exec.property, sourceRevision(exec.code), mode = "macro",
                stage = "dispatched", success = true
            )))
        }
    }

    private sealed interface LaunchResolution {
        data class Ready(val request: MacroLaunchRequest) : LaunchResolution
        data class Failed(val reason: String) : LaunchResolution
        object NotLaunch : LaunchResolution
    }

    private fun resolveLaunch(
        operation: Map<String, Any?>,
        boxMap: Map<String, String>,
        context: MacroReplayContext
    ): LaunchResolution {
        val verb = operation.keys.firstOrNull()?.lowercase() ?: return LaunchResolution.NotLaunch
        if (verb !in launchVerbs) return LaunchResolution.NotLaunch
        val payload = operation.values.firstOrNull() as? Map<*, *>
            ?: return LaunchResolution.Failed("`$verb` op has no payload map")
        val raw = (payload["box"] ?: payload["uid"] ?: payload["id"] ?: payload["target"])?.toString()
            ?: return LaunchResolution.Failed("`$verb` op is missing a box id (expected `box`, `uid`, `id`, or `target`)")
        val mapped = boxMap[raw] ?: raw
        val info = thisSessionInfo.get()
        val target = info.boxes[mapped]
            ?: return LaunchResolution.Failed(
                "`$verb` target box `$mapped` is not present in the document${describePresentBoxes(info)}"
            )
        val exec = executeFromPayload(verb, target.id, payload, fallbackType = payload["type"]?.toString() ?: "launch")
        if (exec.code.isBlank()) {
            return LaunchResolution.Failed(
                "`$verb` target box `$mapped` has no code to run: neither the op nor the box's " +
                    "`${exec.property}` property carries any code"
            )
        }
        return LaunchResolution.Ready(MacroLaunchRequest(target, exec, context))
    }

    private fun describePresentBoxes(info: SessionInformation): String {
        val ids = info.boxes.keys.filter { it != "root" && it != METAROOT_ID }.sorted()
        return if (ids.isEmpty()) {
            " (no user boxes are loaded — check the document/workspace path: `--document` is resolved relative to the workspace root)"
        } else {
            " (present: ${ids.joinToString(", ")})"
        }
    }

    private fun notifyMacroLaunch(target: Box, execute: Execute, context: MacroReplayContext) {
        val macro = context.macroName.ifBlank { "macro" }
        val launchProgress = if (context.launchIndex > 0 && context.launchCount > 0) {
            " ${context.launchIndex}/${context.launchCount}"
        } else {
            ""
        }
        val operationProgress = if (context.operationIndex > 0 && context.operationCount > 0) {
            " op ${context.operationIndex}/${context.operationCount}"
        } else {
            ""
        }
        val strand = execute.strand.ifBlank { "default" }
        val property = execute.property.ifBlank { "code" }
        val label = target.name.ifBlank { target.id.take(8) }
        val message = "Macro '${escapeNotifyText(macro)}' launch$launchProgress$operationProgress: " +
            "${escapeNotifyText(label)}.${escapeNotifyText(property)} strand ${escapeNotifyText(strand)}"
        val notifyMessage = Message("notify").payload(Notify(message, "macro-launch"))
        val documentPath = documentPathFor(target)
        if (documentPath == null) {
            notify(message, "macro-launch")
        } else {
            _send(notifyMessage, document = Regex.escape(documentPath))
        }
        lprintln(
            "info,operation-transcript",
            "macro launch name=$macro launchIndex=${context.launchIndex}/${context.launchCount} " +
                "op=${context.operationIndex}/${context.operationCount} box=${target.id} property=$property strand=$strand"
        )
    }

    private fun escapeNotifyText(text: String): String =
        text.replace("&", "&amp;")
            .replace("<", "&lt;")
            .replace(">", "&gt;")

    private fun tombstoneBox(target: Box) {
        if (target.id == "root" || target.id == METAROOT_ID) return
        val info = thisSessionInfo.get()
        if (target.nestedIn != null) {
            target.nestedIn = null
        }
        target.setPropertyRaw("_tombstone", true, doResync = true)
        info.root.disconnect(target)
        needsResync.add(info.root to "children")
        needsResync.add(target to "parents")
        needsResync.add(info.root to "actions")
        needsResync.add(target to "actions")
        info.topologyGeneration++
    }

    private fun describeMacroFailure(failure: Throwable): String {
        val detail = failure.message?.takeIf { it.isNotBlank() }
        if (detail != null) return "${failure.javaClass.simpleName}: $detail"
        // A message-less throwable — ConcurrentModificationException, a bare NPE, the
        // InterruptedException waitForMacroMillis works around — used to reduce to nothing but its
        // class name, so a transcript replay failure reached CI with no way to locate it. Those are
        // exactly the concurrency faults that need a frame, and they are the ones with no message.
        return failure.javaClass.name + describeOrigin(failure)
    }

First few non-JDK frames of failure, for throwables that carry no message.

    private fun describeOrigin(failure: Throwable, frames: Int = 4): String {
        val trace = failure.stackTrace ?: return ""
        val interesting = trace.filterNot {
            it.className.startsWith("java.") || it.className.startsWith("kotlin.")
        }.take(frames)
        val shown = if (interesting.isNotEmpty()) interesting else trace.take(frames).toList()
        if (shown.isEmpty()) return ""
        return shown.joinToString(prefix = " at ", separator = " <- ") {
            "${it.className.substringAfterLast('.')}.${it.methodName}:${it.lineNumber}"
        }
    }

    private fun waitForMacroMillis(millis: Long) {
        if (millis <= 0L) return
        // Macro playback runs on Dispatchers.IO. Coroutine delay avoids inheriting
        // a transient interrupt from compilation/launch work on a reused worker,
        // which made otherwise successful waits fail with a message-less
        // InterruptedException.
        runBlocking { delay(millis) }
    }

    private fun waitForRunloopFrames(frames: Long) {
        if (frames <= 0L) return
        val target = Runloop.runLoop.frame + frames
        runBlocking {
            withTimeout(30_000L) {
                while (Runloop.runLoop.frame < target) delay(1L)
            }
        }
    }

Barrier: advance runloop frames until every previously-fired executeFragment has finished (no box still has _currentlyExecutingFragment), holding for a couple of settle frames so launches reach their first rendered frame. Bounded by maxFrames. Pumping frames (not Thread.sleep) is what lets the queued inMain fragment work run and its output flow back through the collect reply into the run result.

    private fun awaitPending(payload: Map<*, *>) {
        val info = runCatching { thisSessionInfo.get() }.getOrNull() ?: return
        val maxFrames = payload["maxFrames"]?.asLongOrDefault(-1L)?.takeIf { it >= 0L } ?: 600L
        val settleFrames = payload["settleFrames"]?.asLongOrDefault(-1L)?.takeIf { it >= 0L } ?: 2L
        val startFrame = Runloop.runLoop.frame
        var idle = 0L
        while (Runloop.runLoop.frame - startFrame < maxFrames) {
            val anyFragment = info.boxes.values.any {
                runCatching { it._currentlyExecutingFragment }.getOrDefault(false)
            }
            val advanced = Runloop.runLoop.frame - startFrame
            if (!anyFragment) {
                idle++
                if (idle >= settleFrames && advanced >= 1L) break
            } else {
                idle = 0L
            }
            val before = Runloop.runLoop.frame
            while (Runloop.runLoop.frame == before && Runloop.runLoop.frame - startFrame < maxFrames) {
                Thread.sleep(1L)
            }
        }
    }

Capture box output/error messages (from execute/launch replies) so a transcript run can report what the boxes printed. Only "output" messages carry box stdout.

source — 224 lines, from line 2574
    private fun captureMacroOutput(message: Message, sink: MutableList<MacroOutputLine>) {
        if (message.name != "output") return
        val payload = message.payload as? JsonObject ?: return
        fun str(k: String) = (payload[k] as? JsonPrimitive)?.contentOrNull
        fun int(k: String) = (payload[k] as? JsonPrimitive)?.intOrNull
        val html = str("html")?.trim().orEmpty()
        if (html.isEmpty()) return
        sink.add(
            MacroOutputLine(
                uid = str("uid").orEmpty(),
                kind = str("kind") ?: "normal",
                line = int("line") ?: -1,
                html = html.take(8192)
            )
        )
    }

    private fun executeFromPayload(verb: String, uid: String, payload: Map<*, *>, fallbackType: String): Execute {
        val property = (payload["property"] ?: payload["prop"] ?: "code").toString()
        // A macro replays against the box as it is now: whole-box launches run the box's current
        // code, recorded fragments are found again in it (MacroReplayCode has the rules).
        val live = runCatching { box(uid, createIfMissing = false).getPropertyRaw(property) as? String }.getOrNull()
        val resolved = MacroReplayCode.resolve(verb, payload, live)
        resolved.note?.let { lprintln("info,operation-transcript", "macro `$verb` of `$uid`: $it") }
        return Execute(
            uid = uid,
            type = (payload["type"] ?: fallbackType).toString(),
            line = resolved.line,
            code = resolved.code,
            singleLine = payload["singleLine"].asBooleanOrDefault(false),
            property = property,
            strand = (payload["strand"] ?: "default").toString().ifBlank { "default" }
        )
    }

    private fun transformText(current: String, expected: String, replacement: String, strict: Boolean): String? {
        if (current == expected) return replacement
        val diff = changedMiddle(expected, replacement) ?: return if (strict) null else replacement
        val oldMiddle = diff.first
        val newMiddle = diff.second
        if (oldMiddle.isEmpty()) {
            if (current.startsWith(diff.third) && current.endsWith(diff.fourth)) {
                return diff.third + newMiddle + current.removePrefix(diff.third)
            }
            return if (strict) null else replacement
        }
        val first = current.indexOf(oldMiddle)
        if (first >= 0 && current.indexOf(oldMiddle, first + oldMiddle.length) < 0) {
            return current.replaceFirst(oldMiddle, newMiddle)
        }
        return if (strict) null else replacement
    }

    private fun changedMiddle(before: String, after: String): Quad<String, String, String, String>? {
        var prefix = 0
        val maxPrefix = minOf(before.length, after.length)
        while (prefix < maxPrefix && before[prefix] == after[prefix]) prefix++
        var suffix = 0
        val maxSuffix = minOf(before.length - prefix, after.length - prefix)
        while (suffix < maxSuffix && before[before.length - 1 - suffix] == after[after.length - 1 - suffix]) suffix++
        val beforeMiddle = before.substring(prefix, before.length - suffix)
        val afterMiddle = after.substring(prefix, after.length - suffix)
        val prefixText = before.substring(0, prefix)
        val suffixText = before.substring(before.length - suffix)
        return Quad(beforeMiddle, afterMiddle, prefixText, suffixText)
    }

    private data class Quad<A, B, C, D>(val first: A, val second: B, val third: C, val fourth: D)

    private fun Any?.orEmptyString(): String =
        this?.toString().orEmpty()

    private fun Any?.asDouble(): Double = when (this) {
        is Number -> toDouble()
        else -> toString().toDouble()
    }

    private fun Any?.asDoubleOrNull(): Double? = when (this) {
        is Number -> toDouble()
        null -> null
        else -> toString().toDoubleOrNull()
    }

    private fun Any?.asLongOrDefault(default: Long): Long = when (this) {
        is Number -> toLong()
        null -> default
        else -> toString().toLongOrNull() ?: default
    }

    private fun rectFromMap(frameMap: Map<*, *>): Rect =
        Rect(
            frameMap["x"].asDouble(),
            frameMap["y"].asDouble(),
            frameMap["w"].asDouble(),
            frameMap["h"].asDouble()
        )

    private fun Any?.asIntOrDefault(default: Int): Int = when (this) {
        is Number -> toInt()
        null -> default
        else -> toString().toIntOrNull() ?: default
    }

    private fun Any?.asBooleanOrDefault(default: Boolean): Boolean = when (this) {
        is Boolean -> this
        null -> default
        else -> toString().toBooleanStrictOrNull() ?: default
    }

    private fun writeYamlList(entries: List<Map<String, Any?>>): String {
        if (entries.isEmpty()) return "[]\n"
        return buildString {
            entries.forEach { entry ->
                entry.forEach { (key, value) ->
                    append("- ")
                    append(key)
                    append(":\n")
                    appendYamlValue(value, indent = 4)
                }
            }
        }
    }

    private fun StringBuilder.appendYamlValue(value: Any?, indent: Int) {
        val prefix = " ".repeat(indent)
        when (value) {
            is Map<*, *> -> value.forEach { (key, entryValue) ->
                append(prefix)
                append(key.toString())
                append(":")
                when {
                    entryValue is Map<*, *> -> {
                        append("\n")
                        appendYamlValue(entryValue, indent + 2)
                    }
                    entryValue is List<*> -> {
                        append("\n")
                        appendYamlValue(entryValue, indent + 2)
                    }
                    entryValue is String && shouldUseBlockScalar(key.toString(), entryValue) -> {
                        appendBlockScalar(entryValue, indent)
                    }
                    else -> {
                        append(" ")
                        append(formatScalar(entryValue))
                        append("\n")
                    }
                }
            }

            is List<*> -> {
                if (value.isEmpty()) {
                    append(prefix)
                    append("[]\n")
                } else {
                    value.forEach { item ->
                        append(prefix)
                        append("-")
                        when (item) {
                            is Map<*, *> -> {
                                append("\n")
                                appendYamlValue(item, indent + 2)
                            }
                            is List<*> -> {
                                append("\n")
                                appendYamlValue(item, indent + 2)
                            }
                            is String -> {
                                if (shouldUseBlockScalar(null, item)) {
                                    appendBlockScalar(item, indent)
                                } else {
                                    append(" ")
                                    append(formatScalar(item))
                                    append("\n")
                                }
                            }
                            else -> {
                                append(" ")
                                append(formatScalar(item))
                                append("\n")
                            }
                        }
                    }
                }
            }

            else -> {
                append(prefix)
                append(formatScalar(value))
                append("\n")
            }
        }
    }

    private fun shouldUseBlockScalar(key: String?, value: String): Boolean {
        if (value.isEmpty()) return false
        if (value.contains('\n')) return true
        val textKey = key?.lowercase() in setOf("from", "to", "value", "text", "code")
        return textKey || value.contains('"') || value.contains('\\')
    }

    private fun StringBuilder.appendBlockScalar(value: String, indent: Int) {
        val contentIndent = " ".repeat(indent + 2)
        val preservesFinalNewline = value.endsWith("\n")
        append(" ")
        append(if (preservesFinalNewline) "|" else "|-")
        append("\n")
        val body = if (preservesFinalNewline) value.dropLast(1) else value
        body.lines().forEach { line ->
            append(contentIndent)
            append(line)
            append("\n")
        }
    }

    private fun formatScalar(value: Any?): String = when (value) {
        null -> "null"
        is Number, is Boolean -> value.toString()
        else -> {
            val text = value.toString()
            if (text.isEmpty()) "\"\"" else "\"" + text.replace("\\", "\\\\").replace("\"", "\\\"") + "\""
        }
    }
}