## Routes added to artifacts/api-server/src/routes/testkit.ts
### GET /api/testkit/plan
- Returns TIMMY_TEST_PLAN.md verbatim as text/markdown; charset=utf-8
- Reads file at request time (not on startup) so edits to the plan are picked
up without server restart
- Path resolves via import.meta.url + dirname() → 4 levels up to project root
(handles both dev/tsx and compiled dist/routes/ directories)
### GET /api/testkit/report
- Returns only the content from "## Report template" heading to end-of-file
- Content-Type: text/plain; charset=utf-8 — ready to copy and fill in
- Slice is found with indexOf("## Report template"); 500 if marker absent
- Uses the same PLAN_PATH as /api/testkit/plan (single source of truth)
## Deviation: __dirname → import.meta.url
Original plan said "resolve relative to project root regardless of cwd".
The codebase runs as ESM (tsx / ts-node with ESM), so __dirname is not
defined. Fixed by using dirname(fileURLToPath(import.meta.url)) instead —
equivalent semantics, correct in both dev and compiled output.
## AGENTS.md — Testing section added
Three-step workflow documented between "Branch and PR conventions" and
"Stub mode" sections:
1. curl <BASE>/api/testkit/plan — fetch plan before starting
2. curl -s <BASE>/api/testkit | bash — run suite after implementing
3. curl <BASE>/api/testkit/report — fetch report template to fill in
## Unchanged
- GET /api/testkit bash script generation: untouched
- No new test cases or script modifications
## TypeScript: 0 errors. Smoke tests all pass:
- /api/testkit/plan → 200 text/markdown, full TIMMY_TEST_PLAN.md content
- /api/testkit/report → 200 text/plain, starts at "## Report template"
- /api/testkit → 200 bash script, unchanged
96 lines
3.2 KiB
Markdown
96 lines
3.2 KiB
Markdown
# AGENTS.md — Timmy Tower World
|
|
|
|
Development conventions and workflows for agents and contributors.
|
|
|
|
## One-time setup
|
|
|
|
```bash
|
|
make install
|
|
```
|
|
|
|
This activates git hooks that run `typecheck` and `lint` before every commit and push.
|
|
|
|
## Quality checks
|
|
|
|
```bash
|
|
pnpm run typecheck # TypeScript type-checking (tsc --build across all packages)
|
|
pnpm run lint # ESLint across all TypeScript source files
|
|
make check # Run both in sequence (same as CI)
|
|
```
|
|
|
|
## Pushing to Gitea
|
|
|
|
All pushes go through the bore tunnel helper script (see replit.md for full docs):
|
|
|
|
```bash
|
|
bash scripts/push-to-gitea.sh [PORT]
|
|
```
|
|
|
|
- First call after bore starts: pass the port once — it's saved for the session
|
|
- Subsequent calls: no argument needed, reads from `.bore-port`
|
|
- Bore port changes every restart — pass the new port to update
|
|
|
|
Set `GITEA_TOKEN` or write the token to `.gitea-credentials` (gitignored). Never commit credentials.
|
|
|
|
## Branch and PR conventions
|
|
|
|
- **Never push directly to `main`** — Gitea enforces branch protection
|
|
- Every change lives on a feature branch: `feat/<slug>`, `fix/<slug>`, `chore/<slug>`
|
|
- Open a PR on Gitea and squash-merge after review
|
|
- CI runs `pnpm typecheck && pnpm lint` on every PR automatically
|
|
|
|
## Testing
|
|
|
|
Executor agents should follow this three-step workflow when implementing or verifying any change:
|
|
|
|
**1. Fetch the test plan before starting**
|
|
```bash
|
|
curl <BASE>/api/testkit/plan
|
|
```
|
|
Returns `TIMMY_TEST_PLAN.md` — full architecture notes, route descriptions, and expected behaviour for all 24 tests. Read this first so you understand what each endpoint is supposed to do before touching the code.
|
|
|
|
**2. Run the full test suite after implementing**
|
|
```bash
|
|
curl -s <BASE>/api/testkit | bash
|
|
```
|
|
The server returns a self-contained bash script with the base URL already baked in. Requirements: `curl`, `bash`, `jq` — nothing else. All 24 tests must pass (FAIL=0) before submitting.
|
|
|
|
**3. Fill in and submit the report**
|
|
```bash
|
|
curl <BASE>/api/testkit/report
|
|
```
|
|
Returns just the report template section ready to copy and fill in. Attach the completed report to your PR or task output.
|
|
|
|
Where `<BASE>` is the running server URL, e.g. `http://localhost:8080` locally or the Replit dev URL in CI.
|
|
|
|
## Stub mode
|
|
|
|
The API server starts without Lightning or AI credentials:
|
|
|
|
- **LNbits stub**: invoices are simulated in-memory. Mark paid via `POST /api/dev/stub/pay/:hash`
|
|
- **AI stub**: Anthropic credentials absent → canned AI responses. Set `AI_INTEGRATIONS_ANTHROPIC_API_KEY` for real AI
|
|
|
|
## Workspace structure
|
|
|
|
```
|
|
artifacts/api-server/ — Express 5 API server (@workspace/api-server)
|
|
lib/db/ — Drizzle ORM schema + PostgreSQL client (@workspace/db)
|
|
lib/api-spec/ — OpenAPI spec + Orval codegen
|
|
lib/api-zod/ — Generated Zod schemas (do not edit by hand)
|
|
lib/api-client-react/ — Generated React Query hooks (do not edit by hand)
|
|
scripts/ — Utility scripts (@workspace/scripts)
|
|
```
|
|
|
|
## Running the API server
|
|
|
|
```bash
|
|
pnpm --filter @workspace/api-server run dev
|
|
```
|
|
|
|
## Gitea repos
|
|
|
|
| Repo | Purpose |
|
|
|---|---|
|
|
| `replit/token-gated-economy` | This repo — TypeScript API |
|
|
| `perplexity/the-matrix` | Three.js 3D world frontend |
|