Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,15 @@ jobs:
node-version: 24
- run: corepack enable && corepack install
- run: command -v xcodegen >/dev/null || brew install xcodegen
# The runner image ships several Xcodes and defaults to an older one than
# developer machines use. That skew is what let a Sendable data-race error
# reach main-bound code while compiling clean locally, so pick the newest
# installed and print it — a native failure should never be a mystery about
# which compiler ran.
- name: Select and report the Xcode in use
run: |
latest=$(ls -d /Applications/Xcode*.app | sort -V | tail -1)
echo "Selecting $latest"
sudo xcode-select -s "$latest"
xcodebuild -version
- run: pnpm quality:native
37 changes: 37 additions & 0 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Pages

# The public site is static files. GitHub Pages serves them so the project keeps
# no infrastructure of its own; the iPhone app depends on none of this.
on:
push:
branches: [main]
paths:
- "public/**"
- ".github/workflows/pages.yml"
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

# One deployment at a time, and never cancel one midway.
concurrency:
group: pages
cancel-in-progress: false

jobs:
deploy:
runs-on: ubuntu-latest
timeout-minutes: 10
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/checkout@v6
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v4
with:
path: public
- id: deployment
uses: actions/deploy-pages@v4
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,6 @@ next-env.d.ts
/outputs/
/work/
*.tsbuildinfo

# xcode build output
/ios/build/
3 changes: 0 additions & 3 deletions .prettierignore

This file was deleted.

10 changes: 7 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
- Keep recorded, calculated, authored, adjusted, and unavailable values
visibly distinct.
- Use pnpm and the committed `pnpm-lock.yaml`.
- Run `pnpm run check` before broader release validation.
- Do not deploy, migrate D1, change OAuth configuration, or change production
secrets without explicit approval.
- Run `pnpm run check` before broader release validation. For any change under
`ios/`, run `pnpm quality:native` too — it is the gate CI runs on macOS
(xcodegen, simulator unit and UI tests, release build, coverage floor).
- Setline has no backend. Do not reintroduce an account, a server, or a
network call in the workout path.
- Setline uses no Cloudflare, no database and no hosting account. Do not add one.
- Do not change DNS or publish a release without explicit approval.
138 changes: 103 additions & 35 deletions PROJECT_STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,80 @@

Setline helps people execute a structured workout programme precisely without referring to another document or deciding what to do between sets. The user controls the programme; Setline presents the current action, records explicit results, controls rest, and separates recorded values from calculations.

The first release is an iOS-native workout player with a Cloudflare Worker API backend. It includes
Sarthak’s dated 12-week strength, cardio, and mobility programme, device-first
session execution, optional Google sign-in with a private account copy, basic
history, and progress. It excludes coaching, automatic programme generation,
social features, meal/recovery tracking, sensors, Apple Health, and Apple Watch.
The first release is an iOS-native workout player with no backend of its own. It
includes Sarthak’s dated 12-week strength, cardio, and mobility
programme resolved natively on device, structured set targets, multi-segment set
recording, a set timer alongside the rest timer, a bundled movement catalogue
spanning strength, stamina, mobility and flexibility, and per-exercise measured
current values against authored targets. It excludes coaching, automatic
programme generation, social features, meal/recovery tracking, and sensors.

Apple Health, Apple Watch, CrossFit session formats, range-of-motion
assessments, iCloud sync, and on-device workout generation are planned rather than
shipped. Until iCloud sync lands, training lives only on the device that recorded
it, and the versioned JSON export is the only way to move or back it up.

## Dependencies

- SwiftUI native iPhone app for workout execution.
- Cloudflare Workers for the API backend (auth, state sync, MCP, agent surfaces).
- Vite for test module loading.
- Better Auth with Google OAuth and native Sign in with Apple for optional
identity; existing accounts use an explicit linking flow rather than
email-based implicit linking.
- Cloudflare Workers and D1 for authenticated, user-scoped state.
- Browser `localStorage`, Service Worker, vibration, and installation APIs where supported.
- No email provider, paid service, sensor, or native runtime dependency.
- SwiftUI native iPhone app for workout execution, with Swift Charts for trends
and local notifications for rest completion.
- A JSON document in the app’s own container. No database, no account, no request
during a workout.
- GitHub Pages for the static public site and its agent surfaces. Nothing the app
does depends on it, and it costs no account to maintain.
- Node’s built-in test runner for the static-surface contracts; XCTest for
everything the app does.
- No backend, email provider, paid service, sensor, or third-party runtime
dependency.

## Timeline

- 2026-08-16 — replaced the placeholder privacy notice, terms and changelog with
real pages on the tracked palette. The privacy notice had still claimed that
optional Google sign-in stores a private user-scoped copy, which the backend
removal had made false; it now states that the app collects nothing and makes
no network requests, and it discloses this website's PostHog and portfolio-strip
scripts for the first time. Terms gained the health disclaimer, the
recorded-versus-calculated distinction, and the bundled-programme caveat.
Restored the `quality:native` script that CI calls and raised its coverage floor
from 65.3% to 83.8% against a measured 84.1628%. The never-completed
Google-auth OpenSpec change and the account-data-deletion spec are archived.

- 2026-08-16 — left Cloudflare entirely. Deleted the live `setline` Worker and the
`setline` D1 database, which held zero rows in every table because no one ever
signed in. Removed wrangler, the Cloudflare-only `_headers` and `_redirects`, and
the deploy script. The public site is now published by GitHub Pages from
`public/` with its own CNAME. Setline holds no Cloudflare resources and no
hosting account. `setline.significanthobbies.com` returns 530 until a CNAME to
`significant-hobbies.github.io` is added and Pages publishes.

- 2026-08-16 — removed the Cloudflare Worker backend and every trace of the
account layer: Better Auth with Google and Apple sign-in, D1-backed private
state, the MCP read surface, the whole-document sync and conflict flow, 3,277
lines of superseded TypeScript, and 12 test files covering it. Setline is now
device-first with no server of its own. The public site became static Pages
content carrying its own headers, and the service worker was replaced with one
that evicts the shell of the deleted web app. The sync invariant that the
removed cloud type used to guard is preserved as a document-level contract.

- 2026-08-16 — replaced the placeholder landing page with a real one built to the
fleet landing standard on the app's own tracked palette: hero, product
screenshots, four-pillar breakdown, a refusals section, fit guidance and a FAQ,
with honest pre-release status and no store link. Agent-indexing surfaces were
rewritten to match, and a test now holds the sitemap, the agent catalogue and
the files on disk to one another so no surface can drift. Removed all six
duplicated blocks in the native sources and split the two longest new
functions; duplication is now zero.

- 2026-08-16 — replaced free-text set targets with a structured target model and
ported the dated 12-week programme into the native app, which previously
shipped only a two-template placeholder. Added a bundled movement catalogue
across all four pillars, per-exercise measured current values with authored
targets and trend charts, repeatable multi-segment set recording with a
shorthand parser, a set timer independent of rest, rest-completion
notifications, and authored double-progression rules. Version 2 of the local
document reads version 1 without losing recorded work.

- 2026-08-15 — removed the Next.js web app and went iOS-first. The Cloudflare Worker API backend (auth, native state, MCP, agent-edge) remains unchanged. Static HTML pages in public/ replace the web UI. Shared business logic moved from app/lib/ to src/lib/.

- 2026-08-12 — shipped the native account connection path on the personal
Expand Down Expand Up @@ -90,13 +144,17 @@ social features, meal/recovery tracking, sensors, Apple Health, and Apple Watch.

- `ios/` — native SwiftUI iPhone beta for local-first workout execution;
App Store Connect/TestFlight transport remains manual.
- Static public pages (index, privacy, terms, changelog) served from public/ via the Worker ASSETS binding.
- Static public site in `public/` (landing, privacy, terms, changelog) plus the
agent surfaces `index.md`, `llms.txt`, `llms-full.txt`, `sitemap.xml`,
`robots.txt` and `/api/ai`, published by GitHub Pages on push to `main`. The
canonical hostname is dark until its DNS record points at GitHub Pages.
- [Public GitHub repository](https://github.com/Significant-Hobbies/setline) —
canonical source, product planning, and issue owner.
- `https://setline.significanthobbies.com` — live Cloudflare Worker production
surface.
- `https://setline.significanthobbies.com` — canonical public surface, pending a
DNS record to GitHub Pages.
- [Private Sites deployment](https://setline-workout.sarthak927.chatgpt.site) —
owner-only rollback copy.
owner-gated (401) survivor of the removed web app. It is not a rollback path
for the iPhone app and nothing depends on it.

## Features (shipped)

Expand All @@ -105,8 +163,28 @@ social features, meal/recovery tracking, sensors, Apple Health, and Apple Watch.
timestamp-derived rest, relaunch recovery, planning, history, progression,
data transfer, accessibility, simulator tests, and personal-team archiving.
- Public editorial product changelog at `/changelog`.
- Landing page stating audience, outcome, the four pillars, what the product
refuses to do, poor-fit cases and real FAQs, with product screenshots and no
claim of App Store availability.
- Dated seven-day schedule for the supplied 12-week strength, cardio, and
mobility programme.
mobility programme, resolved natively for every one of its 84 days.
- Structured set targets carrying rep ranges, absolute/relative/bodyweight/assisted
load, reps in reserve, tempo, per-side work, and rest as a band rather than a
scalar; warm-up sets are excluded from volume, records, and progression.
- Bundled movement catalogue with stable identities, muscle groups, equipment,
and per-movement measurable metrics across strength, stamina, mobility, and
flexibility, plus the CrossFit movement vocabulary.
- Per-exercise measured current values (estimated 1RM, top set load, max
repetitions, best hold, longest distance, best pace, range of motion), each
citing the session that produced it, against authored targets with progress,
weekly rate, projected arrival, and trend charts.
- Repeatable multi-segment set recording so `5 reps × 40 kg` followed by
`2 reps × 30 kg` records as one set, with a tested shorthand parser that shows
its interpretation before anything is recorded.
- Set timer recording time under load independently of the rest timer.
- Rest-completion local notification so the timer survives leaving the app.
- Authored double-progression rules per movement, including the plan's own
increments and its below-range regression case.
- Exact authored exercise and set order across Upper, Lower, easy cardio, hard
cardio, mobility, preparation, and cooldown work.
- Week-aware RDL volume, hard-cardio rounds, and pull-up checkpoints.
Expand All @@ -118,44 +196,34 @@ social features, meal/recovery tracking, sensors, Apple Health, and Apple Watch.
- Device-local active-session continuity and workout history.
- Versioned JSON download plus validated, bounded import preview and explicit
whole-state replacement for local workout data.
- Optional Google sign-in with one private, user-scoped D1 state copy.
- Fresh-session-protected self-service account deletion that removes linked
auth records and the private workout copy through existing D1 cascades, then
reports browser cleanup separately.
- Device-first changes with offline retry and deterministic whole-state
reconciliation.
- Explicit state validation that preserves authored exercise and set order.
- Public privacy notice and terms of use.
- Public privacy notice stating that the app collects nothing and disclosing the
website's own third-party scripts, terms of use carrying the health disclaimer,
and a dated changelog that records removals as well as releases. A test reads
the script origins out of the markup and fails if the notice does not name them.
- Honest summary with separate warm-up/working volume and calculated provenance.
- Basic bench target context plus local recorded-volume signal.
- Deterministic progression recommendations from the latest comparable
completed session, with calculated provenance and explicit session-only
Accept, Edit, or Keep current decisions.
- Responsive phone, tablet, and desktop layouts.
- PWA manifest, install metadata, service-worker shell, and offline-friendly local operation.
- Immutable authored plans with a separate session execution queue.
- Partial and drop-set segments such as `60 kg × 5` followed by `50 kg × 3`.
- Session-only extra sets, explicit Do later deferral, and preserved planned and
actual execution positions.
- Authored, adjusted, and actual rest retained separately from wall-clock
completion and next-start timestamps.
- Detailed per-set execution history preserved on device and in authenticated
cloud state.
- Detailed per-set execution history preserved on device, with a versioned JSON
export and a bounded import preview as the only way data leaves or enters.
- Recorded-history analytics with normalized exercise identity, metric-aware
newest-eight trends, lifetime bests and volume, workout aggregates, and
represented bundled programme-week summaries; custom workouts stay separate
and missing history is never treated as missed training.
- Bounded custom workout templates with ordered exercise authoring, edit,
independent duplication from bundled or custom workouts, confirmed deletion,
and the existing offline-first workout player.
- Custom templates included in private whole-state sync and versioned JSON
backup/restore, while active sessions and history retain immutable snapshots.
- One named 1–16 week custom programme with explicit seven-day assignments,
confirmed copy/shrink/delete actions, and enabled or paused state.
- Calendar-correct Today resolution for scheduled custom workouts and explicit
unplanned days, with scheduled sessions retaining programme week/day context.
- Programme assignments reference custom templates, clear atomically when a
template is deleted, and travel in private sync and JSON backup/restore.

## Work queue

Expand Down
48 changes: 34 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,52 @@
# Setline

Setline is a mobile-first workout execution tracker for following an authored
programme, recording actual sets, controlling rest, and preserving detailed
history without depending on a gym connection. Workouts remain device-first;
optional Google sign-in keeps one private, user-scoped D1 copy in sync.
Setline is an iPhone training tracker for following an authored programme,
recording actual sets, controlling rest, and measuring each exercise against a
target you set. It has no backend: everything runs and records on the device, and
the versioned JSON export is the only way data moves.

Production: [setline.significanthobbies.com](https://setline.significanthobbies.com)
The iPhone app lives in [`ios/`](./ios). The public site is static files in
[`public/`](./public) published by GitHub Pages, and nothing the app does depends
on it. There is no backend and no hosting account to maintain.

Site: [setline.significanthobbies.com](https://setline.significanthobbies.com) —
dark until its DNS record points at GitHub Pages ([#43](https://github.com/Significant-Hobbies/setline/issues/43)).

## Local development

The app:

```bash
./ios/scripts/check.sh # xcodegen, simulator tests, release build
```

The public site:

```bash
pnpm install
pnpm run dev
pnpm run check # static-surface contracts and code health
python3 -m http.server -d public 8080
```

## Checks

```bash
pnpm run check
pnpm run check # static surfaces and code health
pnpm quality:native # xcodegen, simulator tests, release build, coverage
```

The release includes the owner-authored 12-week programme, custom workout
templates, one bounded multi-week custom programme, flexible execution,
device-local continuity, versioned whole-state backup/restore, optional private
account sync, history, progress, and explicit deterministic session-only
progression recommendations. Multiple programme libraries, arbitrary workout
import, reminders, coaching, sensors, health integrations, social features,
and full analytics remain deferred.
The release includes the owner-authored dated 12-week programme, structured set
targets, a bundled four-pillar movement catalogue, per-exercise measured current
values against authored targets, multi-segment set recording with a shorthand
parser, a set timer alongside rest, custom workout templates, one bounded
multi-week custom programme, device-local continuity, versioned whole-state
backup/restore, history, progress, and deterministic session-only progression
recommendations.

Deferred: iCloud sync across devices, Apple Health, Apple Watch, CrossFit
session formats, range-of-motion assessments, on-device workout generation,
coaching, and social features. Until iCloud sync lands, training lives only on
the device that recorded it and the JSON export is the only backup.

Source, product planning, and work tracking live in this repository. Fleet
Workspace consumes only catalog and operational links.
7 changes: 1 addition & 6 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import { defineConfig, globalIgnores } from "eslint/config";

const eslintConfig = defineConfig([
globalIgnores([
"dist/**",
"node_modules/**",
"worker-configuration.d.ts",
"worker/agent-edge.d.mts",
]),
globalIgnores(["dist/**", "node_modules/**"]),
]);

export default eslintConfig;
Loading
Loading