refactor(detekt): extract magic-number constants, wrap long lines, drop legit suppressions

Mechanical detekt cleanup across apps/core/infrastructure (behavior-preserving):
- MagicNumber 62->10: named constants + removed 'legit' MagicNumber suppressions
  (Tier level from ordinal, ReplayInferenceProvider CHARS_PER_TOKEN, ConfigLoader
  DEFAULT_* consts, capability scores, HTTP ranges, column widths, etc.)
- MaxLineLength cut to ~0 in production modules (line wraps, no logic change)
- Dropped one dead parameter (ConfigLoader.parseArray lineNum)

Structural findings (ReturnCount/LongMethod/Complexity/LargeClass) left for a
deliberate decomposition pass. Full build + detekt gate green.
This commit is contained in:
2026-07-12 23:12:28 +04:00
parent 135a34eb2f
commit aee2e67c66
70 changed files with 1034 additions and 236 deletions
@@ -39,9 +39,10 @@ class FileWriteTool(
private val normalizedAllowedPaths: Set<Path> = allowedPaths.map { it.normalize().toAbsolutePath() }.toSet()
override val name: String = "file_write"
override val description: String = "Write content to a file at the specified relative path (creates or overwrites). " +
"Writing to a nested path auto-creates any missing parent directories — there is no separate " +
"mkdir step. Do not write shell commands into a file's content."
override val description: String =
"Write content to a file at the specified relative path (creates or overwrites). " +
"Writing to a nested path auto-creates any missing parent directories — there is no separate " +
"mkdir step. Do not write shell commands into a file's content."
override val parametersSchema: JsonObject = buildJsonObject {
put("type", "object")
putJsonObject("properties") {
@@ -179,7 +179,9 @@ class ListDirTool(
private fun render(root: Path, entries: List<String>, truncated: Boolean, ignoredCount: Int): String {
val notes = buildList {
if (truncated) add("truncated at $MAX_ENTRIES entries; narrow the path or list a sub-directory")
if (ignoredCount > 0) add("$ignoredCount ${if (ignoredCount == 1) "entry" else "entries"} hidden by .gitignore")
if (ignoredCount > 0) {
add("$ignoredCount ${if (ignoredCount == 1) "entry" else "entries"} hidden by .gitignore")
}
}
return buildString {
appendLine("<path>$root</path>")
@@ -203,14 +205,14 @@ class ListDirTool(
.filter { it != targetName && isSimilarName(it, targetName) }
.toList()
.sortedWith(compareByDescending<String> { commonPrefixLen(it, targetName) }.thenBy { it })
.take(3)
.take(MAX_SIMILAR_SUGGESTIONS)
}
} catch (_: Exception) { emptyList() }
}
private fun isSimilarName(a: String, b: String): Boolean {
val prefix = commonPrefixLen(a, b)
return prefix >= 2 || levenshtein(a, b) <= 3
return prefix >= SIMILAR_NAME_MIN_COMMON_PREFIX || levenshtein(a, b) <= SIMILAR_NAME_MAX_LEVENSHTEIN
}
private fun commonPrefixLen(a: String, b: String): Int {
@@ -238,6 +240,9 @@ class ListDirTool(
private companion object {
const val MAX_ENTRIES = 400
const val MAX_SIMILAR_SUGGESTIONS = 3
const val SIMILAR_NAME_MIN_COMMON_PREFIX = 2
const val SIMILAR_NAME_MAX_LEVENSHTEIN = 3
}
}
@@ -35,6 +35,7 @@ private const val MAX_RESULTS = 200
// symbol search wants, and reading it line-by-line stalls the walk. ponytail: fixed byte cap; make it
// a param if a real use case needs to grep large generated files.
private const val GREP_MAX_FILE_BYTES = 2_000_000L
private const val GREP_LINE_PREVIEW_LENGTH = 200
/**
* `.gitignore`-aware path search by glob pattern — the affordance a model should reach for to answer
@@ -58,7 +59,10 @@ class GlobTool(
putJsonObject("properties") {
putJsonObject("pattern") {
put("type", "string")
put("description", "Glob pattern, e.g. '**/*.kt' or 'src/**/use*.ts'. Matched against paths relative to 'path'.")
put(
"description",
"Glob pattern, e.g. '**/*.kt' or 'src/**/use*.ts'. Matched against paths relative to 'path'.",
)
}
putJsonObject("path") {
put("type", "string")
@@ -80,13 +84,27 @@ class GlobTool(
return@withContext ToolResult.Failure(request.invocationId, it.reason, recoverable = false)
}
val pattern = (request.parameters["pattern"] as? String)?.takeIf { it.isNotBlank() }
?: return@withContext ToolResult.Failure(request.invocationId, "glob requires a non-empty 'pattern'", recoverable = true)
?: return@withContext ToolResult.Failure(
request.invocationId,
"glob requires a non-empty 'pattern'",
recoverable = true,
)
val base = resolveSearchPath(request, workingDir)
if (!Files.isDirectory(base)) {
return@withContext ToolResult.Failure(request.invocationId, "Not a directory: ${request.parameters["path"] ?: "."}", recoverable = true)
return@withContext ToolResult.Failure(
request.invocationId,
"Not a directory: ${request.parameters["path"] ?: "."}",
recoverable = true,
)
}
val matcher = runCatching { FileSystems.getDefault().getPathMatcher("glob:$pattern") }
.getOrElse { return@withContext ToolResult.Failure(request.invocationId, "Invalid glob pattern: ${it.message}", recoverable = true) }
.getOrElse {
return@withContext ToolResult.Failure(
request.invocationId,
"Invalid glob pattern: ${it.message}",
recoverable = true,
)
}
val hits = ArrayList<String>()
var truncated = false
@@ -147,16 +165,36 @@ class GrepTool(
return@withContext ToolResult.Failure(request.invocationId, it.reason, recoverable = false)
}
val patternStr = (request.parameters["pattern"] as? String)?.takeIf { it.isNotBlank() }
?: return@withContext ToolResult.Failure(request.invocationId, "grep requires a non-empty 'pattern'", recoverable = true)
?: return@withContext ToolResult.Failure(
request.invocationId,
"grep requires a non-empty 'pattern'",
recoverable = true,
)
val regex = runCatching { Regex(patternStr) }
.getOrElse { return@withContext ToolResult.Failure(request.invocationId, "Invalid regex: ${it.message}", recoverable = true) }
.getOrElse {
return@withContext ToolResult.Failure(
request.invocationId,
"Invalid regex: ${it.message}",
recoverable = true,
)
}
val base = resolveSearchPath(request, workingDir)
if (!Files.isDirectory(base)) {
return@withContext ToolResult.Failure(request.invocationId, "Not a directory: ${request.parameters["path"] ?: "."}", recoverable = true)
return@withContext ToolResult.Failure(
request.invocationId,
"Not a directory: ${request.parameters["path"] ?: "."}",
recoverable = true,
)
}
val fileFilter = (request.parameters["glob"] as? String)?.takeIf { it.isNotBlank() }?.let {
runCatching { FileSystems.getDefault().getPathMatcher("glob:$it") }
.getOrElse { e -> return@withContext ToolResult.Failure(request.invocationId, "Invalid glob: ${e.message}", recoverable = true) }
.getOrElse { e ->
return@withContext ToolResult.Failure(
request.invocationId,
"Invalid glob: ${e.message}",
recoverable = true,
)
}
}
val hits = ArrayList<String>()
@@ -169,7 +207,7 @@ class GrepTool(
if (text != null && !text.contains('\u0000')) {
text.lineSequence().forEachIndexed { idx, line ->
if (!truncated && regex.containsMatchIn(line)) {
hits += "$rel:${idx + 1}: ${line.trim().take(200)}"
hits += "$rel:${idx + 1}: ${line.trim().take(GREP_LINE_PREVIEW_LENGTH)}"
if (hits.size >= MAX_RESULTS) truncated = true
}
}
@@ -69,7 +69,8 @@ class WorkspaceSearchToolsTest {
fun `grep respects an optional file glob and prunes gitignore`(): Unit = runBlocking {
val root = fixture()
val tool = GrepTool(allowedPaths = setOf(root), workingDir = root)
val out = (tool.execute(request("grep", mapOf("pattern" to "useAuth", "glob" to "**/*.ts"))) as ToolResult.Success).output
val req = request("grep", mapOf("pattern" to "useAuth", "glob" to "**/*.ts"))
val out = (tool.execute(req) as ToolResult.Success).output
assertTrue(out.contains("src/hooks/useAuth.ts:"), out)
assertTrue(out.contains("src/main.ts:"), out)
assertFalse(out.contains("node_modules"), out) // gitignored