Add runtime diagnostic logging for level setup, native Git calls, inspection, validation, and UI command flow

This commit is contained in:
Joe Tretter
2026-06-25 13:53:51 -05:00
parent 035851ac05
commit 60dd3c82f7
8 changed files with 215 additions and 53 deletions

View File

@@ -111,8 +111,10 @@ fun GitHugApp() {
}
LaunchedEffect(currentLevelIndex) {
AppLog.d("GitHugApp", "Current level index changed to $currentLevelIndex id=${levels[currentLevelIndex].id}")
delay(100)
screenScrollState.animateScrollTo(0)
AppLog.d("GitHugApp", "Scrolled to top for level index=$currentLevelIndex id=${levels[currentLevelIndex].id}")
}
fun updatePaneLayout(transform: (PaneLayout) -> PaneLayout, persist: Boolean = true) {
@@ -214,7 +216,9 @@ fun GitHugApp() {
}
fun resetCurrentLevel(message: String = "Level reset.") {
val startedAt = System.nanoTime()
val resetLevelId = currentLevel.id
AppLog.d("GitHugApp", "Reset requested level=$resetLevelId")
val updatedCompletedLevels = completedLevels - resetLevelId
completedLevels = updatedCompletedLevels
scope.launch { persistProgress(updatedCompletedLevels, resetLevelId) }
@@ -231,6 +235,10 @@ fun GitHugApp() {
gitMessageEditorState = null
manPageState = null
applyRecommendedPaneWeights(persist = false, outputLineCount = terminalOutputLineCount(listOf(message)))
AppLog.d(
"GitHugApp",
"Reset finished level=$resetLevelId durationMs=${elapsedMillisSince(startedAt)} repo=${repo.diagnosticSnapshot()}",
)
}
fun loadLevel(
@@ -239,6 +247,7 @@ fun GitHugApp() {
keepSuppressedImeEcho: Boolean = false,
prepareInBackground: Boolean = false,
) {
val startedAt = System.nanoTime()
val level = levels[index]
val requestId = levelLoadRequestId + 1
levelLoadRequestId = requestId
@@ -260,21 +269,46 @@ fun GitHugApp() {
if (prepareInBackground) {
isPreparingLevel = true
repo = RepoState()
AppLog.d(
"GitHugApp",
"Level load state updated index=$index id=${level.id} requestId=$requestId durationMs=${elapsedMillisSince(startedAt)} preparing=true",
)
scope.launch {
val prepareStartedAt = System.nanoTime()
AppLog.d("GitHugApp", "Background prepare started index=$index id=${level.id} requestId=$requestId")
val preparedRepo = withContext(Dispatchers.Default) {
runtime.prepareLevel(level)
}
val prepareMs = elapsedMillisSince(prepareStartedAt)
if (levelLoadRequestId == requestId) {
AppLog.d("GitHugApp", "Prepared level index=$index id=${level.id}")
AppLog.d(
"GitHugApp",
"Background prepare applying index=$index id=${level.id} requestId=$requestId prepareMs=$prepareMs " +
"repo=${preparedRepo.diagnosticSnapshot()}",
)
repo = preparedRepo
output = message
isPreparingLevel = false
clearCommandInput(recreateField = true)
AppLog.d(
"GitHugApp",
"Background prepare applied index=$index id=${level.id} requestId=$requestId totalMs=${elapsedMillisSince(startedAt)}",
)
} else {
AppLog.d(
"GitHugApp",
"Background prepare discarded index=$index id=${level.id} requestId=$requestId activeRequestId=$levelLoadRequestId prepareMs=$prepareMs",
)
}
}
} else {
isPreparingLevel = false
val prepareStartedAt = System.nanoTime()
repo = runtime.prepareLevel(level)
AppLog.d(
"GitHugApp",
"Synchronous prepare applied index=$index id=${level.id} prepareMs=${elapsedMillisSince(prepareStartedAt)}",
)
}
paneLayout = paneLayout.copy(
weights = paneLayout.weights + recommendedPaneWeights(
@@ -288,6 +322,10 @@ fun GitHugApp() {
),
)
)
AppLog.d(
"GitHugApp",
"Level load returned index=$index id=${level.id} requestId=$requestId durationMs=${elapsedMillisSince(startedAt)} preparing=$isPreparingLevel",
)
}
fun setCommandText(text: String) {
@@ -348,12 +386,14 @@ fun GitHugApp() {
}
fun applyCommandResult(raw: String, newRepo: RepoState, lines: List<String>, echoCommand: Boolean) {
val startedAt = System.nanoTime()
val levelForResult = currentLevel
val solvedAfterCommand = levelForResult.validator(newRepo, raw)
val wasAlreadyCompleted = currentLevel.id in completedLevels
AppLog.d(
"GitHugApp",
"Command='$raw' level=${levelForResult.id} solved=$solvedAfterCommand alreadyCompleted=$wasAlreadyCompleted completedBefore=${completedLevels.sorted()}",
"Command='$raw' level=${levelForResult.id} solved=$solvedAfterCommand alreadyCompleted=$wasAlreadyCompleted " +
"completedBefore=${completedLevels.sorted()} outputLineCount=${lines.size} repo=${newRepo.diagnosticSnapshot()}",
)
val newOutput = buildList {
addAll(output)
@@ -396,6 +436,10 @@ fun GitHugApp() {
output = newOutput
applyRecommendedPaneWeights(persist = false, outputLineCount = terminalOutputLineCount(newOutput))
}
AppLog.d(
"GitHugApp",
"Command result applied level=${levelForResult.id} solved=$solvedAfterCommand durationMs=${elapsedMillisSince(startedAt)}",
)
}
fun openEditor(invocation: VisualEditorInvocation) {
@@ -480,16 +524,23 @@ fun GitHugApp() {
}
fun runCommand() {
val startedAt = System.nanoTime()
val submittedText = commandInput.text
val raw = submittedText.trim()
if (raw.isBlank()) return
if (isPreparingLevel) {
AppLog.d("GitHugApp", "Command blocked while preparing level=${currentLevel.id} raw='$raw'")
output = output + "Still preparing ${currentLevel.title}. Try again in a moment."
clearCommandInput(recreateField = true)
applyRecommendedPaneWeights(persist = false, outputLineCount = terminalOutputLineCount(output))
return
}
val submittedLevelId = currentLevel.id
val isInteractiveInput = repo.interactiveAddSession != null
AppLog.d(
"GitHugApp",
"Command submitted level=$submittedLevelId raw='$raw' interactive=$isInteractiveInput repo=${repo.diagnosticSnapshot()}",
)
showHelpOverlay = false
showTerminalInputHint = false
@@ -529,6 +580,7 @@ fun GitHugApp() {
val (newRepo, lines) = runtime.execute(currentLevel, repo, raw)
applyCommandResult(raw, newRepo, lines, echoCommand = !isInteractiveInput)
AppLog.d("GitHugApp", "Command handling finished level=$submittedLevelId raw='$raw' durationMs=${elapsedMillisSince(startedAt)}")
}
fun showCommandHelp() {