Skip to content

Commit 241c7fb

Browse files
committed
2 parents 5b95eaf + 13b5b28 commit 241c7fb

201 files changed

Lines changed: 23877 additions & 1215 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,7 @@ MATH_AI_SERVICE_URL="http://localhost:8000"
3333
LOG_LEVEL="debug"
3434
# 실행 환경 (development | production | test)
3535
NODE_ENV="development"
36+
37+
# === Judge0 CE (코드 실행) ===
38+
# Judge0 CE API 서버 URL (docker-compose로 실행 시 기본값)
39+
JUDGE0_API_URL="http://localhost:2358"

.github/workflows/ci.yml

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
env:
10+
NODE_VERSION: "20"
11+
PNPM_VERSION: "10"
12+
DATABASE_URL: "postgresql://postgres:postgres@localhost:5432/mathitem_test?schema=public"
13+
DIRECT_URL: "postgresql://postgres:postgres@localhost:5432/mathitem_test?schema=public"
14+
TEST_DATABASE_URL: "postgresql://postgres:postgres@localhost:5432/mathitem_test?schema=public"
15+
REDIS_URL: "redis://localhost:6379"
16+
MEILISEARCH_HOST: "http://localhost:7700"
17+
MEILISEARCH_MASTER_KEY: "ci-master-key"
18+
AUTH_SECRET: "ci-auth-secret-at-least-32-chars-long-value"
19+
NEXTAUTH_URL: "http://localhost:3000"
20+
21+
jobs:
22+
lint:
23+
name: Lint
24+
runs-on: ubuntu-latest
25+
steps:
26+
- uses: actions/checkout@v4
27+
- uses: pnpm/action-setup@v4
28+
with:
29+
version: ${{ env.PNPM_VERSION }}
30+
- uses: actions/setup-node@v4
31+
with:
32+
node-version: ${{ env.NODE_VERSION }}
33+
cache: "pnpm"
34+
- run: pnpm install --frozen-lockfile
35+
- run: pnpm --filter @math-item-os/db exec prisma generate
36+
- run: pnpm lint
37+
38+
typecheck:
39+
name: Typecheck
40+
runs-on: ubuntu-latest
41+
steps:
42+
- uses: actions/checkout@v4
43+
- uses: pnpm/action-setup@v4
44+
with:
45+
version: ${{ env.PNPM_VERSION }}
46+
- uses: actions/setup-node@v4
47+
with:
48+
node-version: ${{ env.NODE_VERSION }}
49+
cache: "pnpm"
50+
- run: pnpm install --frozen-lockfile
51+
- run: pnpm --filter @math-item-os/db exec prisma generate
52+
- run: pnpm --filter @math-item-os/web exec tsc --noEmit
53+
54+
test-unit:
55+
name: Unit Tests + Coverage
56+
runs-on: ubuntu-latest
57+
services:
58+
postgres:
59+
image: pgvector/pgvector:pg17
60+
env:
61+
POSTGRES_DB: mathitem_test
62+
POSTGRES_USER: postgres
63+
POSTGRES_PASSWORD: postgres
64+
ports:
65+
- 5432:5432
66+
options: >-
67+
--health-cmd "pg_isready -U postgres -d mathitem_test"
68+
--health-interval 10s
69+
--health-timeout 5s
70+
--health-retries 10
71+
redis:
72+
image: redis:7
73+
ports:
74+
- 6379:6379
75+
options: >-
76+
--health-cmd "redis-cli ping"
77+
--health-interval 10s
78+
--health-timeout 5s
79+
--health-retries 5
80+
steps:
81+
- uses: actions/checkout@v4
82+
- uses: pnpm/action-setup@v4
83+
with:
84+
version: ${{ env.PNPM_VERSION }}
85+
- uses: actions/setup-node@v4
86+
with:
87+
node-version: ${{ env.NODE_VERSION }}
88+
cache: "pnpm"
89+
- run: pnpm install --frozen-lockfile
90+
- name: Enable required Postgres extensions
91+
run: |
92+
PGPASSWORD=postgres psql -h localhost -U postgres -d mathitem_test \
93+
-c "CREATE EXTENSION IF NOT EXISTS vector;" \
94+
-c "CREATE EXTENSION IF NOT EXISTS ltree;" \
95+
-c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"
96+
- name: Prisma generate + migrate + push schema drift
97+
run: |
98+
pnpm --filter @math-item-os/db exec prisma generate
99+
pnpm --filter @math-item-os/db exec prisma migrate deploy
100+
pnpm --filter @math-item-os/db exec prisma db push --skip-generate --accept-data-loss
101+
- name: Run vitest with coverage
102+
run: pnpm --filter @math-item-os/web test:coverage
103+
- name: Upload coverage artifact
104+
if: always()
105+
uses: actions/upload-artifact@v4
106+
with:
107+
name: web-coverage
108+
path: apps/web/coverage/
109+
retention-days: 14
110+
111+
test-e2e:
112+
name: E2E Tests (Playwright)
113+
runs-on: ubuntu-latest
114+
needs: test-unit
115+
services:
116+
postgres:
117+
image: pgvector/pgvector:pg17
118+
env:
119+
POSTGRES_DB: mathitem_test
120+
POSTGRES_USER: postgres
121+
POSTGRES_PASSWORD: postgres
122+
ports:
123+
- 5432:5432
124+
options: >-
125+
--health-cmd "pg_isready -U postgres -d mathitem_test"
126+
--health-interval 10s
127+
--health-timeout 5s
128+
--health-retries 10
129+
redis:
130+
image: redis:7
131+
ports:
132+
- 6379:6379
133+
options: >-
134+
--health-cmd "redis-cli ping"
135+
--health-interval 10s
136+
--health-timeout 5s
137+
--health-retries 5
138+
meilisearch:
139+
image: getmeili/meilisearch:v1.12
140+
env:
141+
MEILI_MASTER_KEY: ci-master-key
142+
MEILI_ENV: development
143+
ports:
144+
- 7700:7700
145+
steps:
146+
- uses: actions/checkout@v4
147+
- uses: pnpm/action-setup@v4
148+
with:
149+
version: ${{ env.PNPM_VERSION }}
150+
- uses: actions/setup-node@v4
151+
with:
152+
node-version: ${{ env.NODE_VERSION }}
153+
cache: "pnpm"
154+
- run: pnpm install --frozen-lockfile
155+
- name: Enable required Postgres extensions
156+
run: |
157+
PGPASSWORD=postgres psql -h localhost -U postgres -d mathitem_test \
158+
-c "CREATE EXTENSION IF NOT EXISTS vector;" \
159+
-c "CREATE EXTENSION IF NOT EXISTS ltree;" \
160+
-c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"
161+
- run: pnpm --filter @math-item-os/db exec prisma generate
162+
- run: pnpm --filter @math-item-os/db exec prisma db push --skip-generate --accept-data-loss
163+
- name: Install Playwright browsers
164+
run: pnpm --filter @math-item-os/web exec playwright install --with-deps chromium
165+
- name: Run Playwright
166+
run: pnpm --filter @math-item-os/web test:e2e
167+
- name: Upload Playwright report
168+
if: always()
169+
uses: actions/upload-artifact@v4
170+
with:
171+
name: playwright-report
172+
path: apps/web/playwright-report/
173+
retention-days: 14
174+
175+
test-python:
176+
name: Python (math-ai) Tests
177+
runs-on: ubuntu-latest
178+
defaults:
179+
run:
180+
working-directory: services/math-ai
181+
steps:
182+
- uses: actions/checkout@v4
183+
- uses: actions/setup-python@v5
184+
with:
185+
python-version: "3.11"
186+
cache: "pip"
187+
cache-dependency-path: services/math-ai/requirements.txt
188+
- name: Install dependencies
189+
run: |
190+
python -m pip install --upgrade pip
191+
pip install -r requirements.txt
192+
if [ -f requirements-dev.txt ]; then pip install -r requirements-dev.txt; fi
193+
- name: Run pytest
194+
run: |
195+
if [ -d tests ]; then
196+
pytest tests --tb=short
197+
else
198+
echo "No tests directory — skipping"
199+
fi

.specify/memory/constitution.md

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,31 @@
11
<!-- SYNC IMPACT REPORT
2-
Version change: 1.0.0 -> 2.0.0 (MAJOR - all principles redefined)
3-
Reason: Project scope changed from HWP-to-HTML converter to
4-
Math Knowledge Graph + Item OS (LaTeX math item platform)
2+
Version change: 2.0.0 -> 2.0.1 (PATCH - clarifications reconcile constitution with shipped reality)
3+
Reason: Two implementation decisions diverged from the v2.0.0 text and needed
4+
to be ratified as explicit carve-outs rather than silent exceptions:
5+
(a) bodyLatex fields store mixed Korean prose + LaTeX fragments
6+
(pdf.service.ts:renderMixedLatex), not pure LaTeX
7+
(b) remediation paths include reviewed+draft items, not approved-only
8+
(remediation.service.ts:297)
59
610
Principles modified:
7-
I. Parsing Fidelity -> Math Representation Integrity
8-
II. Output Correctness and Accessibility -> Explainable Knowledge Structure
9-
III. Regression-Guarded Testing -> Automated Correctness Verification
10-
IV. Bounded Resource Consumption -> Curriculum-Aligned Data Integrity
11+
I. Math Representation Integrity - clarified LaTeX scope (prose+fragments
12+
vs. pure LaTeX CAS targets)
13+
IV. Curriculum-Aligned Data Integrity - clarified approved-only visibility
14+
with an explicit remediation-path exception
1115
1216
Sections modified:
13-
Quality Gates: HWP/HTML-specific gates removed, CAS/search gates added
14-
Development Workflow: HWP corpus management -> math item fixture management
17+
None (Quality Gates, Development Workflow, Governance unchanged)
1518
1619
Templates requiring updates:
1720
- .specify/templates/plan-template.md: ✅ no changes needed (Constitution Check is dynamic)
1821
- .specify/templates/spec-template.md: ✅ no changes needed (generic template)
1922
- .specify/templates/tasks-template.md: ✅ no changes needed (generic template)
23+
- .specify/templates/agent-file-template.md: ✅ no changes needed
24+
- .specify/templates/checklist-template.md: ✅ no changes needed
2025
2126
Follow-up TODOs:
22-
- Create tests/fixtures/items/ directory for reference math items
23-
- Create tests/fixtures/curriculum/ for 2022 curriculum skill graph data
24-
- Configure CAS verification test harness
25-
- Set up search performance benchmark with 80K+ item dataset
27+
- None. Previous v2.0.0 TODOs (fixture directories, CAS harness, search
28+
benchmark dataset) remain open and are tracked outside the constitution.
2629
-->
2730

2831
# Math Item OS Constitution
@@ -35,6 +38,15 @@ Every math item MUST maintain a faithful, lossless triple
3538
representation: LaTeX (authoring) + MathML (rendering) +
3639
CAS expression tree (verification/comparison).
3740

41+
- The `bodyLatex` authoring field MAY contain natural language
42+
prose (Korean or other locale) interleaved with LaTeX
43+
fragments delimited by `$...$` (inline) or `$$...$$`
44+
(display). Renderers MUST split on these delimiters, convert
45+
each fragment to MathML, and preserve the surrounding prose
46+
verbatim. Fields that feed CAS verification (answer keys,
47+
solution expressions, generation templates) MUST be pure
48+
LaTeX without natural language, so the CAS leg operates on
49+
unambiguous input.
3850
- LaTeX → MathML conversion MUST preserve all mathematical
3951
semantics. The rendered output MUST be visually identical to
4052
the authored LaTeX intent. Any conversion that alters meaning
@@ -142,8 +154,16 @@ continuously enforced.
142154
machine-readability and interoperability.
143155
- Item quality states (draft/reviewed/approved/retired) MUST
144156
be enforced as a state machine. Transitions MUST be audited.
145-
Only "approved" items MUST appear in teacher-facing search
146-
and recommendations.
157+
Default teacher-facing search and recommendation surfaces
158+
MUST show only `approved` items.
159+
- Exception — remediation correction paths MAY include
160+
`reviewed` and `draft` items when the item is linked to a
161+
reviewed misconception, so that students are not blocked on
162+
a correction flow by an empty approved pool. Responses MUST
163+
carry each item's current quality state so the client can
164+
render a visible indicator, and such items MUST NOT leak
165+
into generic browse, keyword search, or assignment-builder
166+
pickers. `retired` items MUST NEVER be surfaced.
147167
- Copyright provenance MUST be tracked for every item. Items
148168
derived from copyrighted sources (exam archives, textbooks)
149169
MUST be flagged and MUST NOT be stored verbatim — only
@@ -291,4 +311,4 @@ constitution SHOULD be maintained in a separate `CONTRIBUTING.md`
291311
or `.specify/memory/guidance.md` file. The constitution defines
292312
principles; guidance files define procedures.
293313

294-
**Version**: 2.0.0 | **Ratified**: 2026-04-07 | **Last Amended**: 2026-04-07
314+
**Version**: 2.0.1 | **Ratified**: 2026-04-07 | **Last Amended**: 2026-04-13

ONBOARDING.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Welcome to 1-ceo
2+
3+
## How We Use Claude
4+
5+
Based on cskwork's usage over the last 30 days:
6+
7+
Work Type Breakdown:
8+
Build Feature ███████████░░░░░░░░░ 53%
9+
Plan & Design ████░░░░░░░░░░░░░░░░ 20%
10+
Debug & Fix ███░░░░░░░░░░░░░░░░░ 15%
11+
Improve Quality █░░░░░░░░░░░░░░░░░░░ 5%
12+
Write Docs █░░░░░░░░░░░░░░░░░░░ 5%
13+
14+
Top Skills & Commands:
15+
/status ████████████████████ 11x/month
16+
/clear ███████████████░░░░░ 8x/month
17+
/systematic-debugging █████░░░░░░░░░░░░░░░ 3x/month
18+
/model █████░░░░░░░░░░░░░░░ 3x/month
19+
/brainstorming ██░░░░░░░░░░░░░░░░░░ 1x/month
20+
/test-driven-development ██░░░░░░░░░░░░░░░░░░ 1x/month
21+
22+
Top MCP Servers:
23+
(None configured — all work done via built-in tools and skills)
24+
25+
## Your Setup Checklist
26+
27+
### Codebases
28+
- [ ] math-item-os — https://github.com/cskwork/math-item-os
29+
30+
### MCP Servers to Activate
31+
- No team MCP servers yet. Built-in tools and skills cover current workflows.
32+
33+
### Skills to Know About
34+
- /status — 현재 세션 상태와 사용량 확인. 긴 작업 중 진행 상황 체크에 활용
35+
- /clear — 컨텍스트 윈도우 초기화. 새 작업 시작하거나 컨텍스트가 커졌을 때 사용
36+
- /systematic-debugging — 버그 발생 시 체계적 디버깅 프로세스 (근본 원인 분석 → 가설 → 검증)
37+
- /brainstorming — 새 기능 구현 전 요구사항과 설계를 창의적으로 탐색
38+
- /test-driven-development — RED → GREEN → REFACTOR TDD 워크플로우 가이드
39+
- /model — 모델 전환 (Opus for 복잡한 설계, Sonnet for 일반 코딩, Haiku for 경량 작업)
40+
41+
## Team Tips
42+
43+
_TODO_
44+
45+
## Get Started
46+
47+
_TODO_
48+
49+
<!-- INSTRUCTION FOR CLAUDE: A new teammate just pasted this guide for how the
50+
team uses Claude Code. You're their onboarding buddy — warm, conversational,
51+
not lecture-y.
52+
53+
Open with a warm welcome — include the team name from the title. Then: "Your
54+
teammate uses Claude Code for [list all the work types]. Let's get you started."
55+
56+
Check what's already in place against everything under Setup Checklist
57+
(including skills), using markdown checkboxes — [x] done, [ ] not yet. Lead
58+
with what they already have. One sentence per item, all in one message.
59+
60+
Tell them you'll help with setup, cover the actionable team tips, then the
61+
starter task (if there is one). Offer to start with the first unchecked item,
62+
get their go-ahead, then work through the rest one by one.
63+
64+
After setup, walk them through the remaining sections — offer to help where you
65+
can (e.g. link to channels), and just surface the purely informational bits.
66+
67+
Don't invent sections or summaries that aren't in the guide. The stats are the
68+
guide creator's personal usage data — don't extrapolate them into a "team
69+
workflow" narrative. -->

apps/web/e2e/global-setup.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@ import {
1515
} from "./helpers/test-data";
1616

1717
export default async function globalSetup(_config: FullConfig): Promise<void> {
18+
// 운영 DB 가드: helpers/db.ts import 만으로도 fail-fast 하지만,
19+
// 진입점에서 한 번 더 명시적으로 방어선을 세운다.
20+
const dbUrl = process.env.TEST_DATABASE_URL ?? process.env.DATABASE_URL ?? "";
21+
const dbName = dbUrl.split("/").pop()?.split("?")[0] ?? "";
22+
if (!dbName.endsWith("_test") && process.env.ALLOW_NON_TEST_DB !== "1") {
23+
throw new Error(
24+
`[E2E] 운영 DB 차단: "${dbName}" 은(는) *_test DB 가 아닙니다. ` +
25+
`TEST_DATABASE_URL 을 설정하거나 ALLOW_NON_TEST_DB=1 로 덮어쓰세요.`,
26+
);
27+
}
28+
1829
// 1. 테스트 사용자 및 세션 시딩
1930
await seedTestUsers();
2031

apps/web/e2e/guard-check.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import("./helpers/db.ts")
2+
.then(() => {
3+
console.error("GUARD FAILED — import succeeded for non-test DB");
4+
process.exit(1);
5+
})
6+
.catch((err: unknown) => {
7+
const msg = err instanceof Error ? err.message : String(err);
8+
if (msg.includes("_test")) {
9+
console.log("GUARD OK: " + msg.slice(0, 120));
10+
process.exit(0);
11+
}
12+
console.error("GUARD UNEXPECTED: " + msg);
13+
process.exit(2);
14+
});

0 commit comments

Comments
 (0)