ADR index
An ADR (Architecture Decision Record) keeps a technical decision in the repo instead of scattering it across Issues and chat, so “why this shape” stays discoverable later. Expand a section below to read Decision, background, options, and consequences. The files under Docs/adr/ in git are the bilingual canonical source; when they diverge, Japanese wins.
Index
0001 — Keep app-related trees under App/ · Accepted · Issue #134
0002 — Split SPM targets into UI / Store / sources layers · Proposed · Issue #109
ADR-0001: Keep app-related trees under App/
Accepted · 2026-08-08 · Site out of scope · layout only, no behavior change
Fix the home for the app and verification artifacts as follows. Directories are renamed, not only moved — names like Sources / Tests read as “the whole repository’s sources,” which blurs scope.
App/
Tokfuel* … executable and libraries (was Tokfuel/Sources)
Tests/
UnitTests/ … what swift test runs
IntegrationTests/ … integration (later)
TestDocs/ … scenario design (not executed)
E2E/ … end-to-end implementations (not under swift test)
Keep the product tree separate from Site / Docs / Scripts. Leave room for TestDocs and E2E under the same App/ parent.
App code lived in Tokfuel/Sources and tests in Tokfuel/Tests, referenced from a single SPM target. We needed in-repo homes for scenario design and end-to-end tests (#134). Putting those at the root or in separate trees multiplies “where do I look?” for app work.
Scattered homes make contributors hunt for the right place and mix unrelated changes in one PR.
Without a decided parent for TestDocs / E2E, ad-hoc conventions appear and clash with later module splits.
Root-level or Tokfuel/Sources names do not clearly mean “the product tree.”
1 Status quo — TestDocs / E2E land elsewhere later; scatter and growth problems remain (rejected).
2 Top-level siblings — entry points align but sit next to Site / Docs (rejected).
3 Gather under App/ — one parent for app-related work; Site stays outside (adopted).
Discoverability, room to grow TestDocs / E2E, and fit with #109 (module split) favor option 3. Migration needs path updates but no behavior change.
One discovery entry for app-related work: App/.
Directory boundary between ops trees and product code.
Later module work can stay scoped as “inside the app.”
This decision does not cover relocating legal docs or renaming the repo root. Scope is App/ consolidation only. Full comparison tables live in the ADR files.
ADR-0002: Split SPM targets into UI / Store / sources layers
Proposed · 2026-08-08 · premise ADR-0001 · target boundaries, not another tree move
Stop using a single SPM target under App/. Split library targets by layer. Fix data flow and dependency direction as follows.
sources (Claude / Cursor / Codex / Budget …) … fetch; expose APIs that yield data
↓
Store … reshape in feature-named files; aggregate for UI
↓
UI … render what Store provides
Dependencies: UI → Store → sources
Concrete wiring: App (executable)
Split sources by fetch axis. Keep only cross-cutting types in a thin TokfuelCore.
In Store, keep source-specific shaping in feature-named files (e.g. CursorUsage.swift) and assemble what UI consumes.
UI sees Store (and thin display types) only — not SQLite, retok, or dashboard APIs.
Keep Firebase, retok resources, and sqlite3 inside the source / Analytics targets that use them.
Do not change product behavior or the ground rules (local-only data, zero setup, unmodified retok, optional python3, no new packages).
Do not adopt feature-vertical splits that close UI pieces inside each source. The natural cut is fetch → shape → present. Splitting Claude / Cursor under sources is the lower layer only; UI and Store stay layered, not source-vertical.
Fix today’s Cursor cost — fetch in TokfuelCursor, shape in Store’s Cursor file, presentation-only tweaks in TokfuelUI.
Popover padding / shared layout — TokfuelUI only. Leave Store / sources alone if data is unchanged.
Cursor row data path — Cursor fetches → Store shapes → UsageStore-like aggregation → PopoverView-like display.
After ADR-0001 gathered code under App/, there was still a single target: UI, Store, networking, and cost math shared one directory (#109). Feature-vertical splits were compared to reduce PR collisions, but real data flow is “sources fetch, Store shapes, UI presents,” and cross-cutting UI edits remain. That cut is a layer boundary.
Store / UI / driver roles are document-only; the compiler cannot enforce them.
It is hard to tell from directory names whether a change is fetch, shape, or present.
Cross-cutting UI work and source-specific fetch work collide in the same tree.
1 Status quo — boundary and clarity problems remain (rejected).
2 Layers — matches data flow and UI cross-cuts; sources split underneath (adopted).
3 Feature-vertical — helps source collisions but fights “fix UI together” (rejected).
4 Many micro-layers — clarity cost too high for this size (rejected).
5 Hybrid — vertical plus layers doubles boundary management (rejected).
Compile-time detection when UI reaches for SQLite or retok internals.
Clear change stories: fetch in Cursor target, shape in Store’s Cursor file, look in UI.
Store / UI can stay hotspots — split by feature-named and screen-named files; keep PRs small.
Untangle reverse deps (e.g. BudgetMonitor → UI) with callbacks / protocols before cutting targets.
How ADRs are written
One decision = one directory. Body filenames match the directory’s ID-slug. Both Japanese (.ja.md) and English (.md) are required. Bodies use Decision / Context / Consideration / Consequences / References; Consideration always includes the status-quo option.
Accepted — in force
Proposed / Draft — under discussion or review
Deprecated / Superseded / Rejected — kept for history
Large direction changes start as a GitHub Issue (label ADR), then land as an ADR once agreed. When you add an ADR or change its status, update the README catalog in the same PR.