AI Session Handoff — Bernie's Backyard Lawncare Portal
Read before making any code changes. FUSE-safe commit rules are mandatory.
Critical Rules
| Rule | Why |
|---|---|
Write files to /tmp first — never to FUSE path directly | FUSE silently truncates large writes — both disk and blob end up identically wrong |
Use /tmp/lc-git — never git -C <FUSE_path> | FUSE git config is unreadable |
Strip null bytes: raw.rstrip(b'\x00') before hashing | Edit/Write tools append null bytes on FUSE mounts |
| Remove ALL unused TypeScript vars before commit | TS6133 = Cloudflare Pages build failure |
App.tsx at src/App.tsx — not src/components/App.tsx | main.tsx imports ./App from src root |
| Parent = last PUSHED commit SHA — hardcode it | Unpushed intermediate commit = GitHub push rejection |
Where Things Live
| Item | Path |
|---|---|
| Project root | E:\Claude_Projects\sonan-trackers\lawncare-portal\ |
| Worker | worker/index.ts |
| Frontend entry | src/main.tsx → src/App.tsx |
| State + config | src/context/AppContext.tsx |
| Admin shell | src/components/AdminApp.tsx |
| D1 migrations | migrations/0001_init.sql, migrations/0002_settings_seed.sql |
| D1 ID | f029e545-6c71-4762-8776-fd4f930264df (lawncare_db) |
FUSE-Safe Commit (Summary)
# 1. Write file to /tmp/MyFile.tsx (Python, not FUSE path)
# 2. Rsync FUSE .git/objects/ → /tmp/lc-git/.git/objects/
# 3. Hash: data = open('/tmp/MyFile.tsx','rb').read().rstrip(b'\x00')
# sha = subprocess.run(['git','hash-object','-w','--stdin'], input=data, cwd='/tmp/lc-git')
# 4. Build trees with Python ls_tree/mktree (never shell printf/grep)
# 5. git commit-tree <tree> -p <LAST_PUSHED_SHA> -m "..."
# 6. Rsync objects back to FUSE; write ref to .git/refs/heads/main
# 7. Provide: git push origin <sha>:refs/heads/main
Next Steps
Portal is code-complete. Remaining: run D1 migrations on remote DB, set JWT_SECRET, deploy Worker, set Pages env var, fix Pages output dir to dist (no trailing space), add custom domain.