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
185 changes: 185 additions & 0 deletions .claude/SKILLS/ios-health-check/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
---
name: ios-health-check
description: >
Runs a full iOS/Capacitor environment health check and auto-fixes any failures
before proceeding with iOS-related work. Use before making any changes to iOS
code, Capacitor config, or Xcode project files.
---

# iOS Environment Health Check — TimeTracker Pro

## When to Use

Run this skill **before** making any changes to:

- `capacitor.config.ts`
- `ios/App/CapApp-SPM/Package.swift`
- `ios/App/App.xcodeproj/project.pbxproj`
- Any file under `ios/`
- Any feature gated by `VITE_IOS_BUILD`

Do not skip this check. Fix every failure before starting the actual task.

---

## Key File Locations

| File | Purpose |
|------|---------|
| `ios/App/CapApp-SPM/Package.swift` | SPM manifest — defines swift-tools-version and iOS platform target |
| `ios/App/CapApp-SPM/Package.resolved` | Resolved dependency lockfile |
| `ios/App/App.xcodeproj/project.pbxproj` | Xcode project — contains `IPHONEOS_DEPLOYMENT_TARGET` entries |
| `ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved` | Workspace-level resolved lockfile |
| `capacitor.config.ts` | Capacitor config — `experimental.ios.spm.swiftToolsVersion` must match Package.swift |
| `.env.ios` | iOS build env (`VITE_IOS_BUILD=true`, no Supabase keys) |

---

## Check 1 — swift-tools-version drift

**Read both values:**

```bash
head -1 ios/App/CapApp-SPM/Package.swift
# Expected: // swift-tools-version:X.X
```

```bash
node -e "const c = require('./capacitor.config.ts'); console.log(c.default?.experimental?.ios?.spm?.swiftToolsVersion ?? 'NOT SET')"
```

Or read `capacitor.config.ts` directly and look for:

```ts
experimental: {
ios: {
spm: {
swiftToolsVersion: "X.X"
}
}
}
```

**Pass condition:** Both values are identical.

**Auto-fix:** Update `swiftToolsVersion` in `capacitor.config.ts` to match the
value in `Package.swift`, then run:

```bash
npm run sync:ios
```

---

## Check 2 — Stale Package.resolved

```bash
cd ios/App/CapApp-SPM
swift package resolve
cd ../../..
```

**Pass condition:** Command exits 0 with no errors or warnings about missing packages.

**Auto-fix:** Delete the stale lockfile and regenerate:

```bash
rm ios/App/App.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
cd ios/App/CapApp-SPM
swift package resolve
cd ../../..
```

---

## Check 3 — iOS build target mismatch

Extract the platform version from `Package.swift`:

```bash
grep -E "\.iOS\(" ios/App/CapApp-SPM/Package.swift
# Expected: .iOS("26.0") or similar
```

Extract all `IPHONEOS_DEPLOYMENT_TARGET` values from the Xcode project:

```bash
grep IPHONEOS_DEPLOYMENT_TARGET ios/App/App.xcodeproj/project.pbxproj | sort -u
```

**Pass condition:** All `IPHONEOS_DEPLOYMENT_TARGET` values match the version
declared in the `.iOS("X.X")` platform entry of `Package.swift`.

**Auto-fix:** Update every `IPHONEOS_DEPLOYMENT_TARGET` entry in
`ios/App/App.xcodeproj/project.pbxproj` to match the Package.swift value.
Use a targeted sed or direct file edit — do not change any other keys.

> ⚠️ `cap sync` overwrites `Package.swift`. Always make version changes in
> `capacitor.config.ts`, not directly in Xcode project files.

---

## Check 4 — Workspace integrity

Check for dangling references in the Xcode workspace:

```bash
grep -rE "path = .*;" ios/App/App.xcodeproj/project.pbxproj \
| sed 's/.*path = //;s/;//' \
| sort -u
```

For any path that looks like a file (not a directory), verify it exists relative
to `ios/App/`. Flag any reference whose target is missing.

**Pass condition:** No referenced paths are missing from the filesystem.

**Auto-fix:** Remove the dangling `PBXFileReference` and any `PBXBuildFile`
entries that reference it from `project.pbxproj`. Do not remove group or
directory entries — only file references.

---

## Check 5 — Build validation

```bash
npm run build:ios
```

**Pass condition:** Exits 0 with no TypeScript errors, no Vite errors.

**Auto-fix:** Read the full error output carefully. Common causes:

| Error pattern | Fix |
|---------------|-----|
| `Cannot find module` | Check import alias — must use `@/`, never relative paths |
| `Type error` in iOS-only code | Ensure `VITE_IOS_BUILD` guard uses `import.meta.env.VITE_IOS_BUILD !== "true"` |
| Vite PWA plugin error | Confirm `.env.ios` sets `VITE_IOS_BUILD=true` to disable PWA plugin |
| Missing env variable | Add to `.env.ios` (never add Supabase keys here) |

---

## Reporting

After all checks, output a table before proceeding with the actual task:

| Check | Status | Action Taken |
|-------|--------|--------------|
| swift-tools-version drift | ✅ Pass / ❌ Fixed | (describe fix or "none") |
| Stale Package.resolved | ✅ Pass / ❌ Fixed | (describe fix or "none") |
| iOS build target mismatch | ✅ Pass / ❌ Fixed | (describe fix or "none") |
| Workspace integrity | ✅ Pass / ❌ Fixed | (describe fix or "none") |
| Build validation | ✅ Pass / ❌ Fixed | (describe fix or "none") |

If any check could not be auto-fixed, stop and report the blocker clearly
before touching any other files.

---

## Rules

- Always run all five checks — do not skip any because a previous one passed.
- Never modify `Package.swift` directly for version changes — always go through `capacitor.config.ts`.
- Never add Supabase credentials to `.env.ios`.
- Never commit `ios/App/App/public/` — it is gitignored and regenerated by `cap sync ios`.
- The minimum iOS deployment target for this project is **iOS 26**.
136 changes: 136 additions & 0 deletions .claude/SKILLS/new-feature/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
---
name: new-feature
description: >
Implements a new feature using a strict TDD workflow: read codebase patterns, write failing tests first, implement iteratively until all tests pass and lint is clean, then summarize decisions. Use when asked to add a feature or when "implement [FEATURE]" is requested.
---

# New Feature — TimeTracker Pro

## Clarification (if needed)

If the feature has not been stated, ask:

> "What feature would you like to implement? Please describe what it does and
> any relevant context (which page it lives on, what data it touches, etc.)."

Do not proceed until the feature is clearly defined.

---

## Autonomous Workflow

Follow these steps strictly and in order. Do not skip steps or combine them.

### Step 1 — Read the codebase

Before writing a single line of code, read:

1. **Existing tests** for the area you're touching:
- `src/components/*.test.{ts,tsx}`
- `src/contexts/*.test.{ts,tsx}`
- `src/services/*.test.{ts,tsx}`
- `src/utils/*.test.{ts,tsx}`
2. **The component or context closest to the new feature** — understand existing patterns before introducing new ones.
3. **[agents/conventions.md](../../agents/conventions.md)** — naming, TypeScript usage, and styling rules.
4. **[agents/architecture.md](../../agents/architecture.md)** — data flow, context structure, and service layer patterns.
5. **[agents/operations.md](../../agents/operations.md)** — how to add components, pages, context methods, and data service methods.

Do not proceed until you have enough context to write correct tests.

### Step 2 — Write failing tests first

Create or update test files **before implementing the feature**.

Cover all of the following:

- **Happy path** — the feature works under normal conditions
- **Edge cases** — empty state, boundary values, loading states, no data
- **Known error patterns** (from this project's history):
- Wrong function signatures passed as props
- State updates triggered during render (causes React warnings)
- Undefined references when context value is not yet initialized
- localStorage read/write failures (mock these explicitly)
- Supabase calls in guest mode (must be no-ops, not errors)

Run the tests to confirm they fail for the right reason:

```bash
npm run test -- --run
```

All new tests must fail at this point. If a test passes without implementation, the test is too weak — strengthen it.

### Step 3 — Implement iteratively

Build the feature in small increments, running tests after each meaningful change:

```bash
npm run test -- --run
npm run lint
```

Follow project code style — **non-negotiable**:

- Tabs, not spaces (2-space display width)
- Double quotes `""` always
- `@/` import alias — never relative paths like `../../`
- shadcn/ui components — never raw HTML with custom styles
- Radix/theme color variables — never custom Tailwind colors like `bg-blue-500`

Follow project architecture patterns:

- New UI → `src/components/` using shadcn/ui primitives
- New page → `src/pages/` with lazy load added in `App.tsx`
- New state/logic → method on `TimeTrackingContext` consumed via `useTimeTracking()`
- New persistence → method on `DataService` interface, implemented in both
`LocalStorageService` and `SupabaseService`
- New utility → `src/utils/` (pure functions, easy to unit-test)

### Step 4 — Do not stop until green

Continue iterating until:

- [ ] All new tests pass
- [ ] All pre-existing tests still pass
- [ ] `npm run lint` exits with no errors
- [ ] `npm run build` succeeds

**Do not ask for help or report partial progress.** Debug failures yourself:

1. Read the full error output — do not skim it.
2. Identify the root cause before changing code.
3. Fix one issue at a time, then re-run tests.
4. If stuck after two attempts on the same failure, step back and re-read the relevant context or service file from scratch.

### Step 5 — Commit the work

Stage only files related to the feature:

```bash
git add <files>
git status # verify nothing unintended is staged
git commit -m "feat: <concise description of the feature>"
```

Do not use `--no-verify`. Do not commit test artifacts or build output.

### Step 6 — Write a summary

After committing, output a brief summary covering:

1. **What was built** — one-paragraph description of the feature
2. **Files added/changed** — list with one-line purpose for each
3. **Architectural decisions** — any non-obvious choices made (e.g., why state lives in context vs. local, why a new service method was needed)
4. **Known limitations** — anything deferred or out of scope
5. **Next step** — remind to run the `sync-docs` skill before opening a PR

---

## Rules

- Never implement before tests exist.
- Never declare success while any test or lint failure remains.
- Never bypass linting (`--no-verify`, `eslint-disable` without justification).
- Never introduce new raw HTML elements where a shadcn/ui equivalent exists.
- Never use relative import paths.
- Never commit directly to `main` — always use a feature branch.
Loading
Loading