Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions app/assets/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ code, .mono { font-family: var(--code-font); font-size: 0.86em; }
.task-meta { display: flex; flex-wrap: wrap; gap: 4px 12px; margin-top: 4px; padding-left: 24px; font-size: 12px; color: var(--muted); }
.task-meta b { color: var(--fg-strong); font-weight: 600; }
.task-meta .ctx b { color: var(--context); }
/* 위험도 색은 앱과 같다: 낮음 초록, 보통 주황, 높음 빨강 */
.task-meta .risk { color: var(--error); }
.task-meta .risk.risk-medium { color: var(--warning); }
.task-meta .risk.risk-low { color: var(--ok); }
.steps { display: grid; grid-template-columns: repeat(6, 1fr); gap: 3px; margin-top: 10px; padding: 0; list-style: none; }
.steps li { font-size: 11px; color: var(--dim); padding-top: 6px; border-top: 2px solid var(--border-strong); transition: color 0.3s, border-color 0.3s; letter-spacing: 0.02em; }
.steps li.past { color: var(--muted); border-top-color: #4a4f63; }
Expand Down Expand Up @@ -229,6 +232,10 @@ h2 { font-size: clamp(1.7rem, 2.9vw, 2.45rem); line-height: 1.24; letter-spacing
.impact { margin: 10px 12px; padding: 10px 12px; border: 1px solid rgba(242, 101, 106, 0.45); border-radius: var(--radius); background: rgba(19, 20, 25, 0.6); }
.impact-head { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--fg-strong); font-weight: 600; }
.impact-head .risk { font-size: 11.5px; font-weight: 600; color: var(--error); background: rgba(242, 101, 106, 0.12); border-radius: 10px; padding: 1px 8px; }
.impact.risk-medium { border-color: rgba(220, 174, 58, 0.45); }
.impact.risk-medium .impact-head .risk { color: var(--warning); background: rgba(220, 174, 58, 0.14); }
.impact.risk-low { border-color: rgba(69, 189, 134, 0.4); }
.impact.risk-low .impact-head .risk { color: var(--ok); background: rgba(69, 189, 134, 0.14); }
.impact-stats { display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 6px; font-size: 13px; color: var(--muted); }
.impact-stats b { color: var(--fg-strong); font-weight: 650; margin-right: 4px; }
.impact-stats .sym { color: var(--fg); font-family: var(--code-font); font-size: 12.5px; }
Expand Down
4 changes: 2 additions & 2 deletions app/components/LandingPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ const sourceLine = computed(() => t.value.source(map.stats.files, map.stats.edge
<span v-if="stage >= 2" class="ctx">{{ t.chips.context }} <b>{{ ctxFiles.length }}</b></span>
<span v-if="stage >= 3">{{ t.chips.read }} <b>{{ task.read.length }}</b></span>
<span v-if="stage >= 5">{{ t.chips.edited }} <b>1</b></span>
<span v-if="stage >= 4" class="risk">{{ t.chips.risk[impact.risk] }}</span>
<span v-if="stage >= 4" :class="['risk', `risk-${impact.risk}`]">{{ t.chips.risk[impact.risk] }}</span>
</div>
<ol class="steps">
<li v-for="(k, i) in STEP_KEYS" :key="k" :class="{ now: stage === i + 1, past: stage > i + 1 }">{{ t.steps[k] }}</li>
Expand Down Expand Up @@ -196,7 +196,7 @@ const sourceLine = computed(() => t.value.source(map.stats.files, map.stats.edge
<div v-else><span class="n">{{ l.n }}</span><span class="s" /><span>{{ l.code }}</span></div>
</template>
</div>
<div class="impact">
<div :class="['impact', `risk-${impact.risk}`]">
<div class="impact-head"><i class="codicon codicon-pulse" />{{ t.impact.head }}<span class="risk">{{ t.chips.risk[impact.risk] }}</span></div>
<div class="impact-stats num">
<span class="sym">{{ impact.touched.join(", ") }}</span>
Expand Down
22 changes: 12 additions & 10 deletions app/content/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@ const en: Copy = {
budget: (used, budget, ms) => `${used} / ${budget} tokens · assembled in ${ms} ms`,
evidenceTitle: "How many answer files each approach retrieves at the same budget",
evidence: [
{ label: "Answer files retrieved (mean recall)", grep: "24%", lantern: "67%" },
{ label: "Questions with at least one answer file", grep: "35%", lantern: "90%" },
{ label: "Answer files retrieved (mean recall)", grep: "41%", lantern: "88%" },
{ label: "An answer file among the first 3 files", grep: "30%", lantern: "65%" },
{ label: "Same questions asked in Korean (recall)", grep: "38%", lantern: "76%" },
],
grep: "Keyword search",
grep: "Keyword search (snippets around matches)",
lantern: "Lantern",
condition: "Measured on one private project (1,772 code files, 20 hand-labelled questions, 8,000-token budget). A public benchmark on an open-source codebase is in progress.",
condition: "Public benchmark on 60 real commits from Flask, Hono and Commons Lang. The question is the commit message and the answer is the files it changed, so nobody hand-picks answers. 8,000-token budget; picking the same number of files at random scores 10%. Anyone can reproduce it with eval/bench in the repository.",
},
read: {
title: "What the agent read stays on the map.",
Expand Down Expand Up @@ -86,10 +87,10 @@ const en: Copy = {
},
models: {
title: "You pick the model, and you can see everything it was sent.",
body: "Lantern doesn’t sell a model. Connect the API key you already use, or a local model on your machine.",
body: "Lantern doesn’t sell a model. Connect the API key you already use, or a local model on your machine, and pick from that provider’s model list. Switch between connected models right from the chat box.",
rows: [
{ term: "Anthropic", text: "Claude (API key)" },
{ term: "OpenAI-compatible", text: "OpenAI, OpenRouter, vLLM, or any OpenAI-style endpoint" },
{ term: "Cloud", text: "Claude, GPT, Gemini, DeepSeek, Grok, Mistral, Groq, OpenRouter (API key)" },
{ term: "OpenAI-compatible", text: "vLLM or any other OpenAI-style endpoint" },
{ term: "Local", text: "Ollama, LM Studio. Your code never leaves the machine" },
],
plain: ["No hidden system prompt", "No telemetry", "API keys in the OS credential store", "Monthly cost limit"],
Expand All @@ -99,18 +100,19 @@ const en: Copy = {
body: "This is a beta built by one person. Worth knowing before you try it.",
rows: [
{ term: "Code signing", text: "Not yet. On Windows, SmartScreen warns you; choose “More info → Run anyway”." },
{ term: "macOS · Linux", text: "They build and pass tests, but haven’t been used day to day. macOS isn’t notarized, so you have to allow it the first time." },
{ term: "macOS · Linux", text: "macOS has been installed and tried, but not used for long; Linux only builds and passes tests. macOS isn’t notarized, so you have to allow it the first time." },
{ term: "Languages analyzed", text: "Context, the map and the impact radius understand Rust, Python, TypeScript/JavaScript, Java, Go and C#. Other languages get syntax colors only, and their impact radius shows “unknown”." },
{ term: "Impact radius limits", text: "It finds calls by name (static analysis), so code a framework calls (@GetMapping, events, DI) may show no callers or tests. The card warns you when that’s likely." },
{ term: "Merges · conflicts", text: "No UI. If a pull diverges, choose merge or rebase in the terminal." },
{ term: "Extensions", text: "VS Code extensions don’t run. It connects language servers (TypeScript, Rust, Python)." },
{ term: "Public benchmark", text: "Not yet. The recall numbers above come from one private project." },
],
},
close: {
title: "Open a project you know well, and hand it one small change.",
body: "Before approving, read the impact radius on the card and press Show on map. Tell us what worked and what got in the way; it shapes the next beta.",
os: [
{ os: "windows", name: "Windows 10 · 11", detail: "x64 installer", status: "Tested", tested: true },
{ os: "mac", name: "macOS 11+", detail: "Apple Silicon · Intel", status: "Untested", tested: false },
{ os: "mac", name: "macOS 11+", detail: "Apple Silicon · Intel", status: "Install verified", tested: false },
{ os: "linux", name: "Linux", detail: "AppImage · deb", status: "Untested", tested: false },
],
github: "View on GitHub",
Expand Down
22 changes: 12 additions & 10 deletions app/content/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@ const ko: Copy = {
budget: (used, budget, ms) => `${used} / ${budget} 토큰 · 조립 ${ms}ms`,
evidenceTitle: "같은 예산에서 정답 파일을 몇 개 가져오나",
evidence: [
{ label: "정답 파일 적중률 (평균)", grep: "24%", lantern: "67%" },
{ label: "정답 파일을 하나라도 가져온 질문", grep: "35%", lantern: "90%" },
{ label: "정답 파일 적중률 (평균)", grep: "41%", lantern: "88%" },
{ label: "처음 3개 파일 안에 정답", grep: "30%", lantern: "65%" },
{ label: "같은 질문을 한국어로 (적중률)", grep: "38%", lantern: "76%" },
],
grep: "키워드 검색",
grep: "키워드 검색 (맞은 곳 앞뒤)",
lantern: "Lantern",
condition: "비공개 프로젝트 하나(코드 파일 1,772개, 직접 정한 질문 20개, 예산 8,000토큰)에서 잰 값입니다. 공개 코드베이스로 만든 벤치마크를 준비하고 있습니다.",
condition: "Flask·Hono·Commons Lang의 실제 커밋 60개로 잰 공개 벤치마크입니다. 질문은 커밋 메시지, 정답은 그 커밋이 고친 파일이라 사람이 정답을 고르지 않습니다. 예산 8,000토큰, 같은 수의 파일을 무작위로 고르면 10%. 저장소의 eval/bench로 누구나 재현할 수 있습니다.",
},
read: {
title: "에이전트가 무엇을 읽었는지 지도에 남습니다.",
Expand Down Expand Up @@ -86,10 +87,10 @@ const ko: Copy = {
},
models: {
title: "모델은 직접 고르고, 보낸 것은 전부 보입니다.",
body: "Lantern은 모델을 팔지 않습니다. 쓰던 API 키나 컴퓨터 안의 로컬 모델을 연결합니다.",
body: "Lantern은 모델을 팔지 않습니다. 쓰던 API 키나 컴퓨터 안의 로컬 모델을 연결하고, 키를 넣으면 그 회사의 모델 목록에서 고릅니다. 연결해 둔 모델끼리는 채팅 입력창에서 바로 바꿉니다.",
rows: [
{ term: "Anthropic", text: "Claude (API 키)" },
{ term: "OpenAI 호환", text: "OpenAI, OpenRouter, vLLM 등 OpenAI 형식 주소" },
{ term: "클라우드", text: "Claude, GPT, Gemini, DeepSeek, Grok, Mistral, Groq, OpenRouter (API 키)" },
{ term: "OpenAI 호환", text: "vLLM 등 OpenAI 형식 주소라면 무엇이든" },
{ term: "로컬", text: "Ollama, LM Studio. 코드가 컴퓨터 밖으로 나가지 않습니다" },
],
plain: ["숨은 시스템 프롬프트 없음", "사용 통계 수집 없음", "API 키는 운영체제 자격 증명 저장소에", "월 비용 한도"],
Expand All @@ -99,18 +100,19 @@ const ko: Copy = {
body: "혼자 만드는 베타입니다. 쓰기 전에 알아 두면 좋은 것들입니다.",
rows: [
{ term: "코드 서명", text: "아직 없습니다. Windows에서 SmartScreen 경고가 뜨면 ‘추가 정보 → 실행’을 눌러야 합니다." },
{ term: "macOS · Linux", text: "빌드와 테스트는 통과하지만 실제로 써 보지 않았습니다. 공증 전이라 macOS는 처음 열 때 허용이 필요합니다." },
{ term: "macOS · Linux", text: "macOS는 설치해 확인했지만 오래 써 보지는 않았고, Linux는 빌드와 테스트만 통과했습니다. 공증 전이라 macOS는 처음 열 때 허용이 필요합니다." },
{ term: "분석하는 언어", text: "맥락·지도·영향 반경은 Rust, Python, TypeScript·JavaScript, Java, Go, C#만 이해합니다. 그 밖의 언어는 코드 색만 나오고 영향 반경은 ‘알 수 없음’으로 보입니다." },
{ term: "영향 반경의 한계", text: "이름으로 호출을 찾는 정적 분석이라, 프레임워크가 부르는 코드(@GetMapping, 이벤트, DI)는 호출자와 테스트가 안 보일 수 있습니다. 이런 코드는 카드에 경고로 표시합니다." },
{ term: "병합 · 충돌 해결", text: "화면이 없습니다. 풀이 갈라지면 터미널에서 병합이나 리베이스를 고릅니다." },
{ term: "확장 기능", text: "VS Code 확장은 쓸 수 없습니다. 언어 서버(TypeScript, Rust, Python)만 연결합니다." },
{ term: "공개 벤치마크", text: "아직 없습니다. 위의 적중률은 비공개 프로젝트 하나로 잰 값입니다." },
],
},
close: {
title: "잘 아는 프로젝트를 열고, 작은 수정 하나를 맡겨 보세요.",
body: "승인하기 전에 카드의 영향 반경을 보고, ‘지도에서 보기’를 눌러 보세요. 무엇이 좋았고 무엇이 막혔는지 알려 주시면 다음 베타에 반영합니다.",
os: [
{ os: "windows", name: "Windows 10 · 11", detail: "x64 설치 파일", status: "확인됨", tested: true },
{ os: "mac", name: "macOS 11 이상", detail: "Apple Silicon · Intel", status: "실사용 확인 전", tested: false },
{ os: "mac", name: "macOS 11 이상", detail: "Apple Silicon · Intel", status: "설치 확인됨", tested: false },
{ os: "linux", name: "Linux", detail: "AppImage · deb", status: "실사용 확인 전", tested: false },
],
github: "GitHub에서 보기",
Expand Down
Loading
Loading