Skip to content

Commit ad9b075

Browse files
addiescode-sjclaude
andcommitted
docs: update guides and gitignore for 0.6.0
- README/AGENTS/CLAUDE: document the model registry + GEMINI_MODEL env, the shared pricing source, ModelAdapter/observability boundaries, and the new eval metrics - Track CLAUDE.md and ignore the generated documents/ artifacts Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent f17ad79 commit ad9b075

4 files changed

Lines changed: 124 additions & 4 deletions

File tree

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,7 @@ vite.config.ts.timestamp-*
142142

143143
# Documentation
144144
chat-documentation/
145-
prd-documentation/user-stories-KR.md
146-
CLAUDE.md
145+
documents/
147146

148147
# Secrets
149148
readmycareer-c547f96903fa.json

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Detailed I/O specs, constraints, and architecture notes for each agent and MCP s
5353
- **MCP runtime**: `@modelcontextprotocol/sdk`
5454
- **Schema validation**: Zod at every agent I/O boundary
5555
- **Language**: TypeScript ESM, Node ≥ 20
56-
- **LLM model**: `gemini-3.1-flash-lite-preview` by default (all agents and MCP skills)
56+
- **LLM model**: `gemini-3.1-flash-lite-preview` by default (all agents and MCP skills). Model ids live in one registry, `agents/lib/models.ts` (`GEMINI_MODEL` / `OPENAI_MODEL`) — never hardcode a model string. In-process code imports from there (app via `@readmycareer/agents/models`); MCP skills run as separate processes and read the same `GEMINI_MODEL` env var, so setting it once switches everything. Token **pricing** (`MODEL_PRICING`) is loaded from `config/model-pricing.json`, the single source the Python eval harness reads too — so live `/admin` cost and offline eval cost stay in sync.
5757
- **Model calls go through the `ModelAdapter` interface** (`agents/lib/model-adapter.ts`) — never construct a provider SDK client inside an agent or the orchestrator. Gemini is the default; the gap-analysis stage is provider-swappable (`provider` arg / `MODEL_PROVIDER` env) via `agents/lib/adapters/`. To add a provider, implement `ModelAdapter` and register it in the `getModelAdapter` factory.
5858
- **Observability**: the orchestrator records per-stage telemetry through `agents/lib/observability.ts` and forwards each metric via the `onMetric` callback. Agents stay free of telemetry/DB concerns; the API route persists metrics to `agent_runs`.
5959
- All agent I/O types must be defined in `agents/types.ts`

CLAUDE.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
readmycareer.com is an AI career-coaching PoC built as a **pnpm monorepo**. A Next.js 14 (App Router) frontend talks to API routes that drive a multi-agent pipeline (Google ADK + Gemini 3.1 Flash Lite Preview). Agents call MCP stdio subprocesses for skill isolation, and use Pinecone RAG plus Supabase (Postgres + Auth + RLS) for persistence.
8+
9+
Pipeline: `pdf-word-to-json` (MCP) → `GapAnalyzerAgent``PlannerAgent` → (after todos done) `ResumeOptimizerAgent`. A separate stateful `ChatQnAAgent` powers the in-app coach. Each step runs inside a **quality gate loop** (≤ 2–3 retries) that validates Zod schemas, plan completeness (≥ 3 todos/week), and date continuity before accepting a result.
10+
11+
See [README.md](./README.md) and [AGENTS.md](./AGENTS.md) for canonical architecture diagrams. Per-subsystem context lives in `.gemini/skills/<name>/SKILL.md` (Gemini CLI workspace skills) — read the matching skill file before editing an agent or MCP skill.
12+
13+
## Repository Context
14+
15+
This is a **pnpm workspace** monorepo (`pnpm-workspace.yaml`). Only `agents/` and `mcp-skills/*` are runtime packages alongside `app/`; everything else is tooling or docs.
16+
17+
```
18+
readmycareer.com/
19+
├── app/ Next.js 14 App Router frontend + API routes
20+
│ └── src/app/
21+
│ ├── (@chat|@goal|@plan|@upload)/ parallel route slots
22+
│ ├── api/ DB + agent entry points (SSE-capable)
23+
│ ├── dashboard/ authenticated user plans
24+
│ ├── admin/ admin-only observability view
25+
│ └── share/ public read-only plan view
26+
├── agents/ Google ADK agents (orchestrator + 4 agents) — runtime
27+
│ ├── orchestrator.ts public API: runCareerAnalysis / runChatQnA / runResumeOptimizer
28+
│ ├── types.ts single source of truth for all agent I/O Zod schemas
29+
│ └── lib/
30+
│ ├── mcp-client.ts connection-pooled MCP stdio client
31+
│ ├── models.ts model ids + pricing registry (reads config/model-pricing.json)
32+
│ ├── model-adapter.ts provider-agnostic LLM adapter; adapters/ = gemini + openai
33+
│ └── observability.ts per-stage telemetry + in-process aggregate
34+
├── mcp-skills/ MCP stdio subprocesses spawned by agents — runtime
35+
│ ├── pdf-word-to-json/ resume extraction
36+
│ ├── career-knowledge-base/ Pinecone RAG
37+
│ ├── career-plan-generator/ structured plan JSON
38+
│ └── resume-generator/ ATS resume synthesis
39+
├── eval/ ragas + agent harness (Python) — ship gate
40+
├── supabase/ SQL migrations + RLS policies
41+
├── config/ shared cross-language config (model-pricing.json)
42+
├── documents/ product/design docs + generated eval report
43+
└── .gemini/skills/ per-subsystem SKILL.md (progressive disclosure)
44+
```
45+
46+
**Rules for working in this repo:**
47+
48+
- **Respect workspace boundaries.** Cross-package imports go through the published workspace name (`@readmycareer/agents`), never via relative `../../agents/...` paths from `app/`.
49+
- **Read the matching `.gemini/skills/<name>/SKILL.md` first** before editing `agents/<name>/index.ts` or `mcp-skills/<name>/src/index.ts`. The global `AGENTS.md` stays lightweight by design — detailed I/O specs live in the skills.
50+
- **Schema migrations** belong in `supabase/` and must include RLS policies. Never modify a published migration; add a new one.
51+
- **Generated artifacts (`dist/`, `.next/`, `node_modules/`) are gitignored.** Do not commit them, and do not edit files under them.
52+
- **Secrets live in `app/.env.local`** (`GOOGLE_API_KEY`, `PINECONE_*`, `NEXT_PUBLIC_SUPABASE_*`). The `readmycareer-*.json` service-account file at the root is a secret — never log, paste, or commit it.
53+
- **Docs that drive behavior**: [README.md](./README.md), [AGENTS.md](./AGENTS.md), [DESIGN.md](./DESIGN.md), [CHANGELOG.md](./CHANGELOG.md). Update [CHANGELOG.md](./CHANGELOG.md) when shipping a user-visible change.
54+
55+
## Architecture Boundaries — Hard Rules
56+
57+
These boundaries exist so the agent layer remains a pure function of its inputs (the eval harness depends on it):
58+
59+
- **Agents do not touch Supabase, Pinecone, or the filesystem directly.** All external access goes through `callMcpTool()` in [agents/lib/mcp-client.ts](agents/lib/mcp-client.ts), or is performed in the API route layer.
60+
- **DB I/O lives in API routes** under [app/src/app/api/](app/src/app/api/) — fetching agent inputs and persisting results (`career_plans`, `gap_analyses`, `roadmaps`, `optimized_resumes`, chat history).
61+
- **MCP skills are spawned via the connection-pooled client** in [agents/lib/mcp-client.ts](agents/lib/mcp-client.ts). Never `spawn()` an MCP subprocess elsewhere.
62+
- **All agent I/O types live in [agents/types.ts](agents/types.ts)** and are validated with Zod at every boundary.
63+
- **Public agent surface** is `runCareerAnalysis`, `runChatQnA`, `runResumeOptimizer` from [agents/orchestrator.ts](agents/orchestrator.ts). App code must not import individual agents.
64+
- **LLM calls go through the `ModelAdapter` interface** ([agents/lib/model-adapter.ts](agents/lib/model-adapter.ts)) — never construct a provider SDK client in an agent or the orchestrator. The gap-analysis stage is provider-swappable (`provider` arg / `MODEL_PROVIDER` env).
65+
- **Observability stays boundary-safe**: the orchestrator emits per-stage metrics via the `onMetric` callback; the API route persists them to `agent_runs`. Agents never log to or touch the DB.
66+
67+
## Gemini / Agent Guidelines
68+
69+
- **Model**: `gemini-3.1-flash-lite-preview` for all agents and MCP skills. Do not silently switch models, and never hardcode a model string — model ids + pricing live in one registry, [agents/lib/models.ts](agents/lib/models.ts) (`GEMINI_MODEL` / `OPENAI_MODEL`; prices from `config/model-pricing.json`). App imports it via `@readmycareer/agents/models`; MCP skills (separate processes) read the same `GEMINI_MODEL` env var, so setting it once switches everything.
70+
- **Framework**: Google ADK TypeScript (`@google/adk`) with `InMemorySessionService`.
71+
- **Caching**: resume tokens use Gemini Context Caching (1h TTL) — preserve cache keys when refactoring.
72+
- **Bilingual output**: all agent output respects `Accept-Language` (en / ko). Never hardcode the response language.
73+
- **Quality gates**: any new agent must be wrapped in a retry loop that validates schema + domain rules before returning. Mirror the pattern already in `gap-analyzer` / `planner`.
74+
75+
## Eval Discipline
76+
77+
The eval suite ([eval/run_evals.sh](eval/run_evals.sh)) is the contract for shipping changes that touch agents, MCP skills, prompts, or RAG:
78+
79+
- **Run `pnpm eval` before declaring agent/MCP/RAG work complete.** A failing eval blocks the change — do **not** weaken thresholds in `agent_harness.py` / `ragas_eval.py` to make it pass.
80+
- The agent harness requires `pnpm dev` to be running on `BASE_URL` (default `http://localhost:3000`).
81+
- Tracked metrics: Schema Compliance, Gap Faithfulness, **Gap Recall/Precision vs. labels**, Plan Completeness, Date Consistency, **Hidden Expectation Coverage**, **Contextual Depth**, p95 Latency, Avg Cost (agents); Faithfulness, Answer Relevancy, Context Precision/Recall, **Grounding/Citation Rate** (RAG). The harness also supports `--repeat N` (variance) and `--save-baseline`/`--compare-baseline` (regression diff).
82+
- Inspect `eval/agent_harness_results.csv`, `eval/ragas_results.csv`, and `eval/grounding_results.csv` — review the CSV, not just the PASS/FAIL summary. Each agent run also regenerates a human-readable Korean report at [documents/agent-eval-report.md](documents/agent-eval-report.md).
83+
- To extend coverage, add cases to [eval/eval_dataset.json](eval/eval_dataset.json) and `eval/fixtures/` rather than relaxing assertions.
84+
85+
## Frontend Guidelines
86+
87+
- **Next.js 14 App Router** — default to **Server Components**; mark Client Components with `"use client"` only when interactivity, hooks, or browser APIs require it.
88+
- **Hybrid rendering / Streaming SSR**:
89+
- Prefetch on the server with `QueryClient.prefetchQuery` and pass through `<HydrationBoundary state={dehydrate(qc)}>` so the client takes over with a warm cache.
90+
- Use `loading.tsx` and `<Suspense>` boundaries to stream above-the-fold UI first; never block a route on a slow agent call.
91+
- For long-running agent runs, stream via Server-Sent Events from `app/src/app/api/` and render incremental progress.
92+
- **TanStack Query (`@tanstack/react-query`)** is the single source of truth for server state on the client. Centralize keys in the shared `queryKeys` module; co-locate query/mutation hooks (`useResumeQuery`, `useCareerPlans`, `useChatMessages`, …) and do not duplicate fetching logic in components.
93+
- **Styling: shadcn/ui + Tailwind CSS only.** No CSS modules, no styled-components, no inline `style` for design concerns.
94+
- Read [DESIGN.md](./DESIGN.md) before any UI work — the Synthetic Intelligence design system is mandatory.
95+
- Never use raw Tailwind palette colors (e.g. `bg-blue-600`, `bg-gray-100`) — use design tokens.
96+
- Use `cn()` (clsx + tailwind-merge) for conditional class composition.
97+
- **i18n**: all user-facing strings go through `next-intl` keys in both `en.json` and `ko.json`. Never hardcode strings in JSX.
98+
- **Code quality**: keep components small and presentational where possible, with explicit prop types. Prefer composition over flag props. Do not introduce abstractions that aren't justified by an existing second caller.
99+
100+
## Commit Workflow
101+
102+
When the user says **"커밋해"**, immediately (no confirmation prompt) split the working tree into logically scoped commits and create them. All commit messages must be **English** and follow Conventional Commits:
103+
104+
```
105+
<type>(<scope>): <subject ≤ 50 chars, imperative, no trailing period>
106+
107+
- bullet 1 (what & why, not how)
108+
- bullet 2
109+
110+
Resolves: #<issue> ← omit entirely if no issue number is associated
111+
```
112+
113+
Common types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`, `perf`, `build`, `ci`. Typical scopes for this repo: `agents`, `gap-analyzer`, `planner`, `chat`, `resume-optimizer`, `mcp`, `rag`, `api`, `dashboard`, `auth`, `i18n`, `eval`, `ui`.

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,14 @@ without touching agent logic or prompts:
200200

201201
| Provider | Default model | Context cache | When to use |
202202
| --- | --- | --- | --- |
203-
| **Gemini** (default) | `gemini-3.1-flash-lite-preview` | Yes (1h TTL) | Default — lowest cost, multimodal, free tier |
203+
| **Gemini** (default) | `gemini-3.1-flash-lite-preview` (`GEMINI_MODEL`) | Yes (1h TTL) | Default — lowest cost, multimodal, free tier |
204204
| **OpenAI** | `gpt-4o-mini` (`OPENAI_MODEL`) | No | Cross-check quality; stronger reasoning on a borderline gap analysis |
205205

206+
Model identifiers and pricing live in a single registry,
207+
[agents/lib/models.ts](./agents/lib/models.ts); every agent, app route, and MCP skill resolves
208+
its model from there, so a model bump (or the `GEMINI_MODEL` env override) takes effect
209+
everywhere from one place.
210+
206211
Select the provider for the gap-analysis stage per request (`"provider": "openai"` in the
207212
`/api/analyze` body) or globally via `MODEL_PROVIDER`. Planning stays on Gemini to preserve the
208213
context-cache path. The eval layer compares providers head-to-head:
@@ -300,6 +305,9 @@ GOOGLE_DRIVE_FOLDER_ID_JD=
300305
GOOGLE_DRIVE_FOLDER_ID_REF=
301306
302307
# Optional — model abstraction
308+
# GEMINI_MODEL= # override the Gemini model for ALL agents, app routes, and
309+
# # MCP skills at once (single switch point; default
310+
# # gemini-3.1-flash-lite-preview). See agents/lib/models.ts.
303311
# MODEL_PROVIDER=gemini # default provider for the gap-analysis stage (gemini | openai)
304312
# OPENAI_API_KEY= # required only when running a stage on OpenAI
305313
# OPENAI_MODEL=gpt-4o-mini # override the default OpenAI model

0 commit comments

Comments
 (0)