Imported from zr0aces/SarnFund (
AGENTS.md). Install upstream withnpx skills add zr0aces/SarnFund. Copyright stays with the author.
AGY.md
This file provides guidance to Google Antigravity (AGY) when working with code in this repository.
SarnFund — AI Coding Agent Guidelines
SarnFund is a mutual fund analytics dashboard for Thai investments (RMF, SSF, ThaiESG/ESG, ThaiESGX/ESGX, ETF, S&P 500). It fetches data from the SEC Thailand Open Data API v2 (api.sec.or.th) using subscription-key authentication.
1. Quick Reference & Commands
# Backend Commands (run from backend/ directory)
cd backend && npm run dev # nodemon watch mode, API on :3001
cd backend && npm start # production start
cd backend && npm test # run automated unit & integration tests
cd backend && npm run scrape # run two-phase scrape manually (2–5 min initial run)
cd backend && npm run scrape:refresh # scrape with forced registry rebuild
cd backend && npm run init # seed initial mock data without API scrape
# Frontend Commands (run from frontend/ directory)
cd frontend && npm run dev # Vite dev server on :5173 (proxies /api/* to :3001)
cd frontend && npm run build # production build → dist/
cd frontend && npm run lint # ESLint execution (max-warnings 0 enforced)
cd frontend && npm run preview # preview production build locally
# Data Ingestion & Refresh Commands (run from project root)
node scripts/fetch-funds.js # scrape latest NAV using cached registry (auto-detects Docker)
node scripts/fetch-funds.js --refresh # scrape with forced registry rebuild
docker compose exec backend npm run scrape # scrape directly inside running Docker container
docker compose exec backend npm run scrape:refresh # scrape with forced registry rebuild inside container
# Versioning Commands (run from project root)
node scripts/sync-version.mjs # metadata-only sync: manifests + local lock versions
node scripts/sync-version.mjs --check # verify version consistency across files
node scripts/release.mjs # prepare only: bump, sync, check
node scripts/release.mjs --help # examples and independent --build / --tag opt-ins
node --test scripts/version-control.test.mjs # release-tooling regression suite
Local release never installs dependencies or pushes. Build precedes exact-path commit and annotated local tag when requested; build failure retains prepared metadata and blocks tagging. To tag an already-prepared version, use printed Git commands instead of rerunning release. Root VERSION is authoritative; missing/malformed source fails.
2. Supported AI Coding Tools & Architecture
SarnFund supports three AI coding tools:
- Claude Code (
CLAUDE.md) - Google Antigravity (AGY) (
AGENTS.md) - Codex AI (
CODEX.md)
All instruction files follow standardized formatting, taxonomy, and operational boundaries.
Project Architecture & Service Map
| Service | Image | Role | Port |
|---|---|---|---|
| backend | built from ./backend |
Express API, SEC API v2 connector, cron scraper | 3001 (internal) |
| frontend | built from ./frontend |
One-shot React/Vite builder (exits after copying dist/) |
N/A |
| nginx | nginx:1.27-alpine |
Reverse proxy & static server gateway | 8091 (public) |
3. Core Development Practices & Guidelines
- Module Format: Pure ESM (
"type": "module") in both backend and frontend. Useimport/exportonly; do not userequire(). - UI/UX & Design System: Dark Obsidian glassmorphic telemetry theme (
#090D16), Kanit font for headings/titles, Prompt font for body copy/tables, JetBrains Mono for metrics. Responsive dynamic layout. - Error Handling: Use
numVal(val, fallback)for SEC API numeric parsing ("-"andnullfallback). UserunBatched()for rate-limiting. - Catalog Retention & Resilience Invariant: Never drop or purge registered funds from datasets or UI tables when upstream SEC API v2 returns HTTP 204 No Content, missing NAV, or zero. Scraper must preserve cached NAV or build fallback metadata records (
nav: null,navUnavailable: true). Frontend components must rendernav: nullgracefully using'—'and'Date unavailable'.backend/seed-data.jsmust maintain exact 1-to-1 parity with all 794 funds indata/fund-registry.json(RMF: 379, SSF: 299, ESG: 38, ESGX: 34, ETF: 11, SP: 33). - Security: Never log API keys or secrets. Store credentials in root
.env.
4. Key Source Files
| File | Purpose |
|---|---|
| backend/sec-api-connector.js | SEC API v2 connector, rate limiting, and 401 failover handling |
| backend/scraper.js | Two-phase scraper (Phase 1: Fund Registry, Phase 2: Daily NAV) with zero-purge retention |
| backend/seed-data.js | Authoritative baseline seed dataset (794 funds across RMF, SSF, ESG, ESGX, ETF, SP) |
| backend/sp-catalog.js | Curated S&P 500 catalog mapping across 12 AMCs to SEC API project IDs |
| backend/sp-integration.test.js | Automated tests for catalog, trailing returns, and risk spectrum |
| backend/server.js | Express endpoints, CORS, cron scheduling (06:30 PM daily) |
| frontend/src/hooks/useFundData.js | Dual-layer cache hook (fund_cache_v4_*) |
| VERSION | Single source of truth for CalVer versioning (YYYY.M.MINOR) |
5. Verification Checklist
Before completing any task:
- Run
cd frontend && npm run lintto verify zero ESLint warnings/errors. - Run
cd frontend && npm run buildto verify frontend production build succeeds. - Run
cd backend && npm testto verify backend calculations and integration pass. - Run
node scripts/sync-version.mjs --checkto verify version alignment.
Plans
When creating a plan file under docs/plans/, the filename must include the creation date using the format YYYY-MM-dd-plan-name.md.
Use the actual date when the plan is created.
Use a clear, descriptive name for plan-name.
Example: 2026-09-12-document-figures-alignment.md
Shared memory and agent state
This project uses agent-parity to keep memory, skills, instructions, and agent wiring portable across agents and machines; treat its managed files as repository state, not disposable generated files.
A shared memory MCP server persists context across sessions and agents (memory_recent, memory_add, memory_search, memory_get). Each tool's description says when to call it — follow them. Store durable context, not secrets, one-off chatter, or facts another source already enforces.
Cross-agent bootstrap: at the start of the first user turn, if the memory tools are unavailable, repair only the one config your own client reads — Claude Code .mcp.json, Cursor .cursor/mcp.json, Codex .codex/config.toml, Antigravity .agents/mcp_config.json — and leave the other three untouched, because a different-OS agent may share this working tree and need the other launcher. In that file, on native Windows replace an exact .agent-parity/mcp/memory/run.sh value with .agent-parity/mcp/memory/run.cmd, and on Unix-like systems make the inverse replacement. Use built-in file read/edit tools, not project scripts or a command the user must type. Preserve a missing, malformed, or custom memory registration. If you changed the file, tell the user that the current agent must be restarted and do not claim the memory tools are available in the current session.
When asked for agent-parity status in a conversation, run the project-local status command and call memory_recent to verify the current session; never infer tool availability from a static tool list because MCP tools may load lazily. If wiring is healthy but that call is unavailable, tell the user to restart the agent session. If wiring is missing, stale, conflicting, or invalid, offer to inspect the named configuration files because unrelated user settings may also prevent the agent from loading them.
When pushing or handing off through Git, commit and include every changed agent-parity-managed file. Never select only some managed changes or bypass the pre-push guard.
