{ "intent": "Bring focus_owner/android/app/src/main/kotlin/com/kuhy/focus_owner/EnforcementDecision.kt (274 lines) under the repo-wide 250-line cap with no change to which packages get hidden.", "scope": [ "focus_owner/.../EnforcementDecision.kt — reduced to the EnforcementDecision data class, evaluate, geofence and haversineMetres", "focus_owner/.../EnforcementTypes.kt — new: HideReason, Geofence, EnforcementReason, EnforcementInputs", "Non-goal: any change to the enforcement rules — the fail-closed LOCATION_UNKNOWN branch, the always-blocked exemption from AWAY and WORKOUT, and the hysteresis widening all keep their semantics exactly", "Non-goal: the other three over-cap Kotlin files, which this same measurement rules out (see risks)" ], "changes": [ "Moved the four value types the decision is expressed in — the two enums, the Geofence record and EnforcementInputs — into EnforcementTypes.kt, leaving the decision class and its pure evaluation logic behind.", "No import statement anywhere changed: Kotlin resolves same-package declarations across files, and both files are com.kuhy.focus_owner. That is why this split touches no consumer and no test.", "Declarations moved verbatim, including the comments recording why `fix` is never consulted by evaluate and why curfewActive is carried separately from reason." ], "verification": [ { "command": "JAVA_HOME=/usr/lib/jvm/java-21-openjdk ./gradlew test --rerun-tasks", "result": "pass", "evidence": "BUILD SUCCESSFUL. Per-class results unchanged: EnforcementDecisionCurfewTest 13, EnforcementDecisionTest 12, EnforcementLogTest 9, EnforcementRunnerBestTest 6 — 40 tests, 0 failures, 0 errors, matching the pre-split baseline exactly. --rerun-tasks was required because a plain `gradlew test` reported UP-TO-DATE from cache and would have proven nothing." }, { "command": "flutter test", "result": "pass", "evidence": "94 tests, all passed — unchanged. Run because the Flutter app ships this Kotlin, so a package-level mistake would surface here even though no Dart file was touched." }, { "command": "flutter analyze", "result": "pass", "evidence": "No issues found." }, { "command": "wc -l on both files", "result": "pass", "evidence": "EnforcementDecision.kt 221, EnforcementTypes.kt 63 — both under the 250-line cap, down from a single 274-line file." }, { "command": "Declaration reachability measurement, run before choosing this target", "result": "pass", "evidence": "A script comparing every fun/val/var declaration in each over-cap Kotlin file against the text of every file in app/src/test/kotlin/ gave: EnforcementDecision.kt 24/36 (66%), FocusPolicy.kt 15/42 (35%), EnforcementRunner.kt 15/47 (31%), DevicePolicyBridge.kt 1/28 (3%). Only this file has coverage strong enough for the test suite to be a real verifier of a split." }, { "command": "pre-commit run --files ", "result": "pass", "evidence": "All configured hooks pass on the two touched files." } ], "risks": [ "focus_owner has no CI workflow and no Kotlin linter — no jacoco, no ktlint, no detekt in the gradle files, and nothing kotlin-related in .pre-commit-config.yaml. So unlike the TypeScript splits in this series there is no lint-error-count check available; the 40 gradle tests plus the Flutter suite are the entire verifier.", "Coverage here is 66% of declarations, not 100%. The twelve unreferenced ones are mostly EnforcementInputs field names and the private haversine internals, which move as a block and are exercised transitively through evaluate — but a split that broke one of them in isolation would not necessarily be caught.", "The remaining three over-cap Kotlin files are deliberately NOT split. DevicePolicyBridge.kt at 3% is an Android DevicePolicyManager wrapper that JVM unit tests cannot reach; splitting it would move code no test executes, which is the same trap that ruled out the usage_report Python scripts at 21-47%." ], "rollback": [ "git revert the commit — one edited file and one added file, with no data, config or schema migration.", "After rollback, re-run gradlew test --rerun-tasks and flutter test; expect 40 and 94 tests passing respectively." ] }