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: 5 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,11 @@ These ten rules apply everywhere — `apps/web`, `apps/mobile`, `packages/shared
2. **Delete unused code immediately.** No "just in case" exports, dead branches, commented-out blocks, stub functions, or speculative parameters. If the linter can't see it's used, delete it.
3. **No `any`.** Use `unknown` with narrowing. No `as any`, no `as unknown as X` escape hatches.
4. **No `console.log` in production code.** Use the project logger if one exists, or don't log.
5. **Comments — strict policy.**
- Allowed: short doc comments on **public / exported** functions, hooks, and types — one short paragraph on intent and contract.
- Allowed: WHY comments for non-obvious decisions (workaround for upstream bug, hidden invariant, subtle constraint).
- Banned: comments that restate the code (`// loop through items`).
- Banned: comments that reference the current task / PR / fix / ticket.
- Banned: TODOs without a tracked issue.
5. **Comments — strict policy (lint-enforced via `local/no-comments`; autofix strips violations).**
- Allowed: `/** */` JSDoc on **exported** functions, hooks, and types — one short paragraph on intent and contract.
- Allowed: a WHY comment ONLY when it links an upstream issue/PR/doc URL (an external constraint you cannot fix here). No link → no comment.
- Allowed: tooling directives (`eslint-disable`, `@ts-expect-error`, `/// <reference>`).
- Banned: everything else. No `//` narration, no restating code, no task/PR/fix references, no TODOs. To explain code, rename it or extract a well-named function instead.
6. **No premature abstraction.** Extract on the third real use, not the second. Three similar lines beats a premature helper.
7. **Function size & nesting.** Soft cap: ~50 lines per function, ~3 levels of nesting. Hard cap: ~100 lines. Going beyond means the function is doing too much — split it.
8. **Error handling at boundaries only.** Validate at trust boundaries (user input, external APIs). Inside the codebase, trust your types. Never swallow errors silently — surface them, or don't catch them.
Expand Down
166 changes: 0 additions & 166 deletions apps/mobile/__tests__/lib/bottom-sheet-overlay-controller.test.ts

This file was deleted.

65 changes: 0 additions & 65 deletions apps/mobile/__tests__/lib/bottom-sheet-snap.test.ts

This file was deleted.

8 changes: 0 additions & 8 deletions apps/mobile/app/(tabs)/calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@ function entryDotState(entry: CalendarDayEntry): StatusDotState {
return "empty";
}

// Visible outcome badge for a day-detail row. Only resolved states carry a badge;
// an upcoming (not-yet-resolved) habit shows none — its status dot already conveys
// the state — so the list stays quiet instead of repeating a label on every row.
function statusBadge(
entry: CalendarDayEntry,
t: (key: string) => string,
Expand Down Expand Up @@ -155,7 +152,6 @@ export default function CalendarScreen() {
setShowDayDetail(true);
}, []);

// Weekday headers — short localized labels via shared i18n.
const weekdayHeaders = useMemo(() => {
const mondayFirst = [
{ key: "monday", label: t("dates.daysShort.monday") },
Expand Down Expand Up @@ -205,7 +201,6 @@ export default function CalendarScreen() {
return days;
}, [currentMonth, dayMap, weekStartsOn]);

// Selected day entries
const selectedEntries = useMemo(() => {
if (!selectedDay) return [];
return dayMap.get(selectedDay) ?? [];
Expand All @@ -228,9 +223,6 @@ export default function CalendarScreen() {
(entry: CalendarDayEntry) => entry.status === "completed",
).length;

// Stats: this month's best streak / total logs / missed (lightweight summary).
// The previous implementation computed only "current month" granularity; we
// keep that scope and surface the counts via SettingsRow below the legend.
const monthStats = useMemo(() => {
const monthDays = gridDays.filter((d) => d.isCurrentMonth);
const totalLogs = monthDays.reduce(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ interface CalendarLegendProps {
function createStyles(tokens: ReturnType<typeof createTokensV2>) {
return StyleSheet.create({
headerWrap: {
// The AppBar handles its own padding; this wrapper is here so the
// tour engine can anchor the month nav to a stable parent.
},
monthNavRow: {
flexDirection: "row",
Expand Down
1 change: 0 additions & 1 deletion apps/mobile/app/(tabs)/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@ const TodaySearchBar = memo(function TodaySearchBar({
}
const focusAnim = focusAnimRef.current;

// Mirror controlled `initialValue` prop into local draft.
const [previousInitialValue, setPreviousInitialValue] = useState(initialValue);
if (initialValue !== previousInitialValue) {
setPreviousInitialValue(initialValue);
Expand Down
4 changes: 0 additions & 4 deletions apps/mobile/app/(tabs)/today-shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,6 @@ export function TodayTabs({
useTourTarget('tour-tabs-bar', tabsRef)
useTourTarget('tour-goals-tab', goalsTabRef)

// Single chip-strip — preserves the chip semantics through `Chip` primitive.
// The two refs are required so the tour engine can locate the tab strip and
// the goals tab specifically. `goalsTabRef` is attached to a wrapper around
// the chip strip's "Goals" position.
const chipTabs = useMemo<SectionHeadTab<TodayTabView>[]>(
() =>
tabs.map((tab) => ({
Expand Down
2 changes: 0 additions & 2 deletions apps/mobile/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ import { VersionUpdateDrawer } from '@/components/version-update-drawer'
import { TourProvider } from '@/components/tour/tour-provider'
import { TourOverlay } from '@/components/tour/tour-overlay'

// Push notifications are not supported in Expo Go (removed in SDK 53).
// Only import PushPrompt in dev builds / standalone.
const isExpoGo = Constants.appOwnership === 'expo'
const PushPrompt = isExpoGo
? () => null
Expand Down
8 changes: 0 additions & 8 deletions apps/mobile/app/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,6 @@ export default function LoginScreen() {
keyboardShouldPersistTaps="always"
showsVerticalScrollIndicator={false}
>
{/* Referral banner at the very top edge */}
{showReferralBanner && (
<View style={styles.referralBanner}>
<Text style={styles.referralBannerText}>
Expand All @@ -384,24 +383,20 @@ export default function LoginScreen() {
)}

<View style={styles.formColumn}>
{/* Saturn glyph + wordmark + hairline rule */}
<View style={styles.brandingHeader}>
<SaturnDropcap size={32} color={tokens.fg1} />
<Text style={styles.wordmark}>Orbit</Text>
<View style={styles.brandingRule} />
</View>

{/* Step subtitle: "Sign in" / "Enter code" */}
<Text style={styles.stepSubtitle}>
{step === 'email' ? t('auth.signIn') : t('auth.enterCode')}
</Text>

{/* Inline italic error (v8 spec: centered overdue) */}
{errorMessage && (
<Text style={styles.inlineError}>{errorMessage}</Text>
)}

{/* Success alert */}
{successMessage && (
<Text style={styles.successText}>{successMessage}</Text>
)}
Expand Down Expand Up @@ -491,7 +486,6 @@ export default function LoginScreen() {
</Text>
</Pressable>

{/* Legal */}
<Text style={styles.legal}>
{t('auth.legalPrefix')}{' '}
<Text style={styles.legalLink} onPress={openTerms}>
Expand Down Expand Up @@ -549,7 +543,6 @@ export default function LoginScreen() {
</Text>
</Pressable>

{/* Mono countdown or resend link */}
<View style={styles.resendRow}>
{canResend ? (
<Pressable onPress={resendCode} disabled={!isOnline}>
Expand Down Expand Up @@ -598,7 +591,6 @@ function createStyles(tokens: AppTokensV2) {
paddingBottom: 24,
},

// Referral edge banner (very top, mono uppercase)
referralBanner: {
alignSelf: 'stretch',
paddingHorizontal: 14,
Expand Down
Loading
Loading