# 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).
