📦 deps(skills): sync pathfinding dependency for codebase-recon

This commit is contained in:
csh
2026-05-29 23:12:17 +08:00
parent b4c88b32be
commit c1bce2fb72
13 changed files with 1503 additions and 7 deletions
+344
View File
@@ -0,0 +1,344 @@
# Example: Early Delivery with Caveats
User requests delivery before reaching full confidence — demonstrates `△ Caveats` and mid-stream concerns.
<turn>
<user>
I want to add real-time notifications to our app. Users should get notified when someone comments on their posts.
</user>
<claude>
```text
[Task] Getting oriented
- Prep notification requirements (in_progress)
- Explore delivery mechanisms (pending)
- Clarify scale and persistence (pending)
- Deliver implementation plan (pending)
```
```text
▓▓░░░ Exploring
Assumptions:
- Existing app with posts and comments
- User accounts with some form of auth
- Web and/or mobile clients
Unknowns:
- Current tech stack?
- Scale (users, notifications/day)?
- Notification types (just comments, or more)?
- Persistence (history, read/unread)?
- Push notifications (mobile) needed?
Decisions:
- Real-time comment notifications
```
**Q1**: What's your current tech stack?
*Why it matters — determines which real-time approach fits best*
```text
[EnterPlanMode]
1. Node.js backend — Socket.io, ws, or SSE
2. Rust backend — Axum with WebSockets
3. Serverless (Vercel, AWS Lambda) — needs external service (Pusher, Ably)
4. Supabase — built-in realtime, minimal setup
5. Something else — describe your stack
```
</claude>
</turn>
<turn>
<user>
Node.js with Express, React frontend, PostgreSQL
</user>
<claude>
```text
Classic PERN stack — lots of good options for real-time.
▓▓▓░░ Charting
Assumptions:
- Can add WebSocket server alongside Express
- React can handle WebSocket connections
- PostgreSQL for notification storage
Unknowns:
- Scale expectations?
- Mobile app too, or web only?
- Need notification history/persistence?
Decisions:
- Node.js + Express + React + PostgreSQL
- Real-time comment notifications
Concerns:
- WebSocket scaling can get tricky with multiple server instances — may need Redis pub/sub or sticky sessions
```
```text
[Task] Shape emerging
- Prep notification requirements (completed)
- Explore delivery mechanisms (in_progress)
- Clarify scale and persistence (pending)
- Deliver implementation plan (pending)
```
**Q2**: What scale are you expecting?
*Why it matters — affects architecture complexity significantly*
```text
[EnterPlanMode]
1. Small (< 1k users) [★] — single server, simple WebSockets *start here, scale later*
2. Medium (1k-50k users) — needs Redis pub/sub for multi-server
3. Large (50k+ users) — dedicated service (Pusher, Ably, or self-hosted)
5. Something else — different constraints
```
</claude>
</turn>
<turn>
<user>
We're small now but hoping to grow. Can we just get something working? I can come back for scaling later.
</user>
<claude>
```text
Makes sense — ship something simple, optimize when needed.
▓▓▓░░ Charting
△ This assumes single-server deployment works for now — if you're already multi-instance, we'd need Redis pub/sub from the start. Clarify now, note for later, or proceed?
```
</claude>
</turn>
<turn>
<user>
Single server for now, let's proceed
</user>
<claude>
```text
Good — simple path forward.
▓▓▓▓░ Mapped
Assumptions:
- Single server deployment
- Web only (no mobile push for now)
- Basic notification (no persistence/history initially)
Unknowns:
- Want notification persistence (history, read/unread)?
Decisions:
- Socket.io on Node.js (simplest for Express)
- Single-server architecture
- Real-time comment notifications
Concerns:
- No persistence means notifications lost on refresh — might frustrate users
```
```text
[Task] Getting close
- Prep notification requirements (completed)
- Explore delivery mechanisms (completed)
- Clarify scale and persistence (in_progress)
- Deliver implementation plan (pending)
```
**Q3**: Should notifications persist? (history, read/unread state)
*Why it matters — affects database schema and UX significantly*
```text
[EnterPlanMode]
1. No persistence — real-time only, notifications disappear on refresh
2. Basic persistence [★] — store in DB, show unread count *better UX, moderate effort*
3. Full history — notification center, mark as read, pagination
5. Something else — different approach
```
</claude>
</turn>
<turn>
<user>
Actually, can you just give me what you have? I need to ship something today and can iterate.
</user>
<claude>
```text
Understood — shipping now, iterating later.
▓▓▓░░ Charting → Deliver (early)
Skipping to delivery at level 3. Including caveats for what's unresolved.
```
```text
[Task] Early delivery — shipping with caveats
- Prep notification requirements (completed)
- Explore delivery mechanisms (completed)
- Clarify scale and persistence (completed)
- Deliver implementation plan (in_progress)
```
## Real-Time Notifications — MVP Plan
**Architecture**:
```text
┌─────────┐ WebSocket ┌─────────────┐
│ React │◄──────────────────►│ Express │
│ Client │ │ + Socket.io│
└─────────┘ └──────┬──────┘
┌──────▼──────┐
│ PostgreSQL │
│ (comments) │
└─────────────┘
```
**Server Setup** (add to existing Express app):
```typescript
// server.ts
import { Server } from 'socket.io';
import { createServer } from 'http';
const httpServer = createServer(app);
const io = new Server(httpServer, {
cors: { origin: process.env.CLIENT_URL }
});
// Track connected users
const userSockets = new Map<string, string>(); // userId -> socketId
io.on('connection', (socket) => {
const userId = socket.handshake.auth.userId;
userSockets.set(userId, socket.id);
socket.on('disconnect', () => {
userSockets.delete(userId);
});
});
// Export for use in routes
export { io, userSockets };
```
**Emit on Comment Creation**:
```typescript
// routes/comments.ts
import { io, userSockets } from '../server';
app.post('/posts/:postId/comments', async (req, res) => {
const comment = await createComment(req.body);
const post = await getPost(req.params.postId);
// Notify post author (if not self-comment)
if (post.authorId !== req.user.id) {
const socketId = userSockets.get(post.authorId);
if (socketId) {
io.to(socketId).emit('notification', {
type: 'comment',
postId: post.id,
commentId: comment.id,
fromUser: req.user.name,
message: `${req.user.name} commented on your post`
});
}
}
res.json(comment);
});
```
**React Client**:
```typescript
// hooks/useNotifications.ts
import { useEffect } from 'react';
import { io } from 'socket.io-client';
import { toast } from 'your-toast-library';
export function useNotifications(userId: string) {
useEffect(() => {
const socket = io(process.env.REACT_APP_API_URL, {
auth: { userId }
});
socket.on('notification', (data) => {
toast(data.message);
// Could also update a notification count in state
});
return () => { socket.disconnect(); };
}, [userId]);
}
```
**Next Steps**:
1. `npm install socket.io` (server) and `socket.io-client` (client)
2. Add Socket.io to your Express server
3. Wire up comment creation to emit notifications
4. Add `useNotifications` hook to your app root
---
## △ Caveats
**Open questions**:
- Notification persistence — currently lost on refresh
- Mobile push — not addressed, would need separate implementation
**Assumed decisions**:
- Single server deployment — will break with multiple instances
- No read/unread tracking — no notification history
- Toast-only UI — no notification center
**Known concerns**:
- User might miss notifications if offline when sent
- No retry mechanism for failed deliveries
- Socket reconnection handling is minimal
**Deferred items**:
- Redis pub/sub for multi-server (when you scale)
- Notification persistence in PostgreSQL (soon — improves UX)
- Mobile push notifications (when you add mobile app)
- Notification preferences (mute, frequency)
```text
[Task] Done — shipped with caveats
- Prep notification requirements (completed)
- Explore delivery mechanisms (completed)
- Clarify scale and persistence (completed)
- Deliver implementation plan (completed)
```
Shipped — MVP real-time notifications ready to go. Come back when you need persistence or scaling.
</claude>
</turn>
+342
View File
@@ -0,0 +1,342 @@
# Example: Greenfield API Design
Starting from zero — vague request, no context.
<turn>
<user>
I need to build an API
</user>
<claude>
```text
[Task] Getting oriented
- Prep API requirements (in_progress)
- Explore architecture options (pending)
- Clarify data and auth needs (pending)
- Deliver API design doc (pending)
```
```text
░░░░░ Prepping
Unknowns:
- What domain/purpose?
- Who consumes it?
- What data?
- Performance/scale needs?
- Existing infrastructure?
```
**Q1**: Before we dive in — what kind of session are you looking for?
*Why it matters — sets the right depth and pace*
```text
[EnterPlanMode]
1. Quick pulse check [★] — nail down key decisions, move fast *good for exploring direction*
2. Deep dive — thorough exploration, comprehensive plan
3. Specific problem — I know what I want, need help with one aspect
5. Something else — describe what you're after
```
</claude>
</turn>
<turn>
<user>
1, I have a rough idea but need to figure out the shape
</user>
<claude>
```text
Got it — quick pulse to find the shape, then we can go deeper where needed.
▓░░░░ Scouting
Decisions:
- Quick pulse session, fast iteration
```
**Q2**: What's this API for?
*Why it matters — determines data model, auth strategy, and scaling approach*
```text
[EnterPlanMode]
1. Internal tool — dashboard, admin, ops
2. Public product API — third-party developers
3. Mobile/web backend — your own apps
4. B2B integration — partner systems
5. Something else — describe the use case
```
</claude>
</turn>
<turn>
<user>
3, it's for a fitness tracking app
</user>
<claude>
```text
Fitness tracking backend — workouts, metrics, user data. Classic mobile backend pattern.
▓▓░░░ Exploring
Assumptions:
- User accounts with personal data
- Workout/activity logging
- Progress tracking over time
- Mobile-first (iOS/Android)
Unknowns:
- Social features? (friends, sharing, leaderboards)
- Device integrations? (Apple Health, Fitbit, etc.)
- Real-time needs? (live workouts, streaming)
- Offline sync requirements?
Decisions:
- Mobile/web backend for fitness app
- Quick pulse session
```
**Q3**: What's the core loop users will do most often?
*Why it matters — shapes the data model and API surface*
```text
[EnterPlanMode]
1. Log workouts manually [★] — exercises, sets, reps, weights *simplest starting point*
2. Track metrics — weight, body measurements, progress photos
3. Follow programs — structured plans, scheduled workouts
4. Social/compete — friends, challenges, leaderboards
5. Something else — different core interaction
```
</claude>
</turn>
<turn>
<user>
1 and 2, logging workouts and tracking body metrics
</user>
<claude>
```text
Core loop: log workouts + track body metrics. Good foundation — can layer social/programs later.
▓▓▓░░ Charting
Assumptions:
- User model with profile data
- Workout sessions with exercises
- Body metrics (weight, measurements) with timestamps
- Historical data for progress charts
Unknowns:
- Auth approach?
- Exercise library (predefined vs custom)?
- Offline-first or always-online?
Decisions:
- Mobile backend for fitness app
- Core: workout logging + body metrics
- Start simple, extensible for social/programs later
Concerns:
- Exercise data can get complex (variations, equipment, muscle groups) — start with simple model, don't over-engineer
```
```text
[Task] Shape emerging — exploring options
- Prep API requirements (completed)
- Explore architecture options (in_progress)
- Clarify data and auth needs (pending)
- Deliver API design doc (pending)
```
**Q4**: How should users authenticate?
*Why it matters — affects security model, user experience, and implementation complexity*
```text
[EnterPlanMode]
1. Email/password [★] — simple, universal *good starting point*
2. Social login (Google/Apple) — better UX, less friction
3. Both — maximum flexibility
4. Magic link — passwordless, email-based
5. Something else — different auth approach
```
</claude>
</turn>
<turn>
<user>
3, I want both options
</user>
<claude>
```text
Both email/password and social login — covers all users.
▓▓▓▓░ Mapped
Assumptions:
- JWT tokens for mobile auth
- Email as primary identifier (link accounts by email)
- Refresh token rotation for security
Unknowns:
- Specific social providers (Google, Apple, both)?
Decisions:
- Dual auth: email/password + social login
- Workout logging + body metrics core
- Mobile backend architecture
Concerns:
- Account linking edge cases (same email, different providers) — handle gracefully
```
```text
[Task] Getting close — one more detail
- Prep API requirements (completed)
- Explore architecture options (completed)
- Clarify data and auth needs (in_progress)
- Deliver API design doc (pending)
```
Can proceed now, or one more question would nail down the social providers. Your call — deliver now or refine?
</claude>
</turn>
<turn>
<user>
Let's just do Google and Apple for now
</user>
<claude>
```text
Google + Apple — covers iOS and Android users well.
▓▓▓▓▓ Ready
Decisions:
- Dual auth: email/password + Google + Apple Sign-In
- Core features: workout logging, body metrics tracking
- JWT tokens with refresh rotation
- Mobile-first REST API
```
```text
[Task] Clear path — delivering design
- Prep API requirements (completed)
- Explore architecture options (completed)
- Clarify data and auth needs (completed)
- Deliver API design doc (in_progress)
```
## Fitness Tracking API Design
**Core Resources**:
```text
/auth
POST /register — email/password signup
POST /login — email/password login
POST /oauth/google — Google Sign-In
POST /oauth/apple — Apple Sign-In
POST /refresh — refresh access token
POST /logout — invalidate tokens
/users
GET /me — current user profile
PUT /me — update profile
DELETE /me — delete account
/workouts
GET / — list workouts (paginated)
POST / — create workout
GET /:id — get workout details
PUT /:id — update workout
DELETE /:id — delete workout
/exercises
GET / — list exercises (library)
POST / — create custom exercise
/metrics
GET / — list body metrics (paginated)
POST / — log new metric
GET /summary — progress summary (charts data)
```
**Data Models**:
```text
User {
id, email, name, avatar_url,
auth_provider: "email" | "google" | "apple",
created_at, updated_at
}
Workout {
id, user_id, name, started_at, ended_at,
exercises: [{ exercise_id, sets: [{ reps, weight, duration }] }],
notes, created_at
}
Exercise {
id, name, category, muscle_groups[],
is_custom, user_id (if custom)
}
BodyMetric {
id, user_id, type: "weight" | "measurement",
value, unit, measured_at
}
```
**Tech Stack Suggestion**:
- **API**: Hono or Express on Bun
- **Database**: PostgreSQL (Supabase or Neon)
- **Auth**: Custom JWT or Supabase Auth
- **Hosting**: Railway, Fly.io, or Vercel
**Next Steps**:
1. Set up project with Bun + Hono
2. Configure PostgreSQL with migrations
3. Implement auth endpoints first
4. Build workout CRUD
5. Add body metrics
6. Deploy MVP
```text
[Task] Done — design shipped
- Prep API requirements (completed)
- Explore architecture options (completed)
- Clarify data and auth needs (completed)
- Deliver API design doc (completed)
```
All set — went from "I need an API" to a concrete design. Ready to start building when you are.
</claude>
</turn>
+242
View File
@@ -0,0 +1,242 @@
# Example: High Start (Level 4)
Clear request with context — minimal clarification needed, fast to delivery.
<turn>
<user>
I need to add a dark mode toggle to my Next.js app. I'm using Tailwind CSS and want to persist the preference in localStorage. Should work with system preference as a default.
</user>
<claude>
```text
[Task] Clear requirements — fast path
- Clarify implementation details (in_progress)
- Deliver dark mode implementation (pending)
```
```text
▓▓▓▓░ Mapped
You've given me most of what I need:
- Next.js + Tailwind CSS
- Toggle component
- localStorage persistence
- System preference default
Assumptions:
- Tailwind's built-in dark mode (class strategy)
- Client-side toggle (no server preference)
- Standard light/dark, no custom themes
Decisions:
- Dark mode with localStorage + system fallback
- Tailwind class strategy
- Toggle UI component
```
Can deliver now, or one quick question: where does the toggle live? (header, settings page, floating button)
[★] If you just want the implementation and will place it yourself, I can skip that question.
```text
[EnterPlanMode]
1. Skip — just give me the implementation
2. Header/navbar — always visible
3. Settings page — dedicated settings area
4. Floating button — corner of screen
5. Something else — different placement
```
</claude>
</turn>
<turn>
<user>
1, I'll put it in my header
</user>
<claude>
```text
▓▓▓▓▓ Ready
All clear — delivering implementation.
```
```text
[Task] Delivering
- Clarify implementation details (completed)
- Deliver dark mode implementation (in_progress)
```
## Dark Mode Implementation
**1. Configure Tailwind** (`tailwind.config.js`):
```javascript
module.exports = {
darkMode: 'class',
// ... rest of config
}
```
**2. Theme Provider** (`components/theme-provider.tsx`):
```typescript
'use client';
import { createContext, useContext, useEffect, useState } from 'react';
type Theme = 'light' | 'dark' | 'system';
const ThemeContext = createContext<{
theme: Theme;
setTheme: (theme: Theme) => void;
}>({ theme: 'system', setTheme: () => {} });
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<Theme>('system');
useEffect(() => {
const stored = localStorage.getItem('theme') as Theme | null;
if (stored) setTheme(stored);
}, []);
useEffect(() => {
const root = document.documentElement;
const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
root.classList.remove('light', 'dark');
if (theme === 'system') {
root.classList.add(systemDark ? 'dark' : 'light');
} else {
root.classList.add(theme);
}
localStorage.setItem('theme', theme);
}, [theme]);
// Listen for system preference changes
useEffect(() => {
const media = window.matchMedia('(prefers-color-scheme: dark)');
const handler = () => {
if (theme === 'system') {
document.documentElement.classList.remove('light', 'dark');
document.documentElement.classList.add(media.matches ? 'dark' : 'light');
}
};
media.addEventListener('change', handler);
return () => media.removeEventListener('change', handler);
}, [theme]);
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}
export const useTheme = () => useContext(ThemeContext);
```
**3. Toggle Component** (`components/theme-toggle.tsx`):
```typescript
'use client';
import { useTheme } from './theme-provider';
import { Sun, Moon, Monitor } from 'lucide-react'; // or your icon library
export function ThemeToggle() {
const { theme, setTheme } = useTheme();
const cycle = () => {
const next = theme === 'light' ? 'dark' : theme === 'dark' ? 'system' : 'light';
setTheme(next);
};
return (
<button
onClick={cycle}
className="p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-800"
aria-label="Toggle theme"
>
{theme === 'light' && <Sun className="w-5 h-5" />}
{theme === 'dark' && <Moon className="w-5 h-5" />}
{theme === 'system' && <Monitor className="w-5 h-5" />}
</button>
);
}
```
**4. Wrap App** (`app/layout.tsx`):
```typescript
import { ThemeProvider } from '@/components/theme-provider';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<ThemeProvider>
{children}
</ThemeProvider>
</body>
</html>
);
}
```
**5. Prevent Flash** (add to `<head>` in layout):
```typescript
<script
dangerouslySetInnerHTML={{
__html: `
(function() {
const theme = localStorage.getItem('theme') || 'system';
const systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const isDark = theme === 'dark' || (theme === 'system' && systemDark);
document.documentElement.classList.add(isDark ? 'dark' : 'light');
})();
`,
}}
/>
```
**6. Use in Header**:
```typescript
import { ThemeToggle } from '@/components/theme-toggle';
export function Header() {
return (
<header className="flex items-center justify-between p-4">
<Logo />
<nav>{/* ... */}</nav>
<ThemeToggle />
</header>
);
}
```
**Usage**:
- Click toggle: cycles light → dark → system → light
- System mode: follows OS preference automatically
- Persists in localStorage across sessions
- No flash on page load
```text
[Task] Done
- Clarify implementation details (completed)
- Deliver dark mode implementation (completed)
```
All set — drop `<ThemeToggle />` in your header and you're good.
</claude>
</turn>