# Recipe Manager — Agent Instructions
**Purpose:** How agents should approach development on this project
**Last Updated:** 2026-03-23
---
## Core Principles
### 1. Orientation First
Every time you wake up (new session):
**PRE-FLIGHT GUARD (mandatory):**
- Verify these files exist at absolute path `/home/paulh/.openclaw/workspace/projects/recipe-manager/`:
- `AGENT_INSTRUCTIONS.md`
- `TODO.md`
- If either is missing, stop immediately and report:
- `STUCK: bad working dir or missing harness files at /home/paulh/.openclaw/workspace/projects/recipe-manager`
Then continue orientation:
1. Read `PROJECT.md` — What are we building?
2. Read `ARCHITECTURE.md` — How are we building it?
3. Read `ROADMAP.md` — What's next?
4. Read `git log --oneline -10` — What happened recently?
5. Check `TODO.md` (if exists) — Any pending tasks?
**Never start coding without context.**
---
## Development Loop
### The Agent Workflow (Single Iteration)
```
┌─────────────────────────────────────────────────┐
│ 1. ORIENT Read context files, git log │
└────────────┬────────────────────────────────────┘
│
┌────────────┴────────────────────────────────────┐
│ 2. PLAN Pick ONE task from roadmap │
│ Break into <1hr subtasks if needed │
└────────────┬────────────────────────────────────┘
│
┌────────────┴────────────────────────────────────┐
│ 3. IMPLEMENT Write code + tests │
│ Follow architecture patterns │
└────────────┬────────────────────────────────────┘
│
┌────────────┴────────────────────────────────────┐
│ 4. VERIFY Run tests, lint, manual check │
│ Does it meet acceptance criteria? │
└────────────┬────────────────────────────────────┘
│
┌────────────┴────────────────────────────────────┐
│ 5. COMMIT Conventional commit message │
│ Update docs (README, ADR, etc.) │
└────────────┬────────────────────────────────────┘
│
┌────────────┴────────────────────────────────────┐
│ 6. REPORT Summarize what you did + what's │
│ next (or escalate if blocked) │
└─────────────────────────────────────────────────┘
```
**One loop = one commit.** Don't try to do everything at once.
---
## Task Selection Rules
### What to Work On
1. **Check TODO.md first** — treat it as the authoritative queue
2. **Pick the first unchecked task** in the current active phase section
3. **If all phase tasks are done,** report completion and request milestone transition
4. **Do not jump to backlog phases** unless TODO explicitly marks the new phase active
### How to Break Down Tasks
**Good task (1-4 hours):**
- "Implement recipe list API endpoint with pagination"
- "Add tag filtering to search UI"
- "Write E2E test for cook mode"
**Bad task (too big):**
- "Build entire recipe import system"
- "Finish frontend"
**If task feels big (>4 hours),** break it into subtasks and commit each one.
---
## Code Quality Standards
### TypeScript
- ✅ Strict mode enabled
- ✅ No `any` types (use `unknown` if needed)
- ✅ All public APIs have JSDoc comments
- ✅ Interfaces for all data models
### Testing
- ✅ Unit test new business logic (services, utilities)
- ✅ Integration test API endpoints
- ✅ E2E test critical user flows (cook mode, search)
- ✅ Aim for >80% coverage on core logic
### Commits
- ✅ Conventional Commits format: `type(scope): description`
- `feat:` new feature
- `fix:` bug fix
- `docs:` documentation only
- `test:` test additions/changes
- `refactor:` code restructure (no behavior change)
- `chore:` tooling, dependencies
- ✅ Descriptive messages (not "fix stuff" or "wip")
- ✅ Commit working code only (tests pass)
### Documentation
- ✅ Update README when setup changes
- ✅ Add ADR (Architecture Decision Record) in `docs/` for significant choices
- Format: `ADR-001-why-sqlite.md`, `ADR-002-recipe-scraping-strategy.md`
- ✅ Update API docs when endpoints change
- ✅ Keep TODO.md current (add new tasks, remove completed)
---
## Common Patterns
### API Endpoint Template
```typescript
// src/routes/recipes.ts
import { Router } from 'express';
import { z } from 'zod';
import { RecipeService } from '../services/RecipeService';
const router = Router();
const recipeService = new RecipeService();
// Validation schema
const createRecipeSchema = z.object({
title: z.string().min(1),
ingredients: z.array(z.string()),
instructions: z.array(z.string()),
// ...
});
router.post('/recipes', async (req, res) => {
try {
const data = createRecipeSchema.parse(req.body);
const recipe = await recipeService.create(data);
res.json({ success: true, data: recipe });
} catch (error) {
if (error instanceof z.ZodError) {
res.status(400).json({ success: false, error: error.errors });
} else {
res.status(500).json({ success: false, error: 'Internal error' });
}
}
});
export default router;
```
### React Component Template
```typescript
// src/components/RecipeCard.tsx
import { Recipe } from '../types/recipe';
interface RecipeCardProps {
recipe: Recipe;
onEdit: (id: number) => void;
onDelete: (id: number) => void;
}
export function RecipeCard({ recipe, onEdit, onDelete }: RecipeCardProps) {
return (
{recipe.title}
{recipe.description}
{/* ... */}
);
}
```
### Database Query Template
```typescript
// src/repositories/RecipeRepository.ts
import Database from 'better-sqlite3';
import { Recipe } from '../types/recipe';
export class RecipeRepository {
constructor(private db: Database.Database) {}
findAll(): Recipe[] {
const stmt = this.db.prepare('SELECT * FROM recipes ORDER BY created_at DESC');
return stmt.all() as Recipe[];
}
findById(id: number): Recipe | undefined {
const stmt = this.db.prepare('SELECT * FROM recipes WHERE id = ?');
return stmt.get(id) as Recipe | undefined;
}
// ...
}
```
---
## Error Handling
### When Things Go Wrong
1. **Build errors:** Fix immediately, don't commit broken code
2. **Test failures:** Investigate, fix, re-run
3. **Stuck on implementation (>30 min):**
- Document what you tried
- Explain the blocker
- Ask Paul for guidance
4. **Unclear requirements:** Propose 2-3 options, ask Paul to choose
### Never Guess
If PROJECT.md or ARCHITECTURE.md doesn't specify:
- **Good:** "Should recipe images be stored in SQLite or filesystem? I recommend filesystem for simpler backups."
- **Bad:** Just implementing without asking
---
## Error Signals (CRITICAL)
If you encounter a blocker or error, **DO NOT fail silently**. Include one of these signals in your response:
### STUCK Signal
```markdown
⚠️ **STUCK:** Cannot complete task "[task name]"
**Attempted:**
- [what you tried]
- [what you tried]
**Error/Blocker:**
[exact error message or description of the problem]
**Need from Paul:**
[specific question or decision needed]
```
### ERROR Signal
```markdown
❌ **ERROR:** Build/test failure
**Command:** `[exact command that failed]`
**Error output:**
```
[paste last 20 lines of error]
```
**Context:** [what you were trying to do]
```
### ALL_TASKS_COMPLETE Signal
```markdown
🎉 **ALL_TASKS_COMPLETE**
[summary of what was built]
[deployment instructions]
```
---
## Communication Protocol
### Progress Updates (After Each Commit)
```markdown
✅ **Completed:** Added recipe list API endpoint with pagination
- Implemented GET /api/recipes with offset/limit
- Added integration tests (100% coverage)
- Updated API docs
**Next up:** Recipe detail view UI component
**ETA:** 1-2 hours
```
### Milestone Completion
```markdown
🎉 **MVP Complete!**
All MVP features implemented:
- ✅ Manual recipe entry
- ✅ Recipe CRUD operations
- ✅ Tagging & search
- ✅ Cook mode with wake lock
- ✅ Docker deployment
**Test results:** 47/47 passing
**Documentation:** README, API docs, user guide updated
**Deployment:** Tested locally, ready for paje.ca
**Awaiting approval** to start v1.0 milestone (recipe scraping).
```
### Escalation (Blocked)
```markdown
⚠️ **Blocked:** Recipe scraping strategy unclear
**Context:** Working on browser extension for recipe import. Need decision on:
1. **Puppeteer vs Cheerio?**
- Puppeteer: Handles JS-rendered sites, heavier
- Cheerio: Fast, static HTML only
2. **Where to run scraping?**
- Client-side (extension scrapes, sends JSON to API)
- Server-side (extension sends URL, server scrapes)
**Recommendation:** Cheerio for v1 (80% of sites), Puppeteer later if needed. Server-side scraping for easier updates.
**Action needed:** Paul, which approach do you prefer?
```
---
## Anti-Patterns (Don't Do This)
❌ **Committing without testing**
❌ **Changing architecture without documenting (ADR)**
❌ **Working on multiple unrelated tasks in one commit**
❌ **Ignoring linting errors "to fix later"**
❌ **Hardcoding values that should be env vars**
❌ **Skipping documentation updates**
❌ **Assuming requirements without asking**
---
## Quick Reference
### Starting a new feature
```bash
git pull origin main
git checkout -b feat/recipe-scaling
# ... code ...
npm test
git add .
git commit -m "feat: add recipe serving size scaling"
git push origin feat/recipe-scaling
```
### Running tests
```bash
npm test # All tests
npm test -- RecipeService # Specific file
npm run test:coverage # Coverage report
```
### Building & deploying
```bash
docker-compose build # Build containers
docker-compose up -d # Start services
docker-compose logs -f # Watch logs
```
---
## Success Metrics
You're doing it right if:
- ✅ Every commit is small, focused, tested
- ✅ Paul wakes up to completed features, not questions
- ✅ Tests pass consistently
- ✅ Documentation stays current
- ✅ Code is readable (you're writing for future-you)
---
## OpenClaw Environment Notes
### File Access
- Working directory: `/home/paulh/.openclaw/workspace/projects/recipe-manager`
- **CRITICAL:** Use absolute paths in all exec commands
- The `~` shorthand does NOT work in exec — use `/home/paulh/` instead
### Build Commands
- Use `cd /absolute/path && command` pattern
- Example: `cd /home/paulh/.openclaw/workspace/projects/recipe-manager && npm test`
- Never rely on implicit working directory
### Git
- Commit after each completed task
- Use conventional commit format: `feat(scope): description`
- Don't push — Paul will review and push
### Exit Signals
- Include **ALL_TASKS_COMPLETE** when all TODO.md tasks are checked
- Include **STUCK:** or **ERROR:** if blocked (see Error Signals above)
- Always exit after ONE commit (don't chain multiple tasks)
---
_Remember: You're not just writing code—you're building a product Paul's family will use. Quality matters._