Move SSD truth store filenames to typed Kotlin

ober

5aef2a15ca12f22d6a43f371dab4f00d899bb166

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 806ba11..d340697 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -1300,7 +1300,9 @@
                 StorageStats-files StorageStats-files-set!
                 StorageStats-bytes StorageStats-bytes-set!
                 storageSummaryText compressionRatioBudget boundedTreeReadLimit
-                boundedReadInitialCapacity mergedJsonLinesText)
+                boundedReadInitialCapacity mergedJsonLinesText
+                truthFileName reviewFileName eventsFileName
+                inputLimitExceededMessage outputLimitExceededMessage)
         (type Int32)
         (record ImportBudget
           ((mut entries : Int32)
@@ -1327,6 +1329,26 @@
           (minIntValue entryLimit remaining))
         (def (boundedReadInitialCapacity (limit : Int)) : Int
           (minIntValue limit (int 65536)))
+        (def (truthFileName (hash : String)) : String
+          (string-append
+            "truth-"
+            (string-append hash ".truth.json")))
+        (def (reviewFileName (hash : String)) : String
+          (string-append
+            "review-"
+            (string-append hash ".review.json")))
+        (def (eventsFileName (hash : String)) : String
+          (string-append
+            "events-"
+            (string-append hash ".events.jsonl")))
+        (def (inputLimitExceededMessage (limit : Int)) : String
+          (string-append
+            "Input exceeds "
+            (string-append (int->string limit) " bytes")))
+        (def (outputLimitExceededMessage (limit : Int)) : String
+          (string-append
+            "Output exceeds "
+            (string-append (int->string limit) " bytes")))
         (def (mergedJsonLinesText (lines : (Set String))) : String
           (joinStringSet
             lines
@@ -7499,7 +7521,7 @@
        "    fun truthPath(sourceKey: String): File {"
        "        val key = validatedSourceKey(sourceKey)"
        "            ?: throw IllegalArgumentException(\"Invalid source key\")"
-       "        return containedLeaf(groundTruthDir, \"truth-${sha256Hex(key.toByteArray())}.truth.json\")"
+       "        return containedLeaf(groundTruthDir, truthFileName(sha256Hex(key.toByteArray())))"
        "    }"
        ""
        "    fun loadTruth(sourceKey: String): JSONObject? {"
@@ -7554,10 +7576,10 @@
        "        atomicWriteText(truthFile, truth.toString(2))"
        "        invalidateTruthIndex()"
        "        val sessionId = truthSessionIdOr(truth, truthSourceKeyOrUnknown(sourceKey))"
-       "        val reviewFile = containedLeaf(reviewsDir, \"review-${sha256Hex(sessionId.toByteArray())}.review.json\")"
+       "        val reviewFile = containedLeaf(reviewsDir, reviewFileName(sha256Hex(sessionId.toByteArray())))"
        "        atomicWriteText(reviewFile, truth.toString(2))"
        "        val event = snapshotEventJson(sessionId, sourceKey, truthFile.name)"
-       "        appendJsonLine(containedLeaf(eventsDir, \"events-${sha256Hex(sessionId.toByteArray())}.events.jsonl\"), event)"
+       "        appendJsonLine(containedLeaf(eventsDir, eventsFileName(sha256Hex(sessionId.toByteArray()))), event)"
        "        appendJsonLine(containedLeaf(eventsDir, \"all-events.jsonl\"), event)"
        "        rebuildLearnedExamples()"
        "        pushTruthAsync(truth)"
@@ -7566,7 +7588,7 @@
        ""
        "    fun appendEvent(type: String, session: SsdSession, details: JSONObject = emptyJsonObject()) {"
        "        val event = sessionEventJson(type, session, details)"
-       "        appendJsonLine(containedLeaf(eventsDir, \"events-${sha256Hex(session.sessionId.toByteArray())}.events.jsonl\"), event)"
+       "        appendJsonLine(containedLeaf(eventsDir, eventsFileName(sha256Hex(session.sessionId.toByteArray()))), event)"
        "        appendJsonLine(containedLeaf(eventsDir, \"all-events.jsonl\"), event)"
        "    }"
        ""
@@ -7582,7 +7604,7 @@
        "        private fun account(amount: Int): Int {"
        "            if (amount > 0) {"
        "                count += amount.toLong()"
-       "                if (count > limit) throw IllegalStateException(\"Input exceeds $limit bytes\")"
+       "                if (count > limit) throw IllegalStateException(inputLimitExceededMessage(limit))"
        "            }"
        "            return amount"
        "        }"
@@ -7601,14 +7623,14 @@
        "            private set"
        ""
        "        override fun write(value: Int) {"
-       "            if (count + 1L > limit) throw IllegalStateException(\"Output exceeds $limit bytes\")"
+       "            if (count + 1L > limit) throw IllegalStateException(outputLimitExceededMessage(limit))"
        "            out.write(value)"
        "            count += 1L"
        "        }"
        ""
        "        override fun write(buffer: ByteArray, offset: Int, length: Int) {"
        "            if (length < 0 || count + length.toLong() > limit) {"
-       "                throw IllegalStateException(\"Output exceeds $limit bytes\")"
+       "                throw IllegalStateException(outputLimitExceededMessage(limit))"
        "            }"
        "            out.write(buffer, offset, length)"
        "            count += length.toLong()"
@@ -7625,7 +7647,7 @@
        "            if (read < 0) break"
        "            if (read == 0) continue"
        "            total += read.toLong()"
-       "            if (total > limit) throw IllegalStateException(\"Input exceeds $limit bytes\")"
+       "            if (total > limit) throw IllegalStateException(inputLimitExceededMessage(limit))"
        "            output.write(buffer, 0, read)"
        "        }"
        "        return output.toByteArray()"