type: user

role: user

content:
In the AgenticLever-website project at `/workspace/extra/projects/AgenticLever` (or similar path), I need to find any planning docs or observations that hint at what should be built next.

Please read:
1. `docs/observations.md` or `observations.md` at the root (Open items section only)
2. Any BACKLOG.md or TODO.md
3. The CLAUDE.md (look for a "Next steps" or "Roadmap" section)

Report any open items, backlog items, or explicitly stated next-step ideas. Under 150 words.

userType: external

entrypoint: sdk-ts

gitBranch: HEAD

slug: mellow-wobbling-swan


type: attachment


type: message

role: assistant

type: text

text: I'll help you find the planning documents in the AgenticLever project. Let me search for these files.

service_tier: standard

attributionAgent: Explore

type: assistant


Bash

command: find /workspace/extra/projects/AgenticLever -maxdepth 2 \( -name "observations.md" -o -name "BACKLOG.md" -o -name "TODO.md" -o -name "CLAUDE.md" \) 2>/dev/null

type: direct

speed: standard


content:
/workspace/extra/projects/AgenticLever/observations.md
/workspace/extra/projects/AgenticLever/CLAUDE.md


text: Now let me read these files:


content:
1	# Observations
2
3	## Open
4	- [ ] `public/` still holds stale copies of index.html/script.js/styles.css/favicon.svg; both Vercel and server.mjs serve from the project root, so the copies drift silently
5
6	## Closed
7	- [x] `tests/api-handler.test.mjs` appends real records to `data/interests.jsonl` — STALE: verified 2026-07-15 that `INTERESTS_FILE` isolation is already in place (the test sets `INTERESTS_FILE`/`DISCOVERY_FILE` to a temp dir before importing the handler; `bun test` leaves `data/interests.jsonl` untouched — same mtime, 47 lines).
8
9	## Notes
10	- context-only; never auto-processed
11


content:
1	# CLAUDE.md
2
3	This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
5	# AgenticLever
6
7	Static landing page with a lead-capture API. Zero npm dependencies — Bun is both the runtime and the test runner.
8
9	## Commands
10
11	- `bun run dev` — start the site with watch mode
12	- `bun run start:local` — start the production server on `PORT` (default `4173`)
13	- `bun test` — run all tests
14	- `bun test tests/interest.test.mjs` — run a single test file
15	- `bun run check` — tests plus a browser-JavaScript build check for `script.js`
16	- `bun run sync-interests --dry-run` — count locally saved leads waiting for the shared Sheet
17	- `bun run sync-interests` — replay all local leads to the configured Sheet; duplicate IDs are ignored
18
19	## Architecture
20
21	The live static files (`index.html`, `script.js`, `styles.css`, `favicon.svg`) sit at the **project root** — both Vercel (`vercel.json` builds array) and `server.mjs` serve from there. The `public/` directory holds stale copies; do not edit it.
22
23	There are two server entry points that share the same `lib/` modules:
24
25	- **`server.mjs`** — Bun-native server using the Web API (`Request`/`Response`). Used for local dev and any non-Vercel deployment. Serves static files from the project root via `lib/static.mjs` and handles `POST /api/interests`.
26	- **`api/interests.js`** — Vercel serverless function using the Node.js `(req, res)` style. Vercel routes `POST /api/interests` here. This file duplicates some logic from `server.mjs` (rate limiting, notify) because Vercel handlers cannot share the Bun Web API surface.
27
28	### lib/ modules
29
30	- **`lib/interest.mjs`** — validation and persistence for both record kinds. `validateInterest`/`saveInterest` append to `data/interests.jsonl`; `validateDiscovery`/`saveDiscovery` append to `data/discovery.jsonl` (both mode 0o600). The `website` field is a honeypot on both forms: any non-empty value throws `InterestValidationError` with `isSpam: true`, which the handler silently acknowledges with 200 OK.
31	- **`lib/delivery.mjs`** — POSTs a saved record to the Google Sheets webhook. Called after every successful save; failure is logged but non-fatal so the local JSONL files remain the source of truth.
32	- **`lib/replay.mjs`** — reads and validates a JSONL file, deduplicates by `id`, and drives delivery. Used only by `scripts/sync-interests.mjs` for manual recovery (interest records only).
33	- **`lib/static.mjs`** — path-traversal-safe file server backed by `Bun.file`. Only used by `server.mjs`; Vercel handles static files natively.
34
35	### Two-stage contact flow
36
37	Stage 1 (interest) captures name/email/business/location plus one problem ("what task keeps stealing your time"). On success, the panel offers three optional discovery questions modeled on question-led selling (see `docs/discovery-playbook.md`): what would change, what it costs today, what solving it would be worth. Stage 2 is always skippable and stage-1 capture never depends on it.
38
39	- Stage 1: `script.js` → `POST /api/interests` → `validateInterest` → `saveInterest` → `deliverInterest` (Sheet row) → ntfy push
40	- Stage 2: `script.js` → `POST /api/interests` with `kind: "discovery"` + `interestId` → `validateDiscovery` → `saveDiscovery` → `deliverInterest` (enriches the Sheet row matched by `interestId`) → high-priority ntfy push
41
42	Health metric for the flow: stage-2 completion rate = `data/discovery.jsonl` records ÷ `data/interests.jsonl` records (or Discovery ID column density in the Sheet).
43
44	## Testing
45
46	Tests live in `tests/`. Run with `bun test`.
47
48	`tests/api-handler.test.mjs` spins up a real Node.js HTTP server using the Vercel handler (`api/interests.js`) to catch `(req, res)` vs Web API incompatibilities. **Any change to `api/interests.js` must pass this test before pushing** — this runtime mismatch crashed silently on Vercel previously. Note: the handler rate-limits 6 POSTs per 10 minutes per IP; tests that add POSTs must use distinct `X-Forwarded-For` values.
49
50	## Deployment
51
52	- **Vercel**: root static files and `api/interests.js` are declared in the `vercel.json` `builds` array. On Vercel, `/tmp/interests.jsonl` and `/tmp/discovery.jsonl` are ephemeral fallback storage; Google Sheets is the durable store.
53	- **Self-hosted**: `bun run start:local` on any host with `PORT` set.
54
55	## Environment variables
56
57	See `.env.example`. Key variables:
58	- `INTEREST_WEBHOOK_URL` + `INTEREST_WEBHOOK_SECRET` — Google Sheets webhook (both required together)
59	- `NTFY_TOPIC` — ntfy.sh topic name or full URL for push notifications per submission
60	- `INTERESTS_FILE` / `DISCOVERY_FILE` — override the JSONL paths (useful in tests or alternate deployments)
61
62	Google Sheets integration setup and redeploy steps: `integrations/google-sheets/README.md`
63


text:
## Planning Summary

**Open Items (observations.md):**
1. **Public directory duplication**: The `public/` directory holds stale copies of `index.html`, `script.js`, `styles.css`, and `favicon.svg`. Both Vercel and the local server serve from the project root, causing silent drift. This needs addressing.

**From CLAUDE.md:**
No explicit "Next Steps" or "Roadmap" section is present. The document focuses on current architecture and testing practices. Notable: the test suite catches Vercel/Bun API mismatches, and there's a two-stage contact flow with stage-2 completion metrics tracked via the Sheet and JSONL records.

**No BACKLOG.md or TODO.md found.**

The main actionable item is **resolving the public directory stale-copy problem** to prevent silent file drift between served and stored versions.