Skip to content

Native iOS app: typed Sparring - #138

Merged
Programcode merged 12 commits into
feat/native-iosfrom
native-ios/05b-sparring
Oct 14, 2026
Merged

Programcode merged 12 commits into
feat/native-iosfrom
native-ios/05b-sparring

Conversation

@Programcode

Copy link
Copy Markdown
Owner

Typed Sparring in the iOS app, mirroring the website's SparringPage in its typed mode. Voice waits for the first development build.

What's in it

  • Setup. A native form with the website's formats and defaults. The side is chosen when the round starts.
  • Live round (mock 05).
    • Full screen and follows the system theme.
    • Speeches run in format order, with a ring clock per speech built on deadlines (the 5a timer logic).
    • Pause, resume, and the website's retry.
    • The opponent's AI speeches.
    • Your speech is typed in a composer, with a haptic tick when your turn starts. The screen stays awake.
    • The flow button opens the Flowchart on the Current Debate's map, and the round keeps running underneath.
  • Judging and scorecard (mock 06). Score bars instead of the website's radar chart, then the verdict, category notes, key moments, what to work on next and overall feedback.
  • Saved rounds. They reopen from Practice and the Debate tab's recent work. Delete asks for confirmation first.
  • Saving. As on the website, the server creates and completes the sparring_sessions row. The app files it in its debate under your side, with user_id filters on every read.
  • Shared logic. The round's moves live in packages/core/src/sparring, and the website imports them back in one line. The website's turn-order and state tests pass unchanged.
  • Voice. The switch is shown disabled, with the "Coming with the app build" note.

Checks (local; GitHub Actions is out of minutes)

At 1689eef, which has the same tree as the head 6400f2f after the feat merge:

  • npm run verify: exit 0.

    • Unit tests 311/311 and 30/30.
    • Edge tests 333 passed.
    • The build passed.
    • Playwright smoke 30/30.
  • npm -w @debatelab/mobile run typecheck, npx eslint apps/mobile and npx knip: exit 0.

  • The screenshot harness ran all 8 device, theme and language combinations, 70 shots each, 6 of them Sparring:

    • setup
    • opponent speaking
    • your turn
    • the Flowchart opened from the round
    • judging
    • scorecard

    Two iPad-dark runs stopped once at the shared one-off step while the Debate tab's counts loaded from staging. Both passed when rerun alone.

  • Live on staging (seed Pro account, made-up motion, Lincoln-Douglas as Pro):

    • 3 AI calls: opponent turns of 19.6 s and 19.0 s, and the judge at 22.6 s.
    • The row saved as complete, reopened from Practice, then was deleted.
    • sparring_sessions went 0 → 1 → 0.

Differences from the mocks

  • Mock 05:
    • No clock during the opponent's typed turn, as on the website.
    • A "thinking" card instead of a waveform.
    • Send instead of the mic, and Reset instead of Skip (the website has no skip).
    • A text box with role guidance on your turn.
  • Mock 06:
    • The motion appears under the headline.
    • A "⋯" Delete menu.
    • The website's extra feedback sections.
    • The buttons float over the scrolling content.

Not provable here

The haptic tick, keep-awake, the native page-sheet look and the Flowchart over a live round all need a real phone.

Codex review rounds follow as comments.

🤖 Generated with Claude Code

Programcode and others added 11 commits October 9, 2026 16:28
The store's turn, clock, judging and saved-row logic becomes pure functions
in packages/core/src/sparring/session.ts, so the app keeps rounds the same
way. The website store and SparringPage import them back unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sparring mirrors the website's typed round: a setup form, the side asked
when the round starts, the opponent's turns and the student's typed
speeches on each speech's clock, judging, and the scorecard as bars
(mocks 05 and 06). The server saves the judged round; the app files it in
its debate, reopens saved rounds from Practice and the Debate tab, and
deletes them after confirming. The voice switch shows disabled until the
development build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The screenshot script plays a Lincoln-Douglas round as Con from fixed
outputs in English and Hungarian, holding the opponent and the judge for
their shots, and checks the turn-start taps and the running clock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in #129's form-sheet roots, OneOffNotice and shared keepIfSame,
and #132's timer signal fixes. Sparring's setup shows one-off mode through
WorkingIn like the other tool forms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in Brainstorm and Factoids (#131), the phone-test fixes (#129) and
untilAborted's move into ai-request.ts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eetScrollView

Practice now numbers its loads and files a failure under the debate it was
read for, as Prepare does, so a slow load or an error for one debate never
shows under another. The round's notes sheet uses SheetScrollView like every
sheet, and the opponent and judge requests read the Sparring settings under
the request's abort, so leaving while they load sends nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in the Flowchart (#133) and postFunction's abort check before the
session read. Saved Sparring rounds and flowcharts both open from a work row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Now that the Flowchart is in the app, the live round's flow button opens it on
the Current Debate's map, as mock 05 asks, instead of the session-only notes
sheet that stood in for it. The round keeps running underneath. The notes
sheet, its session slot and its three strings go. The screenshot run opens
the Flowchart from the student's turn and checks the draft is still there on
the way back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 14, 2026 12:24
@vercel

vercel Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
debate-navigator Ready Ready Preview Oct 14, 2026 12:50pm UTC
debatelab-staging Ready Ready Preview Oct 14, 2026 12:50pm UTC

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository YAML (base), Organization UI (inherited)
  • Review profile: CHILL
  • Plan: Free
  • Run ID: 3b5a0912-6fa4-40f8-aebc-5e923ed0c24e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Essentials by visiting https://app.coderabbit.ai/settings/billing.

Comment @coderabbitai help to get the list of available commands.

A reopened scorecard now remembers whose round it holds, so after an
account change it shows loading instead of the previous account's round
while the new read runs. Each side choice is numbered, so a slow debate
creation from an earlier choice never starts a round over a newer one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Programcode

Copy link
Copy Markdown
Owner Author

Codex review r1 at 6400f2f (gpt-6.1-sol, high): 2 findings, both verified against the code and fixed in f696946.

  • High: a reopened scorecard kept the previous account's round on screen after an account change until the new read finished. The screen now records whose round it holds and shows loading for anyone else.
  • Medium: a slow 'Create debate' from an earlier side choice could start a round over a newer one and erase its draft. Side choices are now numbered and a stale one is dropped.
    Codex also matched website behaviour across six format/side combinations and 201 state checkpoints, and en/es/hu keep identical sets of 182 mobile.* keys.
    Local at f696946: npm run verify green (311 vitest, 30 smoke), mobile typecheck, eslint, knip pass. Codex r2 next.

@Programcode

Copy link
Copy Markdown
Owner Author

Codex review r2 at f696946 (gpt-6.1-sol, high): no findings. Saved-scorecard ownership, account clearing, sign-out, stale fetch cleanup and both awaits in the start flow checked; both r1 findings fixed. Merging into feat/native-ios. Not provable here: haptic tick, keep-awake, native page sheet and the Flowchart over a live round (Adam's phone).

@Programcode
Programcode merged commit eb5edd7 into feat/native-ios Oct 14, 2026
8 of 18 checks passed
@Programcode
Programcode deleted the native-ios/05b-sparring branch October 14, 2026 12:50
Programcode added a commit that referenced this pull request Oct 14, 2026
Brings in Sparring (#138), development-build prep (#142), App Store
entitlements (#141) and offline reading (#139).

- The push migration becomes 20261014130000_push_tokens.sql so it sorts
  after 20261014123154_app_store_entitlements.sql.
- auth.tsx and _layout.tsx keep both the push wiring (release on sign-out,
  refresh on launch and language change) and setCacheOwner/watchNetwork.
- package-lock.json is feat's lock plus `npm install` for expo-notifications.
- app.config.ts is unchanged: #142 already strips aps-environment from
  development builds. The mobile guide now says so, and that real push needs
  a profile with push and an APNs key from Adam's Apple Developer account.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch was successfully deployed

2 active deployments
Preview – debate-navigator — f696946c Deployed Oct 14, 2026 by vercel[bot]
Preview – debatelab-staging — f696946c Deployed Oct 14, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants