Phase 0 — Kozica opens on its own screen, in its own colours, with nothing of the template left
Sequence lives in PLAN.md; the live worklist lives in DOD.md. This phase
amends ADR-0003 (nothing schedules any more) and relies on
ADR-0006. CONTEXT.md is owed
nothing more: Region, Trail, Path, Hut and Shelter were settled before this phase opened, and no term
of its own appears on screen.
What closing this phase means. Today the app is the template: a tab bar around an Items list, reminders with their alarms and permissions, a slate-blue scheme. After this phase it opens on one screen that holds the map’s place, with Settings, Licences and Support behind an icon, in the chamois-ochre palette, in English and Polish. The difference a device can be asked about: the installed build declares none of the reminders’ permissions, and nothing on screen says “Item”.
0. What this phase inherits
- Version 0.1.0 on Play’s internal track, built from the template unchanged. Nothing has reached a stranger, so nothing is frozen yet.
minSdk26, deliberately kept: the only phone in the loop is API 36, so branches below it are exercised only by CI’s lowest-API legs until testers’ phones arrive.scripts/aab-permissions.py’s EXPECTED table still describes the template.
What is in, and what is deliberately not
In: deleting reminders, WorkManager and the rest of work/; deleting the Items screens, routes,
strings and tab bar, and the sample data that feeds them; a single home screen with an empty-map
placeholder and an icon to Settings; the ochre palette; aab-permissions.py and
scripts/edge-to-edge.py rewritten against what is left; the privacy policy and
play-app-content.md amended to match.
Not in, and each with a reason rather than a phase:
- The map. It is phases 1 and 2. This phase leaves its place empty rather than drawing anything temporary that a later phase would have to remove.
- The mark. Its concept is the owner’s to draw or generate, and it must not resemble the Tatra National Park’s chamois logo. The placeholder ships until then; the DOD item stays open.
- The support address. It waits for the dedicated account; the DOD item stays open.
ItemEntityas a table. It stays in the schema, dormant, with no screen reading it. Room cannot run with no entity, and the first real one — a planned route — arrives in phase 5. Only a debug build may drop the database (destructiveMigrationAllowed()), and Play installs already run 0.1.0, so phase 5 ships a realMIGRATION_1_2that dropsitemsand creates its own table, with all five items ofDOD.md’s standing schema gate. Deleting Room now and re-adding it then would cost more than a table nobody reads.- Backup in Settings. The code and the screen stay; the row leaves Settings until phase 6 gives it something of the user’s to keep, for the same reason a tab waits for the phase that fills it.
The tempting one is to put the three final tabs in now — Map, Routes, Hikes — so the shell never changes. Two of them would be empty through the whole closed test. A tab arrives with the phase that fills it (phase 5).
Checkpoints
| Checkpoint | Merges | Depends on | |
|---|---|---|---|
| A | Reminders gone — the code, the manifest entries, WorkManager, Settings’ section, the allowlist rows | refactor: |
— |
| B | Items gone, one screen — the Items UI and tab bar out, the empty-map home in, the debug seeding seam kept but seeding nothing | feat: |
— |
| C | The palette — four seeds in scripts/gen_scheme.py, regenerated, read on the phone in light and dark |
feat: |
— |
A and B are independent; both edit SettingsScreen.kt, so whichever merges second rebases. C goes
last so the palette is judged on the screen that will actually carry it rather than on the Items
list.
There is no gate. Nothing in this phase is unmeasured platform behaviour; the risk is a permission or a string left behind, which the readings below catch.
1. Reminders gone
docs/optional-modules.md § Reminders and WorkManager is the list, file by file. What it leaves
easy to miss:
- Six permissions leave the artifact:
POST_NOTIFICATIONS,RECEIVE_BOOT_COMPLETEDandSCHEDULE_EXACT_ALARM, which the manifest declares, andWAKE_LOCK,ACCESS_NETWORK_STATEandFOREGROUND_SERVICE, which WorkManager merges.aab-permissions.py’s EXPECTED loses all six in the same commit, andACCESS_NETWORK_STATEandACCESS_WIFI_STATEjoinINTERNETin FORBIDDEN, with ADR-0008 as the reason. - The rest of
work/goes too.Autostart.ktandBatteryExemption.ktserve only background work, andPLAN.mdrule 4 brings them back only on a reading. Thecom.miui.securitycenterentry in<queries>goes withAutostart.kt. Two helpers move out first:startActivitySafelytoui/common/, becauseui/support/SupportHandoff.ktuses it and phase 3’s hand-offs will; andschemaBlocksBackgroundWork()todata/, beside the gate, because ADR-0001 makes it the check every background entry point runs and phase 6’s recording service is the next one.SchemaGuard.kt’srebuildInBackgroundserves only the reminders’ receivers and goes with them. - Settings’ Reminders section is the template’s worked example of
PLAN.mdrule 4, and phase 2’s location ask copies its shape. After this checkpoint read it at10bf995:ui/settings/SettingsScreen.ktandwork/NotificationPermission.kt.
ADR-0003 gets a dated amendment: Kozica schedules nothing, and both mechanisms are gone.
2. Items gone, one screen
docs/optional-modules.md § The placeholder domain lists the files. The home screen is an empty
map placeholder — a neutral surface with the app name and one line of copy — and a top-bar icon to
Settings. scripts/edge-to-edge.py’s SCENES walk this screen and Settings, nothing else.
Debug seeding keeps its seam: SeedReceiver, Settings’ debug rows and the seed machinery in
edge-to-edge.py and screenshots.py stay, and SampleData.kt seeds nothing until phase 5 or 6
has data to put in it. Deleting the seam would mean rewriting both scripts now and again then. The
wipe row’s debug_wipe, “Delete all items”, becomes “Delete all data”, or R4 finds it.
Copy, English:
- Placeholder: “Your map will appear here.”
- Settings icon’s content description: “Settings”
3. The palette
Four seeds in scripts/gen_scheme.py:
| Seed | Hue |
|---|---|
| Primary | Chamois ochre, the summer coat |
| Secondary | Warm grey-brown, rock |
| Tertiary | Muted slate, dark enough to read as neither trail blue nor black |
| Neutral | Warm stone grey |
The constraint is the map, not taste. Red, blue, green, yellow and black are Trails. No role the
app paints over the map — the position dot, a selected control, a floating button — may read as one
of them, and each Trail colour must stay clearly visible on the map in light and dark. The Trail
colours themselves belong to the map style, not to MaterialTheme; phase 2 records that exception
to the house rule.
This phase cannot check the constraint, because there is no map yet. Phase 2 reads it: the position dot and the map controls over a yellow and a black Trail, in light and dark, and a seed changes if one fails.
Tests
None. This phase introduces no value that computes or bounds something safety-relevant (PLAN.md
rule 3).
Documents this phase amends
- ADR-0003: the amendment above.
CLAUDE.md: the WorkManager stack row,work/in the layout, and the environment note’s scheduled notifications.docs/privacy-policy.md: the notifications line goes with reminders, and point 2 of The three things that happen outside the app, the backups you export yourself, with the heading’s count, until phase 6 brings Backup back.docs/play-app-content.md: the reminder permissions’ rows, § Foreground service permissions and the reminders in the header comment, in the same commit as the policy.scripts/aab-permissions.py: EXPECTED, to what is left; FORBIDDEN, as in § 1, and the battery exemption row’s reason, which nameswork/BatteryExemption.kt.
Known gaps, deliberately
- The placeholder mark ships to internal testing. Nobody but the owner sees it before the door.
support@example.comstays compiled in until the dedicated account exists. No stranger has a build before phase 3, which owns the address. Since 2026-10-20 the developer Gmail is compiled in instead; the dedicated account is still open inDOD.md.
Readings
| # | Reading | Command | Result |
|---|---|---|---|
| R1 | The release bundle declares none of the six permissions in § 1 | ./gradlew bundleRelease && python3 scripts/aab-permissions.py |
2026-10-18, versionCode 13: one permission, AndroidX’s own DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION; none of the 8 forbidden ones |
| R2 | The app opens on the placeholder screen, in English and in Polish | ./gradlew installDebug, then adb shell cmd locale set-app-locales io.github.srednimax.kozica.debug --locales pl (and back with --locales ""), screenshots via adb exec-out screencap -p |
2026-10-18, versionCode 19 debug, Xiaomi 24115RA8EG: “Your map will appear here.” / “Tu pojawi się twoja mapa.” under the app name, Settings icon top right. The in-app picker itself was not tapped; the command sets the per-app locale it drives |
| R3 | The palette in light and dark, on the phone | ./gradlew installDebug, then adb shell cmd uimode night yes / no |
2026-10-18, same phone: warm stone surfaces in both; in dark, ochre section headers and warm-brown selected chips in Settings. The Trail constraint waits for phase 2 |
| R4 | Nothing says “Item” anywhere | grep -rniE '>[^<]*\bitems?\b' app/src/*/res/values*/strings.xml, and adb shell uiautomator dump of Home, Settings (top and bottom), Help and feedback, and Licences |
2026-10-18: the grep is empty; the dumps show no “item” in any label. The licence text screens were not walked; the grep covers their strings |