# History — Period ``` Status: Current Owner: _null Last reviewed: 2026-08-18 Governs: the narrative of how this project got to where it is Review trigger: A decision reversed, a direction abandoned, or a rewrite ``` ## What this is for The story, in prose: what was tried, what was abandoned, and why. A reader arriving in six months wants to know which walls have already been walked into, and that is not something a commit log tells them. **This is a record of *then*, never a description of *now*.** That distinction is what makes it safe to leave alone as the project changes — a history document edited to stay current is not a history, it is a second and competing description of the present. If you find yourself updating a sentence here because the code changed, the sentence belongs somewhere else. ## Where this project started Period began as a single document. Before any repository existed there was one 2,500-line specification — product, privacy, prediction algorithm, screen copy, monetization and compliance — written to be handed to a coding agent whole. It is still here, unchanged in substance, as [`../planning/PRODUCT_PLAN.md`](../planning/PRODUCT_PLAN.md). That is worth recording because it explains a shape a newcomer would otherwise find odd: this repository has an unusually complete specification and no code. Most projects have the reverse problem. ## Decisions and their reasons One entry per decision that would otherwise look arbitrary later. The reason matters more than the decision: "we chose X" ages badly, "we chose X because Y was true at the time" survives Y stopping being true. | When | What was decided | Why, at the time | | --- | --- | --- | | 2026-08-18 | Kotlin and Jetpack Compose, not Java or XML | Android is Kotlin-first and Compose-first in Google's own current documentation; the alternative was legacy on arrival | | 2026-08-18 | Room, not files or SharedPreferences, for cycle history | history is structured, must survive app updates, and needs migrations that can be tested — the other options make a migration a hand-written parser | | 2026-08-18 | The prediction engine is a **pure Kotlin JVM module** | it is the product, so it needs the most tests; a module that cannot see the Android SDK gets tests that run in a second instead of tests that need an emulator | | 2026-08-18 | A robust personalized statistical model for V1, not a learned model | it is explainable, offline, fast, deterministic and testable, and the product promise is *personal*, not *neural*. A local ML model is a post-V1 option and only if it demonstrably beats this | | 2026-08-18 | WorkManager for reminders, and **no exact-alarm permission** | a period reminder does not need alarm-clock precision, and requesting that permission is a Play scrutiny cost with no user benefit | | 2026-08-18 | Ads stay behind an abstraction in a module that cannot reach cycle data | the privacy promise is the product; a rule people remember is not a control, a compile error is | | 2026-08-18 | One-time purchase to remove ads, not a subscription | it keeps prediction quality free for everyone and avoids an entire class of entitlement defect — nothing to claw back on cancellation | | 2026-08-18 | Six Gradle modules at the skeleton, not the seventeen the specification sketches | a module created before it has contents is a place for things to be put by accident; the rest arrive with the batch that needs them | | 2026-08-18 | Eight milestones opened at once, issues filed only under Batch 01 | the roadmap is genuinely known and worth being visible; the *work items* are not, and inventing them would make every tracker percentage permanently wrong | | 2026-08-18 | `OPERATIONS.md` deleted rather than kept empty | this is an offline app, not a deployed service; an empty runbook reads as one nobody wrote | ## What was tried and dropped Nothing yet. This is the most useful section in the file and the one most often missing — an approach abandoned for a good reason will be proposed again by somebody who does not know it was tried, including you, in a year. The specification already carries a partial version of it: every `Avoid:` and `Do not:` list in [`../planning/PRODUCT_PLAN.md`](../planning/PRODUCT_PLAN.md) is a decision made in advance rather than a lesson learned. When one of them turns out to be wrong, that reversal belongs here. ## What this file is not - **Not the plan.** That is [`../planning/PROJECT_PLAN.md`](../planning/PROJECT_PLAN.md). - **Not the work list.** Open work lives in the tracker as milestones and issues. - **Not a changelog.** Dated entries go in [`DEVELOPMENT_LOG.md`](DEVELOPMENT_LOG.md).