Skip to content

Latest commit

 

History

History
185 lines (168 loc) · 9.59 KB

File metadata and controls

185 lines (168 loc) · 9.59 KB

PLAINLY — Ship Plan (v1, 2026-07-05)

Lives in the repo. Ledger + verdicts live in the project's Memory.md. Status: VALIDATED (see Memory.md v4) → this file is the build contract.

The product in one line

Your battery, explained like a human — a Mac menubar app that turns Apple's raw numbers (health %, cycles, charging state) into one plain verdict, plus a charging-habit nudge when it's relevant. Read-only by design.

Why this wins (evidence-backed, 2026-07-05)

  • Apple defines numbers but never interprets them; "Learn More" bounces to support.apple.com (builder audit, 0/5 on kill sheet). macOS 27 "Golden Gate" doesn't change this (Perplexity-verified, PARTIAL/safe).
  • Paid incumbents sell actions (AlDente ★9.1k) or dashboards; nobody sells understanding. AlDente's closed-source resentment = trust wedge.
  • Read-only = structurally low maintenance (P8): action apps break every macOS release; Plainly mostly won't.

MVP SPEC (scope-locked — additions go to v1.1 list, not v1)

Menu bar item: subtle icon + optional short status. NOT another % badge (the system already shows %). Click → popover:

  1. VERDICT HEADER (the product): one plain sentence — the five ratified states (like-new / normal / worn / service / no-battery). The copy already carries the "health in context" and "cycle position" framing, so those aren't separate insight rows (cut in Week 2 — see Verdict engine below). Subline: "87% capacity · 412 cycles"
  2. INSIGHT — charging habit (reads AC power state + current charge %): shown only when triggered (on AC and sitting at 100%): "Batteries age faster when kept sitting at 100%. macOS has a built-in setting to cap charging at 80% — it slows aging. Your choice; convenience matters too." (Points at Apple's control; never implement charging actions — P8.)
  3. Footer: "What do these numbers mean?" → in-app plain explainer. NEVER bounce to a website. That's the whole point.

Data layer (all read-only, no sudo, no helpers):

  • IOPSCopyPowerSourcesInfo / IOPSCopyPowerSourcesList: charge %, power source, charging state, time estimates.
  • IORegistry "AppleSmartBattery": CycleCount, AppleRawMaxCapacity / NominalChargeCapacity, DesignCapacity, BatteryHealthCondition, (Temperature — v1.1).
  • ALL reads behind one BatteryReader protocol + adapter (BatFi #143 lesson: isolate OS-facing code; per-release churn hits the adapter, not the app).

Verdict engine: deterministic rules table shipped as readable data in the repo (VerdictEngine.swift). Health drives the verdict; cycle count is context only (it never demotes a healthy reading — a battery past 1,000 cycles still holding ≥80% is beating Apple's own rating, not falling behind it) and only gates the like-new floor (<50 cycles). Apple's own condition flag overrides the health/cycle bands entirely. No LLM at runtime. Transparent rules = trust wedge + community PRs. Sources cited in comments (Apple's 80%@1000 rating, service thresholds).

Edge cases v1: desktop Mac / no battery → friendly empty state; Intel Macs → "untested, PRs welcome" in README (different SMC keys; don't block v1 on hardware you can't test).

Explicit NON-goals v1: charge limiting or any write action; menu-bar % badge; history database (Pro, later); notifications; Intel validation; localization.

THE GIF (the launch asset — craft this like a feature)

~12s loop, ~800px, <5MB (README autoplay):

  1. Apple's real Battery Health ⓘ popup: "Maximum Capacity 100% — a measure of battery capacity relative to when it was new." (hold 3s)
  2. Cursor clicks Plainly in the menu bar.
  3. Popover: verdict gauge animates → "100% capacity · 2 cycles — like new. Charge however you like; you're years from worrying."
  4. Caption: "Apple defines the number. Plainly gives you the verdict." Record on the M4 (clean desktop, light mode) with a second variant on an aged battery if a friend's older MacBook is borrowable — the 87% frame is more relatable than 100%.

Status: DONE (v1, like-new variant). docs/plainly-demo.gif, 1.5MB, 800px/12fps, embedded at the top of the README — Apple's Battery Health popup next to Plainly's actual ratified LIKE-NEW verdict ("100% capacity · 2 cycles"). Built with Scripts/make-gif.sh. No caption overlay or gauge animation yet (popover UI polish is Week 3); the aged-battery (87%) second variant is still open — nice-to-have, not blocking.

BUILD SEQUENCE (~10 hrs/week)

WEEK 1 — foundation + the gate

  • [2h, FIRST] Sandbox spike: new Xcode project, App Sandbox ON, read IOPS + AppleSmartBattery keys. 🟡→🟢 this before anything else; it gates the MAS path. Paste results into next session.
  • Scaffold from ~/dev/templates/macos-menubar-app: MenuBarExtra + popover skeleton, Swift 6 strict concurrency, reads on a background actor. BatteryReader protocol + live adapter + mock adapter (mock drives previews/tests with aged-battery fixtures: 87%/412c, 79%/950c, Service Recommended, etc.). WEEK 2 — the product
  • Verdict rules table + engine (pure functions; Claude Code writes exhaustive unit tests across the band matrix).
  • YOU write every verdict sentence. Read them aloud to one non-technical person; rewrite until they nod.
  • Popover UI: header + charging-habit insight (when triggered) + explainer sheet. WEEK 3 — polish + assets
  • Launch-at-login, light/dark, gauge animation (this is the GIF star), empty states. Record + edit GIF. README (structure below). WEEK 4 — launch the WTP test
  • Repo public with working source + GIF + waitlist link (Buttondown or Tally — zero-backend). X build-in-public thread (the Claude-Code- assisted workflow is itself content). r/macapps post (GIF-led).
  • HOLD Show HN for notarized v1.0 — one front-page shot; don't spend it on a waitlist. POST-TEST (only if greenlit): Apple Developer Program ($99) → notarized DMG via GitHub Actions → Show HN → v1.x cadence → MAS.

WTP TEST SPEC (the single riskiest assumption)

Assumption: people install/pay for explanation vs googling once. Artifact: public repo (real code) + GIF + waitlist. 4 weeks.

  • ≥300 stars OR ≥200 waitlist emails → GREENLIGHT: join Dev Program, notarize, ship v1.0, plan Pro.
  • 100–300 stars → one repositioning pass (GIF/title/framing), +2 weeks.
  • <100 stars → back to WATCH; run slow/hot rematch (Memory.md). [Thresholds pending builder ratification — say the word or counter.]

GITHUB STRATEGY

README order: GIF → one-liner → "Why" (Apple's popup screenshot beside Plainly's verdict) → Install (source now; "notarized build at 300★") → How verdicts work (link the rules table — transparency vs closed-source incumbents) → Roadmap ("Plainly family: next, your Mac's heat & slowness, explained") → Waitlist. License: MIT (portfolio-credibility goal > fork protection). Channels, in order: X thread (day 1, ongoing) → r/macapps (launch) → r/mac + r/macbookpro (week 2, answer battery-confusion threads with the app where genuinely relevant) → Show HN (notarized v1.0 only).

APP STORE MIGRATION (after GitHub v1.0 traction)

  • Gate already half-cleared: sandboxed IOPS is public API; MAS battery apps showing cycle counts exist (precedent 🟢). Spike confirms 🟢.
  • Risk: App Review objecting to IORegistry reads. Mitigation: IOPS primary, IORegistry enhancement, degrade gracefully; precedent apps in appeal notes.
  • Listing: "Plainly — Battery, Explained." Free + Pro one-time IAP (history/trends, cycle-pace coaching, replacement-timing advisor). Price at Pro launch; UsageScope precedent supports one-time. Ceiling thought: $9.99.
  • MAS adds: payment rails + normie discovery. GitHub stays the trust/dev channel. Same core, feature-flagged Pro.

RISKS & MOATS

Risks:

  1. macOS 27 GM re-check (Sep–Oct): battery pane + menubar rendering. Known churn: NSMenu hides symbol images by default in 27 → adopt preferredImageVisibility (NSMenuItem) now; build on 26.x, test each 27 beta. (BatFi #143 class of breakage — UI, not data; IOKit untouched in 27 notes 🟢.)
  2. WTP unproven → the test above exists precisely for this.
  3. Fast-follow clones of a viral GIF → moats: verdict-copy quality, transparent rules, family roadmap, shipping velocity.
  4. Single-maintainer stall (BatteryBoi's fate) → tiny scope (P8), rules-as-data for community PRs, read-only = low upkeep.
  5. Apple Sherlock: LOW. Ten years of battery UI without interpretation (time-remaining removed 2016; 26.4 added controls; 27 adds performance). Apple explains controls, never states (P7). Re-check every WWDC. Moats: P7 structural vacancy · P8 low-maintenance read-only wedge · open-source trust vs AlDente resentment · human-grade verdict copy · Plainly family brand compounding stars across domains.

STACK (matched to the machine)

SwiftUI + MenuBarExtra · min target macOS 14, Apple Silicon first · Swift 6.3 strict concurrency · IOKit via C interop (no wrappers needed) · zero third-party dependencies in v1 (no Sparkle yet — GitHub Releases

  • lightweight update check later) · gh CLI for releases · GitHub Actions build+notarize post-Dev-Program · unit tests concentrated on the verdict engine.

CLAUDE CODE vs HUMAN JUDGMENT

Claude Code: IOKit interop, scaffolding, rules-engine implementation + test matrix, empty/edge states, README mechanics, CI/notarization pipeline, GIF-recording scripts. Human (the product): verdict sentences and voice · rules thresholds and their honesty (when to say "worth watching" without fearmongering) · GIF pacing · launch copy/timing · pricing · saying no to v1 scope creep. Rule of thumb: if it compiles, delegate it; if a stranger reads it and decides whether to trust you, write it yourself.