From b0254653ca43bc0148606c182095486699309cd0 Mon Sep 17 00:00:00 2001 From: Sihyeong Lee Date: Thu, 3 Sep 2026 21:24:51 +0000 Subject: [PATCH 01/10] fix: align the site with the verified employment record The hire page and the about timeline each carried a claim the record does not support. The timeline merged two CTO roles into one five-year ItemBox entry running to 2026; ItemBox closed in October 2025, and the 2021-2024 half was GEOMEC. Split them, and give ItemBox the numbers the repositories actually show: nine engineers across Korea and Vietnam, a 20-module NestJS/TypeORM backend with 300 REST endpoints, 58 controllers, 55 entities and ~72k lines of TypeScript. Two smaller corrections travel with it. "5+ years owning engineering as a CTO" was 4 years 9 months, so it now reads "nearly five years across two companies". The site spelled the name "Si Hyeong Lee" while the resume and LinkedIn use "Sihyeong Lee" - a recruiter comparing the three reads that as two people, so the public surfaces (messages, JSON-LD, llms.txt) now use one spelling. LICENSE and the historical planning docs keep theirs. The hire page also never said "US permanent resident, no sponsorship required", which is the quietest reason a US employer skips a candidate. It says it now, in both languages, and the working style is stated as fully remote rather than remote-first. employment-positioning.test.ts and seo.test.ts assert these strings verbatim, so both move with the copy. --- content/about.json | 18 ++++++++++---- messages/en.json | 24 +++++++++---------- messages/ko.json | 6 ++--- src/app/llms-full.txt/route.ts | 2 +- src/app/llms.txt/route.ts | 6 ++--- .../__tests__/employment-positioning.test.ts | 6 ++--- src/lib/__tests__/seo.test.ts | 2 +- src/lib/seo.ts | 8 +++---- 8 files changed, 40 insertions(+), 32 deletions(-) diff --git a/content/about.json b/content/about.json index 5a25a5d..571536c 100644 --- a/content/about.json +++ b/content/about.json @@ -188,11 +188,19 @@ "type": "project" }, { - "date": "2021 - 2026", - "titleKo": "ItemBox CTO · 이커머스 SaaS", - "titleEn": "ItemBox — CTO, E-commerce SaaS", - "descriptionKo": "5년 2개월간 CTO로 AI 기반 이커머스·드롭시핑 플랫폼의 기술 전반을 책임졌습니다. API 모듈 18개 이상의 NestJS 백엔드와 React 프론트엔드를 올리고, 상품 콘텐츠 자동 생성에 OpenAI와 Replicate를, 구독 결제에 Stripe를 붙였습니다. Shopify·Cafe24·Amazon·Taobao·AliExpress 멀티마켓 재고 동기화와 대리구매 인프라를 구축했고, 아키텍처부터 배포까지 소유하며 개발 워크플로와 기술 방향을 이끌었습니다.", - "descriptionEn": "As CTO for five years and two months, I owned the full technical operation of an AI-powered e-commerce and dropshipping platform. I built a NestJS backend of 18+ API modules behind a React frontend, integrated OpenAI and Replicate for automated product-content generation and Stripe for subscription billing, and shipped multi-marketplace inventory sync across Shopify, Cafe24, Amazon, Taobao and AliExpress plus proxy-purchasing infrastructure — owning architecture through deployment while leading developer workflows and technical direction.", + "date": "2024 - 2025", + "titleKo": "ItemBox(㈜빛나라) CTO · AI 이커머스 플랫폼", + "titleEn": "ItemBox (Bitnara Inc.) — CTO, AI-assisted e-commerce platform", + "descriptionKo": "플랫폼 전체를 소유하면서 한국·베트남에 분산된 9명 규모의 개발팀을 이끌었고, 동시에 최다 기여자였습니다 — 프론트엔드 2,458커밋 중 857건, 백엔드 335건, 프로덕션 배포 11회. 20개 API 모듈의 NestJS/TypeORM 백엔드(REST 엔드포인트 300개·컨트롤러 58개·엔티티 55개·TypeScript 약 7.2만 줄)와 Next.js 프론트엔드를 소유했고, 멀티테넌트 워크스페이스와 5개 범위 권한 제어를 구현했습니다. 수동 API 키 방식을 Shopify OAuth 2.0(HMAC 검증·웹훅 자동 등록)으로 대체하고 Cafe24 관리자 앱 설치 플로우와 다중 통화·교차 환율 서비스를 붙였으며, Stripe 구독 결제를 갱신·실패 웹훅까지, 그리고 해외 주문을 받치는 대리구매·견적 서비스를 구축했습니다. ComfyUI·ModelsLab·Kling 기반 이미지 생성·배경 제거·번역을 판매자 워크플로에 넣었고, FastAPI 마이크로서비스 전환과 OpenAI·Anthropic 통합, Redis/Celery 파이프라인, AWS 운영을 맡았습니다. 2025년 10월 폐업.", + "descriptionEn": "Owned the platform end to end and led a distributed team of nine engineers across Korea and Vietnam, while remaining its top individual contributor — 857 of the frontend's 2,458 commits plus 335 on the backend, shipped through 11 production deployments. I owned a 20-module NestJS/TypeORM backend — 300 REST endpoints, 58 controllers, 55 entities, ~72k lines of TypeScript — behind a Next.js frontend, with multi-tenant workspaces and role-based permissions across five scopes. I replaced manual API-key onboarding with a Shopify OAuth 2.0 integration (HMAC validation, automatic webhook registration), shipped the Cafe24 admin-panel install flow, multi-currency stores and a cross-exchange-rate service, and built Stripe subscription billing end to end alongside the proxy-purchase and quoting services behind cross-border orders. AI went into the seller's workflow — image generation, background removal and translation over ComfyUI, ModelsLab and Kling — beside a FastAPI move to microservices, one unified interface over the OpenAI and Anthropic APIs, a Redis/Celery pipeline, and the AWS footprint. The company closed in October 2025.", + "type": "work" + }, + { + "date": "2021 - 2024", + "titleKo": "㈜지오맥 CTO · 사내 시스템·인프라", + "titleEn": "GEOMEC Inc. — CTO, internal systems & infrastructure", + "descriptionKo": "사내 운영 시스템과 업무용 클라이언트, 그리고 그 아래 인프라 전체를 총괄했습니다 — 양쪽 모두 담당 엔지니어는 저 혼자였습니다. ElectronJS 데스크탑 클라이언트를 설계·배포하고 업데이트·로깅·릴리스를 자동화했으며, NAS 기반 파일 서버에 권한 기반 접근 제어를 세웠습니다. Proxmox VE 가상화로 내부 VM 배포를 자동화하고 스냅샷 백업 체계를 만들었고, 리눅스 서버·방화벽·SSH 키·중앙 로깅을 통합 관리했으며 VPN 서버를 구축해 사내 네트워크 보안을 표준화했습니다. 2023년부터는 미국에서 원격으로 수행했습니다. 회사 파산으로 종료.", + "descriptionEn": "Owned the company's internal systems, its business desktop client, and the whole infrastructure underneath them — I was the only engineer on either. I designed and shipped an ElectronJS desktop client with automated release, update and logging pipelines, and built a NAS-backed file server with role-based access control. I stood up Proxmox VE virtualization with automated internal VM provisioning and a snapshot backup regime, ran the Linux server estate end to end (firewalls, SSH key management, centralized logging), and built the VPN server that standardized the company's network security practice. From 2023 I did this remotely from the US. The company ceased operations.", "type": "work" } ] diff --git a/messages/en.json b/messages/en.json index 7c3ce26..bd0eb6b 100644 --- a/messages/en.json +++ b/messages/en.json @@ -1,7 +1,7 @@ { "metadata": { "title": "WritingDeveloper", - "description": "Build logs and engineering notes from Si Hyeong Lee — an AI-native product engineer shipping developer tools, applied AI systems, and production full-stack products." + "description": "Build logs and engineering notes from Sihyeong Lee — an AI-native product engineer shipping developer tools, applied AI systems, and production full-stack products." }, "nav": { "home": "Home", @@ -15,7 +15,7 @@ "home": { "hero": { "greeting": "Hello", - "name": "Si Hyeong Lee", + "name": "Sihyeong Lee", "role": "AI-Native Product Engineer", "description": "I design, ship, and operate AI-native products and developer infrastructure." }, @@ -24,13 +24,13 @@ "featuredProjects": "Projects", "noPosts": "No posts yet.", "explore": "Explore my world", - "metaDescription": "Si Hyeong Lee — AI-native product engineer in Los Angeles. I build and operate developer tools, RAG systems, local-AI/GPU infrastructure, and production full-stack products." + "metaDescription": "Sihyeong Lee — AI-native product engineer in Los Angeles. I build and operate developer tools, RAG systems, local-AI/GPU infrastructure, and production full-stack products." }, "blog": { "title": "Blog", "description": "Stories about development, technology, and startups", "metaTitle": "Build Logs from Shipping Real Products", - "metaDescription": "In-depth build logs and dev stories from Si Hyeong Lee — AI safety, full-stack architecture, indie hacking, and lessons from shipping real products.", + "metaDescription": "In-depth build logs and dev stories from Sihyeong Lee — AI safety, full-stack architecture, indie hacking, and lessons from shipping real products.", "allCategories": "All", "categoryFilter": "Category filter", "readingTime": "min read", @@ -56,7 +56,7 @@ "title": "Projects", "description": "Things I'm building", "metaTitle": "{count} Projects — Web, Games, Dev Tools", - "metaDescription": "{count} projects built solo by Si Hyeong Lee — SaaS, developer tools, games and AI experiments, each with a live demo or store link.", + "metaDescription": "{count} projects built solo by Sihyeong Lee — SaaS, developer tools, games and AI experiments, each with a live demo or store link.", "viewProject": "View Project", "viewShowcase": "See the work", "viewCode": "View Code", @@ -90,7 +90,7 @@ "title": "Project Graveyard", "description": "Here lie the projects I built and lost — an honest record of what failure taught me.", "metaTitle": "Project Graveyard — What Failure Taught Me", - "metaDescription": "A memorial to the projects Si Hyeong Lee built and then lost. Each tombstone carries its cause of death, an honest post-mortem, and what it taught.", + "metaDescription": "A memorial to the projects Sihyeong Lee built and then lost. Each tombstone carries its cause of death, an honest post-mortem, and what it taught.", "empty": "No projects rest here yet.", "restInPeace": "R.I.P", "causeLabel": "Cause", @@ -114,7 +114,7 @@ "title": "About", "description": "AI-native product engineering, from architecture to production operations", "metaTitle": "About — AI-Native Product Engineer & Senior Full-Stack", - "metaDescription": "Si Hyeong Lee — AI-native product engineer and former CTO in Los Angeles. Developer tooling, applied AI, full-stack products, local GPU infrastructure, and the decisions behind them.", + "metaDescription": "Sihyeong Lee — AI-native product engineer and former CTO in Los Angeles. Developer tooling, applied AI, full-stack products, local GPU infrastructure, and the decisions behind them.", "body": "I am an AI-native product engineer and former CTO who owns the full path from architecture and implementation through testing, deployment, and production operations. I use coding agents heavily, but the engineering decisions stay explicit: constraints, acceptance criteria, failure analysis, and what ships. Recent work spans developer tooling such as DevDeck, measured RAG in citefirst, civic-tech systems such as RentRights, and a self-hosted MCP/GPU generation platform running across my own infrastructure.", "skills": "Tech Stack", "timeline": "Timeline" @@ -122,18 +122,18 @@ "hire": { "title": "Work with me", "description": "AI-native product engineer open to senior product, applied AI / AI platform, and senior full-stack roles — plus focused project work.", - "metaTitle": "Si Hyeong Lee — AI-Native Product Engineer | Senior Full-Stack", + "metaTitle": "Sihyeong Lee — AI-Native Product Engineer | Senior Full-Stack", "metaDescription": "AI-native product engineer in Los Angeles, open to remote senior product, applied AI / AI platform, and senior full-stack roles. {shipped} shipped products with a public demo or store listing.", - "badgeRemote": "Los Angeles · Remote-first", + "badgeRemote": "Los Angeles · Fully remote · US permanent resident", "badgeNow": "Available now", "fulltime": { "heading": "Full-time", "rolesLabel": "Roles", "roles": "Senior Product Engineer · Applied AI / AI Platform Engineer · Senior Full-Stack Engineer", "modeLabel": "Working style", - "mode": "Los Angeles · remote-first · US", + "mode": "Fully remote (US, Pacific Time) · US permanent resident — no sponsorship required", "bringLabel": "What I bring", - "bring": "5+ years owning engineering as a CTO, plus hands-on AI-native product work spanning agent tooling, RAG evaluation, full-stack systems, CI/QA, and local GPU infrastructure." + "bring": "Nearly five years owning engineering as a CTO across two companies, plus hands-on AI-native product work spanning agent tooling, RAG evaluation, full-stack systems, CI/QA, and local GPU infrastructure." }, "contract": { "heading": "Project work", @@ -298,7 +298,7 @@ "play": { "title": "Explore", "description": "Explore the portfolio in 3D space", - "metaDescription": "Explore Si Hyeong Lee's portfolio in an interactive 3D space — navigate projects, skills, timeline, and writing rendered in real-time WebGL.", + "metaDescription": "Explore Sihyeong Lee's portfolio in an interactive 3D space — navigate projects, skills, timeline, and writing rendered in real-time WebGL.", "loading": "Loading...", "exit": "Exit", "sections": { diff --git a/messages/ko.json b/messages/ko.json index b1ecb52..dec7cbc 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -124,16 +124,16 @@ "description": "시니어 제품·Applied AI / AI 플랫폼·시니어 풀스택 역할과 집중형 프로젝트 의뢰를 받고 있습니다.", "metaTitle": "이시형 — AI 네이티브 제품 엔지니어 | 시니어 풀스택", "metaDescription": "로스앤젤레스의 AI 네이티브 제품 엔지니어. 원격 시니어 제품·Applied AI / AI 플랫폼·시니어 풀스택 역할에 지원 중이며, 공개 데모·스토어가 있는 제품 {shipped}건을 직접 출시했습니다.", - "badgeRemote": "로스앤젤레스 · 원격 우선", + "badgeRemote": "로스앤젤레스 · 전면 원격 · 미국 영주권자", "badgeNow": "지금 바로 시작 가능", "fulltime": { "heading": "정규직", "rolesLabel": "찾는 역할", "roles": "시니어 제품 엔지니어 · Applied AI / AI 플랫폼 엔지니어 · 시니어 풀스택 엔지니어", "modeLabel": "근무 형태", - "mode": "로스앤젤레스 · 미국 원격 우선", + "mode": "전면 원격(미국, 태평양 표준시) · 영주권자(취업 스폰서 불필요)", "bringLabel": "가져오는 것", - "bring": "CTO로 5년 이상 엔지니어링을 책임진 경험과, 에이전트 도구·RAG 평가·풀스택 시스템·CI/QA·로컬 GPU 인프라를 직접 만드는 최근 AI 네이티브 제품 경험." + "bring": "두 회사에서 5년 가까이 엔지니어링을 책임진 CTO 경험과, 에이전트 도구·RAG 평가·풀스택 시스템·CI/QA·로컬 GPU 인프라를 직접 만드는 최근 AI 네이티브 제품 경험." }, "contract": { "heading": "프로젝트 의뢰", diff --git a/src/app/llms-full.txt/route.ts b/src/app/llms-full.txt/route.ts index a9afe51..1d48792 100644 --- a/src/app/llms-full.txt/route.ts +++ b/src/app/llms-full.txt/route.ts @@ -24,7 +24,7 @@ export async function GET() { const content = `# WritingDeveloper — Full Content -> Full-text version of every blog post by Si Hyeong Lee (이시형). For a compact +> Full-text version of every blog post by Sihyeong Lee (이시형). For a compact > index (posts, projects, links), see ${SITE_URL}/llms.txt ${sections.join('\n\n---\n\n')} diff --git a/src/app/llms.txt/route.ts b/src/app/llms.txt/route.ts index 5cbe944..f0cee5d 100644 --- a/src/app/llms.txt/route.ts +++ b/src/app/llms.txt/route.ts @@ -37,7 +37,7 @@ export async function GET() { const content = `# WritingDeveloper -> Personal blog and portfolio by Si Hyeong Lee (이시형) — a solo full-stack developer and entrepreneur who designs, builds, and ships products end to end. +> Personal blog and portfolio by Sihyeong Lee (이시형) — a solo full-stack developer and entrepreneur who designs, builds, and ships products end to end. > Dev stories, tech tutorials, and the startup journey behind the projects below. ## About @@ -59,8 +59,8 @@ ${projectLines} ## Project Graveyard -- [Project Graveyard (Korean)](${SITE_URL}/graveyard): A memorial to projects Si Hyeong Lee built and then failed or discontinued — each with its cause of death, an honest post-mortem, and lessons learned. -- [Project Graveyard (English)](${SITE_URL}/en/graveyard): A memorial to projects Si Hyeong Lee built and then failed or discontinued — each with its cause of death, an honest post-mortem, and lessons learned. +- [Project Graveyard (Korean)](${SITE_URL}/graveyard): A memorial to projects Sihyeong Lee built and then failed or discontinued — each with its cause of death, an honest post-mortem, and lessons learned. +- [Project Graveyard (English)](${SITE_URL}/en/graveyard): A memorial to projects Sihyeong Lee built and then failed or discontinued — each with its cause of death, an honest post-mortem, and lessons learned. ## Technical Stack diff --git a/src/lib/__tests__/employment-positioning.test.ts b/src/lib/__tests__/employment-positioning.test.ts index 66e8b9d..de8705d 100644 --- a/src/lib/__tests__/employment-positioning.test.ts +++ b/src/lib/__tests__/employment-positioning.test.ts @@ -17,18 +17,18 @@ describe('employment positioning', () => { expect(en.home.metaDescription).toContain('AI-native product engineer') expect(en.about.metaTitle).toContain('AI-Native Product Engineer') expect(en.hire.metaTitle).toContain('AI-Native Product Engineer') - expect(en.hire.badgeRemote).toBe('Los Angeles · Remote-first') + expect(en.hire.badgeRemote).toBe('Los Angeles · Fully remote · US permanent resident') expect(en.hire.fulltime.roles).toBe( 'Senior Product Engineer · Applied AI / AI Platform Engineer · Senior Full-Stack Engineer' ) - expect(en.hire.fulltime.bring).toContain('5+ years owning engineering as a CTO') + expect(en.hire.fulltime.bring).toContain('Nearly five years owning engineering as a CTO') }) it('keeps the Korean positioning aligned with the English profile', () => { expect(ko.home.metaDescription).toContain('AI 네이티브 제품 엔지니어') expect(ko.about.metaTitle).toContain('AI 네이티브 제품 엔지니어') expect(ko.hire.metaTitle).toContain('AI 네이티브 제품 엔지니어') - expect(ko.hire.badgeRemote).toBe('로스앤젤레스 · 원격 우선') + expect(ko.hire.badgeRemote).toBe('로스앤젤레스 · 전면 원격 · 미국 영주권자') expect(ko.hire.fulltime.roles).toBe( '시니어 제품 엔지니어 · Applied AI / AI 플랫폼 엔지니어 · 시니어 풀스택 엔지니어' ) diff --git a/src/lib/__tests__/seo.test.ts b/src/lib/__tests__/seo.test.ts index 1908aac..c2cf63b 100644 --- a/src/lib/__tests__/seo.test.ts +++ b/src/lib/__tests__/seo.test.ts @@ -166,7 +166,7 @@ describe('generateProjectListJsonLd', () => { expect(result.itemListElement[0].item['@type']).toBe('CreativeWork') expect(result.itemListElement[0].item.author).toEqual({ '@type': 'Person', - name: 'Si Hyeong Lee', + name: 'Sihyeong Lee', url: 'https://writingdeveloper.blog/about', }) expect(result.itemListElement[0].item).toHaveProperty('keywords', 'TypeScript, Next.js') diff --git a/src/lib/seo.ts b/src/lib/seo.ts index 0be8adc..425c448 100644 --- a/src/lib/seo.ts +++ b/src/lib/seo.ts @@ -80,7 +80,7 @@ export function generateWebsiteJsonLd(locale: string) { inLanguage: locale === 'ko' ? 'ko-KR' : 'en-US', publisher: { '@type': 'Person', - name: locale === 'ko' ? '이시형' : 'Si Hyeong Lee', + name: locale === 'ko' ? '이시형' : 'Sihyeong Lee', url: `${SITE_URL}/about`, }, } @@ -92,7 +92,7 @@ export function generatePersonJsonLd(locale: string) { '@type': 'ProfilePage', mainEntity: { '@type': 'Person', - name: locale === 'ko' ? '이시형' : 'Si Hyeong Lee', + name: locale === 'ko' ? '이시형' : 'Sihyeong Lee', url: `${SITE_URL}${locale === 'ko' ? '' : '/en'}/about`, jobTitle: locale === 'ko' ? '개발자 & 창업가' : 'Developer & Entrepreneur', description: @@ -145,7 +145,7 @@ export function generateProjectListJsonLd( }[], locale: string ) { - const authorName = locale === 'ko' ? '이시형' : 'Si Hyeong Lee' + const authorName = locale === 'ko' ? '이시형' : 'Sihyeong Lee' const author = { '@type': 'Person', name: authorName, url: `${SITE_URL}/about` } return { '@context': 'https://schema.org', @@ -209,7 +209,7 @@ export function generateProjectJsonLd( }, locale: string ) { - const authorName = locale === 'ko' ? '이시형' : 'Si Hyeong Lee' + const authorName = locale === 'ko' ? '이시형' : 'Sihyeong Lee' const sameAs = [project.website, project.github, project.playStore].filter(Boolean) as string[] const common = { From 2a363c13792b4dea69ec3560c06e705ac1d2ae1b Mon Sep 17 00:00:00 2001 From: Sihyeong Lee Date: Tue, 8 Sep 2026 00:42:21 +0000 Subject: [PATCH 02/10] fix(about): cut count-stacking from the ItemBox entry and drop em dashes The ItemBox timeline copy carried raw commit, endpoint, controller and entity counts (857 of 2,458 commits, 300 REST endpoints, 58 controllers, 55 entities, ~72k lines of TypeScript). Those were pulled from the resume for reading as filler rather than evidence, and the site was about to put them back. Rewrote both locales to match the resume: what was owned and built, not how many of it there were. Also replaced the em dashes across the timeline copy with periods, colons and middots, and switched the title separators to the middot the Korean titles already use. Adds a test so neither regression can come back through the site copy. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01LY9haZyJhdQfT45Jamnzrq --- content/about.json | 20 +++++++-------- .../__tests__/employment-positioning.test.ts | 25 +++++++++++++++++++ 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/content/about.json b/content/about.json index 571536c..a4fece3 100644 --- a/content/about.json +++ b/content/about.json @@ -152,15 +152,15 @@ "titleKo": "오픈소스·시빅테크로 확장", "titleEn": "Expanding into open source & civic tech", "descriptionKo": "RentRights(LA 세입자 임대료 규제 추정기), DevDeck(Claude Code·Codex·Antigravity 프로젝트 관제 데스크톱 앱), citefirst(인용을 검증하고 검색 품질을 측정하는 RAG), TransitLA(차 없이 대중교통으로 가는 LA 탐색) 등 공개 데이터·개발 도구 프로젝트를 공개.", - "descriptionEn": "Released public-data and developer-tool projects — RentRights (LA rent-control estimator for tenants), DevDeck (a command deck for Claude Code, Codex and Antigravity projects), citefirst (a RAG system that verifies its citations and measures its retrieval), and TransitLA (car-free LA discovery on public transit).", + "descriptionEn": "Released public-data and developer-tool projects: RentRights (LA rent-control estimator for tenants), DevDeck (a command deck for Claude Code, Codex and Antigravity projects), citefirst (a RAG system that verifies its citations and measures its retrieval), and TransitLA (car-free LA discovery on public transit).", "type": "project" }, { "date": "2026", "titleKo": "생성 스튜디오 구축: 5모달리티 개인 생성 팩토리", - "titleEn": "Building the studios — a five-modality generation factory", + "titleEn": "Building the studios · a five-modality generation factory", "descriptionKo": "이미지·영상·3D·음성·음악을 Claude가 MCP 툴로 생성하고, 기계 게이트와 직접 검수를 거쳐 재시도하는 개인 생성 파이프라인을 구축. 여섯 개 레포를 히스토리 보존 subtree 병합으로 단일 모노레포에 통합하고, 자연어로 지휘하면 로컬 LLM이 툴을 직접 불러 생성부터 검수까지 밟는 에이전트 하네스를 붙임. 이 사이트의 블로그 히어로 이미지도 여기서 나왔다.", - "descriptionEn": "Built a personal generation pipeline where Claude drives image, video, 3D, voice, and music through MCP tools — generate, pass a machine gate, inspect the result directly, retry. Six repositories were consolidated into a single monorepo through history-preserving subtree merges, and an agent harness now lets a local LLM call those tools itself from a natural-language brief. The hero images on this site's blog came out of it.", + "descriptionEn": "Built a personal generation pipeline where Claude drives image, video, 3D, voice, and music through MCP tools: generate, pass a machine gate, inspect the result directly, retry. Six repositories were consolidated into a single monorepo through history-preserving subtree merges, and an agent harness now lets a local LLM call those tools itself from a natural-language brief. The hero images on this site's blog came out of it.", "type": "project" }, { @@ -168,7 +168,7 @@ "titleKo": "웹·모바일 제품 연속 출시", "titleEn": "Shipping web & mobile products", "descriptionKo": "healframe(멘탈헬스), argus-fusion(실시간 OSINT), zodiacly(운세), kindling(감정 케어) 등 웹·모바일 제품을 빠르게 기획·개발·출시.", - "descriptionEn": "Rapidly designed, built, and shipped web and mobile products — healframe (mental health), argus-fusion (real-time OSINT), zodiacly (horoscope), and kindling (emotional care).", + "descriptionEn": "Rapidly designed, built, and shipped web and mobile products: healframe (mental health), argus-fusion (real-time OSINT), zodiacly (horoscope), and kindling (emotional care).", "type": "project" }, { @@ -190,17 +190,17 @@ { "date": "2024 - 2025", "titleKo": "ItemBox(㈜빛나라) CTO · AI 이커머스 플랫폼", - "titleEn": "ItemBox (Bitnara Inc.) — CTO, AI-assisted e-commerce platform", - "descriptionKo": "플랫폼 전체를 소유하면서 한국·베트남에 분산된 9명 규모의 개발팀을 이끌었고, 동시에 최다 기여자였습니다 — 프론트엔드 2,458커밋 중 857건, 백엔드 335건, 프로덕션 배포 11회. 20개 API 모듈의 NestJS/TypeORM 백엔드(REST 엔드포인트 300개·컨트롤러 58개·엔티티 55개·TypeScript 약 7.2만 줄)와 Next.js 프론트엔드를 소유했고, 멀티테넌트 워크스페이스와 5개 범위 권한 제어를 구현했습니다. 수동 API 키 방식을 Shopify OAuth 2.0(HMAC 검증·웹훅 자동 등록)으로 대체하고 Cafe24 관리자 앱 설치 플로우와 다중 통화·교차 환율 서비스를 붙였으며, Stripe 구독 결제를 갱신·실패 웹훅까지, 그리고 해외 주문을 받치는 대리구매·견적 서비스를 구축했습니다. ComfyUI·ModelsLab·Kling 기반 이미지 생성·배경 제거·번역을 판매자 워크플로에 넣었고, FastAPI 마이크로서비스 전환과 OpenAI·Anthropic 통합, Redis/Celery 파이프라인, AWS 운영을 맡았습니다. 2025년 10월 폐업.", - "descriptionEn": "Owned the platform end to end and led a distributed team of nine engineers across Korea and Vietnam, while remaining its top individual contributor — 857 of the frontend's 2,458 commits plus 335 on the backend, shipped through 11 production deployments. I owned a 20-module NestJS/TypeORM backend — 300 REST endpoints, 58 controllers, 55 entities, ~72k lines of TypeScript — behind a Next.js frontend, with multi-tenant workspaces and role-based permissions across five scopes. I replaced manual API-key onboarding with a Shopify OAuth 2.0 integration (HMAC validation, automatic webhook registration), shipped the Cafe24 admin-panel install flow, multi-currency stores and a cross-exchange-rate service, and built Stripe subscription billing end to end alongside the proxy-purchase and quoting services behind cross-border orders. AI went into the seller's workflow — image generation, background removal and translation over ComfyUI, ModelsLab and Kling — beside a FastAPI move to microservices, one unified interface over the OpenAI and Anthropic APIs, a Redis/Celery pipeline, and the AWS footprint. The company closed in October 2025.", + "titleEn": "ItemBox (Bitnara Inc.) · CTO, AI-assisted e-commerce platform", + "descriptionKo": "플랫폼 전체를 처음부터 끝까지 소유하면서 한국과 베트남에 흩어진 개발자 아홉 명을 이끌었고, 동시에 가장 많이 기여한 사람이었습니다. API 모듈 스무 개짜리 NestJS/TypeORM 백엔드와 Next.js 프론트엔드를 소유했고, 멀티테넌트 워크스페이스와 역할 기반 권한, 그리고 이메일 인증부터 자격 정보 전달까지 이어지는 초대 플로우를 만들었습니다. 수동 API 키 방식은 Shopify OAuth 2.0 연동으로 대체했습니다. 판매자가 클릭 한 번으로 스토어를 연결하면 앱이 HMAC를 검증하고 토큰을 저장하고 웹훅까지 알아서 등록합니다. Cafe24 쪽도 같은 방식으로 만들고 다중 통화 스토어와 교차 환율 서비스를 붙였으며, Stripe 구독 결제를 갱신·결제 실패 웹훅까지, 그리고 해외 주문을 받치는 대리구매·견적 서비스를 함께 만들었습니다. AI는 판매자가 실제로 일하는 자리에 넣었습니다. ComfyUI와 ModelsLab, Kling으로 이미지 생성과 배경 제거, 번역을 붙이고 OCR 서비스와 크롬 확장을 함께 두었습니다. FastAPI 서비스는 마이크로서비스 구조로 옮기면서 OpenAI와 Anthropic API를 하나의 인터페이스로 감쌌고, PostgreSQL과 MongoDB를 함께 운영하고 Redis·Celery 파이프라인을 만들고 AWS를 운영했습니다. 2025년 10월 폐업했습니다.", + "descriptionEn": "Owned the platform end to end and led the engineering team, nine people split between Korea and Vietnam, while remaining its most active contributor. I owned a NestJS/TypeORM backend of twenty API modules behind a Next.js frontend, with multi-tenant workspaces, role-based permissions, and an invitation flow that carried a new teammate from email verification through to credential delivery. I replaced manual API-key onboarding with a Shopify OAuth 2.0 integration: a seller connects a store in one click and the app validates HMAC, stores the token and registers its webhooks by itself. I built the Cafe24 equivalent, then multi-currency stores and a cross-exchange-rate service, and shipped Stripe subscription billing with renewal and payment-failure webhooks alongside the proxy-purchase and quoting services behind cross-border orders. AI went where sellers actually work: image generation, background removal and translation through ComfyUI, ModelsLab and Kling, with an OCR service and a Chrome extension alongside. I moved the FastAPI services onto a microservice architecture behind one interface over the OpenAI and Anthropic APIs, ran PostgreSQL and MongoDB together, built the Redis and Celery pipeline, and operated the AWS footprint. The company closed in October 2025.", "type": "work" }, { "date": "2021 - 2024", "titleKo": "㈜지오맥 CTO · 사내 시스템·인프라", - "titleEn": "GEOMEC Inc. — CTO, internal systems & infrastructure", - "descriptionKo": "사내 운영 시스템과 업무용 클라이언트, 그리고 그 아래 인프라 전체를 총괄했습니다 — 양쪽 모두 담당 엔지니어는 저 혼자였습니다. ElectronJS 데스크탑 클라이언트를 설계·배포하고 업데이트·로깅·릴리스를 자동화했으며, NAS 기반 파일 서버에 권한 기반 접근 제어를 세웠습니다. Proxmox VE 가상화로 내부 VM 배포를 자동화하고 스냅샷 백업 체계를 만들었고, 리눅스 서버·방화벽·SSH 키·중앙 로깅을 통합 관리했으며 VPN 서버를 구축해 사내 네트워크 보안을 표준화했습니다. 2023년부터는 미국에서 원격으로 수행했습니다. 회사 파산으로 종료.", - "descriptionEn": "Owned the company's internal systems, its business desktop client, and the whole infrastructure underneath them — I was the only engineer on either. I designed and shipped an ElectronJS desktop client with automated release, update and logging pipelines, and built a NAS-backed file server with role-based access control. I stood up Proxmox VE virtualization with automated internal VM provisioning and a snapshot backup regime, ran the Linux server estate end to end (firewalls, SSH key management, centralized logging), and built the VPN server that standardized the company's network security practice. From 2023 I did this remotely from the US. The company ceased operations.", + "titleEn": "GEOMEC Inc. · CTO, internal systems & infrastructure", + "descriptionKo": "사내 운영 시스템과 업무용 클라이언트, 그리고 그 아래 인프라 전체를 총괄했습니다. 양쪽 모두 담당 엔지니어는 저 혼자였습니다. ElectronJS 데스크탑 클라이언트를 설계·배포하고 업데이트·로깅·릴리스를 자동화했으며, NAS 기반 파일 서버에 권한 기반 접근 제어를 세웠습니다. Proxmox VE 가상화로 내부 VM 배포를 자동화하고 스냅샷 백업 체계를 만들었고, 리눅스 서버·방화벽·SSH 키·중앙 로깅을 통합 관리했으며 VPN 서버를 구축해 사내 네트워크 보안을 표준화했습니다. 2023년부터는 미국에서 원격으로 수행했습니다. 회사 파산으로 종료.", + "descriptionEn": "Owned the company's internal systems, its business desktop client, and the whole infrastructure underneath them. I was the only engineer on either. I designed and shipped an ElectronJS desktop client with automated release, update and logging pipelines, and built a NAS-backed file server with role-based access control. I stood up Proxmox VE virtualization with automated internal VM provisioning and a snapshot backup regime, ran the Linux server estate end to end (firewalls, SSH key management, centralized logging), and built the VPN server that standardized the company's network security practice. From 2023 I did this remotely from the US. The company ceased operations.", "type": "work" } ] diff --git a/src/lib/__tests__/employment-positioning.test.ts b/src/lib/__tests__/employment-positioning.test.ts index de8705d..ec97df6 100644 --- a/src/lib/__tests__/employment-positioning.test.ts +++ b/src/lib/__tests__/employment-positioning.test.ts @@ -1,6 +1,7 @@ import { readFileSync } from 'node:fs' import { join } from 'node:path' import { describe, expect, it } from 'vitest' +import about from '../../../content/about.json' import en from '../../../messages/en.json' import ko from '../../../messages/ko.json' @@ -24,6 +25,30 @@ describe('employment positioning', () => { expect(en.hire.fulltime.bring).toContain('Nearly five years owning engineering as a CTO') }) + it('keeps the timeline copy free of count-stacking and em dashes', () => { + const copy = about.timeline.flatMap((entry) => [ + entry.titleEn, + entry.titleKo, + entry.descriptionEn, + entry.descriptionKo, + ]) + + for (const text of copy) { + // Em dashes read as machine-written; the site uses periods, colons and middots. + expect(text).not.toContain('\u2014') + } + + const itembox = about.timeline.find((entry) => entry.titleEn.includes('ItemBox')) + expect(itembox).toBeDefined() + // Raw commit/endpoint/entity counts were pulled from the resume for reading as + // filler rather than evidence. They must not come back through the site copy. + for (const banned of ['2,458', '857', '72k', '300 REST', '58 controllers', '55 entities']) { + expect(itembox!.descriptionEn).not.toContain(banned) + } + expect(itembox!.descriptionEn).toContain('nine people split between Korea and Vietnam') + expect(itembox!.descriptionKo).toContain('개발자 아홉 명') + }) + it('keeps the Korean positioning aligned with the English profile', () => { expect(ko.home.metaDescription).toContain('AI 네이티브 제품 엔지니어') expect(ko.about.metaTitle).toContain('AI 네이티브 제품 엔지니어') From 568e3ca7fba2b49f989f0b7f85d72f1d2413de5b Mon Sep 17 00:00:00 2001 From: Si Hyeong Lee Date: Wed, 23 Sep 2026 21:18:37 -0700 Subject: [PATCH 03/10] feat(portfolio): feature BRAIN//VAT case study (BVAT-14) --- content/projects.json | 40 ++++++++++++++++++-- public/images/projects/brain-vat-siege.webp | Bin 0 -> 67526 bytes src/lib/__tests__/projects.test.ts | 18 +++++++-- src/lib/projects.ts | 3 +- 4 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 public/images/projects/brain-vat-siege.webp diff --git a/content/projects.json b/content/projects.json index c9e24a5..6eb3c59 100644 --- a/content/projects.json +++ b/content/projects.json @@ -88,7 +88,7 @@ "status": "active", "github": "https://github.com/writingdeveloper/JuiceBar", "private": false, - "featured": true, + "featured": false, "updatedAt": "2026-08-26", "screenshot": "/images/projects/juicebar.webp", "screenshotAltKo": "JuiceBar 트레이 팝업 실제 화면. 연료 게이지 형태의 진행 표시와 이번 청구 주기 비용, 오늘 사용량, 예상 비용, 최근 추세를 보여준다.", @@ -593,7 +593,7 @@ "website": "https://healframe.app", "playStore": "https://play.google.com/store/apps/details?id=app.healframe", "private": true, - "featured": false, + "featured": true, "screenshot": "/images/projects/healframe.webp", "screenshotAltKo": "HealFrame 랜딩 화면. 상단 내비게이션에 Circle·Dashboard·Pricing·Account가 있고, 'Reset your nervous system in 2 minutes' 헤드라인 아래 'Tap to breathe'라고 적힌 원형 호흡 버튼과 초록색 시작 버튼이 놓여 있다.", "screenshotAltEn": "HealFrame landing page. The top nav shows Circle, Dashboard, Pricing and Account; below the headline 'Reset your nervous system in 2 minutes' sit a gradient circle labelled 'Tap to breathe' and a green 'Start breathing — it's free' button." @@ -660,7 +660,7 @@ "website": "https://rentrights.writingdeveloper.blog", "github": "https://github.com/writingdeveloper/rentrights", "private": false, - "featured": true, + "featured": false, "screenshot": "/images/projects/rentrights.webp", "screenshotAltKo": "RentRights 랜딩 화면. 'You have rights.' 헤드라인 아래 로스앤젤레스 주소를 넣는 입력창과 Check 버튼이 있고, 공공기록·갱신일·주소 미저장 배지에 이어 3단계 이용 안내와 RSO 관련 FAQ가 보인다.", "screenshotAltEn": "RentRights landing page. Under the headline 'You have rights.' sit an address field showing a Los Angeles example and a Check button, followed by badges for public records, the update date and 'free, no address saved', a three-step how-it-works list and an FAQ about LA's Rent Stabilization Ordinance." @@ -914,6 +914,40 @@ "screenshot": "/images/projects/tantrum-tower.webp", "screenshotAltKo": "Tantrum Tower 시작 화면. 어두운 카드 안에 노란 TANTRUM TOWER 로고와 한 줄 소개, '스토리 시작' 버튼과 쉬움·보통·어려움 난이도 선택, '현장 투입' 버튼이 있고, 그 아래 조작키 안내와 현장 이벤트 목록이 정리돼 있다.", "screenshotAltEn": "Tantrum Tower start screen. Inside a dark panel, the glowing yellow logo sits above a one-line Korean pitch, a story-start button, easy/normal/hard difficulty buttons and a quick-play button, with a key-binding list and a table of site events underneath." + }, + { + "name": "BRAIN//VAT", + "slug": "brain-vat-siege", + "descriptionKo": "Three.js 보스전과 신경 컨트롤러 연구를 하나의 공개 인터랙티브 케이스 스터디로 만든 프로젝트입니다. 미학습·사전학습·온라인 적응 예측기를 같은 입력에서 비교하고, 플레이로 달라진 102개 가중치 기억을 호환 보스 몸체로 옮길 수 있습니다. 별도 연구 경로에서는 166,700-뉴런 MaleCNS 고정 connectome의 시간 상태에 작은 외부 readout을 붙여 held-out 움직임 이력 분류를 검증했습니다.", + "descriptionEn": "A public interactive case study combining a Three.js boss fight with neural-controller research. It compares untrained, pretrained-frozen and online-adaptive predictors on the same committed inputs, and lets a player move a 102-weight learned memory cartridge into a compatible boss chassis. A separate research path keeps the 166,700-neuron MaleCNS connectome fixed and tests small external readouts over its temporal state on a held-out motion-history task.", + "techStack": [ + "JavaScript", + "Three.js", + "Node.js", + "Playwright", + "Python", + "C++", + "WebGL2", + "Vercel" + ], + "status": "active", + "website": "https://brain-vat-siege.vercel.app", + "private": true, + "featured": true, + "updatedAt": "2026-09-23", + "screenshot": "/images/projects/brain-vat-siege.webp", + "screenshotAltKo": "BRAIN//VAT SENTINEL 보스전의 실제 Three.js 화면. 중앙의 발광 기계형 보스가 세 개의 네온 레인을 향해 공격을 준비하고 있다.", + "screenshotAltEn": "A real Three.js capture of the BRAIN//VAT SENTINEL boss fight, with a glowing mechanical boss preparing an attack over three neon lanes.", + "caseStudy": { + "problemKo": "신경망이 동작한다는 그래프만으로는 사용자가 무엇을 할 수 있는지, 그리고 AI의 기억·예측이 실제 플레이를 어떻게 바꾸는지 체감하기 어려웠습니다.", + "problemEn": "Neural telemetry alone did not make it obvious what a player could do with the system or how prediction and memory changed an actual interaction.", + "decisionKo": "예측을 사용자 입력 전에 잠그는 3레인 보스전을 만들고 미학습·고정 사전학습·온라인 적응 모델을 같은 회피 기록으로 비교했습니다. 이어 플레이로 변한 102개 예측 가중치만 호환 보스 chassis로 옮기는 기억 카트리지와 게임 소유 action budget을 분리했습니다.", + "decisionEn": "I built a three-lane boss fight that commits predictions before player input, compares fresh, frozen-pretrained and online-adaptive models on the same dodge trace, and separates game-owned action budgets from a 102-weight predictor memory cartridge that can move only between compatible boss chassis.", + "evidenceKo": "공개 production은 `/boss`, `/demo`, `/evaluation`을 외부 AI API 없이 실행합니다. SENTINEL의 실제 Chrome QA는 합법적인 키 입력으로 10회 반격 승리·무조작 패배를 모두 재현했고, 기억 카트리지는 SENTINEL에서 WRAITH로 이동 후 HP·라운드는 초기화되면서 예측 가중치만 유지됐습니다. MaleCNS 별도 평가에서는 최종 프레임만 30/90(33.3%), 36개 calibrated optic cell의 시간 상태+111개 외부 readout 파라미터가 66/90(73.3%)였으며 connectome weight SHA는 전후 동일했습니다.", + "evidenceEn": "The public production runs `/boss`, `/demo` and `/evaluation` without an external AI API. Real Chrome QA records a legitimate 10-counter SENTINEL victory and an unattended defeat; a saved memory cartridge moves from SENTINEL to WRAITH while HP and round state reset and only predictor weights persist. In a separate MaleCNS test, final-frame-only scoring is 30/90 (33.3%) while temporal state from 36 calibrated optic cells plus a 111-parameter external readout reaches 66/90 (73.3%); the connectome-weight SHA is unchanged before and after.", + "resultKo": "결과는 단순 AI 데모가 아니라 플레이 가능한 3D 시스템, 재현 가능한 평가, 명시적 권한 경계, 기억 이식 실험과 고정 connectome readout 연구를 한 공개 케이스 스터디로 묶은 것입니다.", + "resultEn": "The result is a public case study that joins a playable 3D system with reproducible evaluation, explicit action boundaries, compatible memory transfer, and fixed-connectome readout experiments instead of presenting a neural model as a black-box demo." + } } ] } diff --git a/public/images/projects/brain-vat-siege.webp b/public/images/projects/brain-vat-siege.webp new file mode 100644 index 0000000000000000000000000000000000000000..3ea7ce3578bef4ec75f3a47f51fdb632c1ec2916 GIT binary patch literal 67526 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 { }) it('keeps selected work to five complementary projects in editorial order', () => { - expect(SELECTED_WORK).toEqual(['devdeck', 'studios', 'rentrights', 'citefirst', 'juicebar']) + expect(SELECTED_WORK).toEqual(['devdeck', 'studios', 'citefirst', 'brain-vat-siege', 'healframe']) expect(new Set(SELECTED_WORK).size).toBe(5) }) }) -describe('JuiceBar ledger refresh', () => { +describe('selected ledger refresh', () => { const ledger = projectsData.projects as Project[] - it('adds exactly one project to the 41-project baseline and that project is JuiceBar', () => { - expect(ledger).toHaveLength(42) + it('keeps JuiceBar and adds the public BRAIN//VAT case study', () => { + expect(ledger).toHaveLength(43) const juicebar = ledger.find((project) => project.slug === 'juicebar') expect(juicebar).toBeDefined() expect(juicebar?.github).toBe('https://github.com/writingdeveloper/JuiceBar') @@ -242,6 +242,16 @@ describe('JuiceBar ledger refresh', () => { expect(juicebar?.caseStudy?.evidenceEn).toBeTruthy() }) + it('adds BRAIN//VAT as a public demo without exposing a private repo', () => { + const bvat = ledger.find((project) => project.slug === 'brain-vat-siege') + expect(bvat).toBeDefined() + expect(bvat?.website).toBe('https://brain-vat-siege.vercel.app') + expect(bvat?.private).toBe(true) + expect(bvat?.github).toBeUndefined() + expect(bvat?.screenshot).toBe('/images/projects/brain-vat-siege.webp') + expect(bvat?.caseStudy?.evidenceEn).toContain('66/90') + }) + it('uses the selected-work list as the only featured set', () => { expect(new Set(ledger.filter((project) => project.featured).map((project) => project.slug))).toEqual( new Set(SELECTED_WORK) diff --git a/src/lib/projects.ts b/src/lib/projects.ts index 6030a1b..358ac28 100644 --- a/src/lib/projects.ts +++ b/src/lib/projects.ts @@ -1,6 +1,6 @@ import type { Project } from '@/types/content' -export const SELECTED_WORK = ['devdeck', 'studios', 'rentrights', 'citefirst', 'juicebar'] as const +export const SELECTED_WORK = ['devdeck', 'studios', 'citefirst', 'brain-vat-siege', 'healframe'] as const export type ProjectCaseStudyKey = 'problem' | 'decision' | 'evidence' | 'result' @@ -191,6 +191,7 @@ export const HOME_GROUPS: Record<'products' | 'games' | 'tools', string[]> = { 'observer-of-lines', ], games: [ + 'brain-vat-siege', 'coinrace', 'wishing-stones', 'hoverslam', From 4ef2f4227424317401841b548e2ebbf34cd00479 Mon Sep 17 00:00:00 2001 From: Si Hyeong Lee Date: Sun, 11 Oct 2026 21:28:07 -0700 Subject: [PATCH 04/10] feat(portfolio): preserve verified evidence resume and bilingual positioning QA --- .github/workflows/ci.yml | 33 ++++ .gitignore | 3 + AGENTS.md | 11 ++ README.md | 15 ++ content/about.json | 66 +++++++- content/evidence.json | 51 ++++++ .../en/agent-engineering-ownership/index.mdx | 96 +++++++++++ .../ko/agent-engineering-ownership/index.mdx | 96 +++++++++++ content/projects.json | 51 ++++-- content/resume-manifest.json | 18 ++ docs/operations/evidence-workflow.md | 29 ++++ docs/research/ai-positioning-2026-09-22.md | 26 +++ .../2026-10-11-live-site-refresh-audit.md | 96 +++++++++++ .../minglestage-case-study-2026-09-22.md | 11 ++ docs/reviews/portfolio-qa-2026-09-22.md | 66 ++++++++ messages/en.json | 60 +++++-- messages/ko.json | 60 +++++-- package.json | 6 +- public/resume/Sihyeong-Lee-Resume-DevEx.pdf | Bin 0 -> 84927 bytes public/resume/Sihyeong-Lee-Resume-FDE.pdf | Bin 0 -> 88049 bytes public/resume/Sihyeong-Lee-Resume.pdf | Bin 0 -> 87672 bytes scripts/evidence.mts | 106 ++++++++++++ scripts/qa-navigation.ts | 2 +- scripts/qa-portfolio.mts | 157 ++++++++++++++++++ src/app/[locale]/LedgerHome.tsx | 40 ++++- src/app/[locale]/hire/page.tsx | 59 ++++++- src/app/[locale]/layout.tsx | 15 +- .../[locale]/play/sections/SkillsSection.tsx | 13 +- src/components/projects/EvidencePanel.tsx | 41 +++++ src/components/projects/ProjectCard.tsx | 2 +- src/components/ui/SkillGrid.tsx | 8 +- .../__tests__/employment-positioning.test.ts | 26 +-- src/lib/__tests__/evidence-policy.test.ts | 87 ++++++++++ .../__tests__/evidence-regressions.test.ts | 49 ++++++ src/lib/__tests__/projects.test.ts | 21 +-- src/lib/evidence-policy.ts | 98 +++++++++++ src/lib/projects.ts | 7 +- src/lib/skill-groups.ts | 8 + src/lib/telemetry-policy.ts | 11 ++ src/types/content.ts | 3 +- 40 files changed, 1442 insertions(+), 105 deletions(-) create mode 100644 AGENTS.md create mode 100644 content/evidence.json create mode 100644 content/posts/en/agent-engineering-ownership/index.mdx create mode 100644 content/posts/ko/agent-engineering-ownership/index.mdx create mode 100644 content/resume-manifest.json create mode 100644 docs/operations/evidence-workflow.md create mode 100644 docs/research/ai-positioning-2026-09-22.md create mode 100644 docs/reviews/2026-10-11-live-site-refresh-audit.md create mode 100644 docs/reviews/minglestage-case-study-2026-09-22.md create mode 100644 docs/reviews/portfolio-qa-2026-09-22.md create mode 100644 public/resume/Sihyeong-Lee-Resume-DevEx.pdf create mode 100644 public/resume/Sihyeong-Lee-Resume-FDE.pdf create mode 100644 public/resume/Sihyeong-Lee-Resume.pdf create mode 100644 scripts/evidence.mts create mode 100644 scripts/qa-portfolio.mts create mode 100644 src/components/projects/EvidencePanel.tsx create mode 100644 src/lib/__tests__/evidence-policy.test.ts create mode 100644 src/lib/__tests__/evidence-regressions.test.ts create mode 100644 src/lib/evidence-policy.ts create mode 100644 src/lib/skill-groups.ts create mode 100644 src/lib/telemetry-policy.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3ba241..303d9ce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,9 @@ jobs: - name: Unit tests run: npm test + - name: Evidence and résumé integrity + run: npm run evidence:check + - name: Translation parity run: npm run untranslated @@ -47,5 +50,35 @@ jobs: - name: Build run: npm run build + - name: Install browser for release QA + run: npx playwright install --with-deps chromium + + - name: Production preview browser QA + shell: bash + run: | + mkdir -p .qa/portfolio + npm start -- -p 3100 -H localhost > .qa/portfolio/server.log 2>&1 & + PREVIEW_PID=$! + trap 'kill "$PREVIEW_PID" 2>/dev/null || true' EXIT + ready=0 + for attempt in $(seq 1 40); do + if curl -fsS http://localhost:3100/en/hire > /dev/null; then ready=1; break; fi + sleep 1 + done + test "$ready" = 1 + npm run qa:portfolio + npm run qa:navigation + QA_LOCALE=ko npm run qa:navigation + + - name: Preserve browser QA evidence + if: always() + uses: actions/upload-artifact@v7 + with: + name: portfolio-browser-qa + path: .qa/portfolio/ + include-hidden-files: true + retention-days: 14 + if-no-files-found: warn + - name: Audit dependencies run: npm audit --audit-level=high diff --git a/.gitignore b/.gitignore index 5815c74..a83f63c 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,6 @@ next-env.d.ts # local agent permissions/state .claude/settings.local.json + +# Local verification artifacts; never public content or automatic claims +/.qa/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..69d6369 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,11 @@ +# Portfolio execution guide + +Read README.md and docs/operations/evidence-workflow.md. Preserve existing uncommitted changes. + +- Tasks: live Plane Portfolio (FOLIO), workspace soursea; project ID 1bc2719a-4d8b-4182-ac54-743acfe8d639. Read live work before implementation. Separate implementation, automated QA, visual review and deployment. +- Public evidence: content/evidence.json. Check the Git version before trusting a source README. Collection writes only ignored review candidates and never publishes measurements automatically. +- Résumé originals: notebook hangar/data. Public files are versioned snapshots; do not mix unrelated personal records into this repository. +- Core checks: npm run type-check; npm run lint; npm run format:check; npm test; npm run evidence:check; npm run untranslated; npm run build. +- Browser checks: start production preview, then npm run qa:portfolio and both locales of qa:navigation. Preserve .qa/portfolio/report.json and screenshots. Do not remove console assertions to manufacture PASS. +- Never delete Git lock files without establishing ownership. No force push, visibility change or deployment as an incidental maintenance action. +- Current design/research decisions live under docs/research and docs/reviews. Their written dates and limitations matter. diff --git a/README.md b/README.md index 990f393..dd52bda 100644 --- a/README.md +++ b/README.md @@ -81,3 +81,18 @@ scripts/ content/media verification and capture utilities ``` The project ledger is intentionally broader than "shipped" work. UI counts distinguish total builds from public destinations and store listings rather than presenting every row as a release. + +## Evidence and release QA + +See [the evidence workflow](docs/operations/evidence-workflow.md) for reviewed source snapshots, read-only collection, résumé integrity and production-preview QA. The collector never automatically publishes a new number. + +```bash +npm run evidence:check +npm run evidence:collect +# After npm run build, start a preview in another terminal: +npm start -- -p 3100 -H localhost +# Then run the persisted browser matrix: +npm run qa:portfolio +``` + +The [AI positioning review](docs/research/ai-positioning-2026-09-22.md) separates source-backed engineering themes from unverified market claims. The [MingleStage selection decision](docs/reviews/minglestage-case-study-2026-09-22.md) keeps staged work distinct from public releases. Execution is tracked in Plane Portfolio (FOLIO); screenshots and machine reports are evidence, not automatic human approval. diff --git a/content/about.json b/content/about.json index a4fece3..9b76b2b 100644 --- a/content/about.json +++ b/content/about.json @@ -98,15 +98,15 @@ }, { "name": "Google Gemini", - "category": "tools" + "category": "ai" }, { "name": "Claude API", - "category": "tools" + "category": "ai" }, { "name": "Model Context Protocol", - "category": "tools" + "category": "ai" }, { "name": "Turborepo", @@ -135,6 +135,66 @@ { "name": "Ollama", "category": "infra" + }, + { + "name": "Claude Code", + "category": "ai" + }, + { + "name": "OpenAI / Codex", + "category": "ai" + }, + { + "name": "Agent orchestration", + "category": "ai" + }, + { + "name": "Tool calling", + "category": "ai" + }, + { + "name": "LLM eval harnesses", + "category": "ai" + }, + { + "name": "RAG", + "category": "ai" + }, + { + "name": "MongoDB", + "category": "backend" + }, + { + "name": "TypeORM", + "category": "backend" + }, + { + "name": "SQLite", + "category": "backend" + }, + { + "name": "Celery", + "category": "backend" + }, + { + "name": "PostGIS", + "category": "backend" + }, + { + "name": "AWS", + "category": "infra" + }, + { + "name": "GitHub Actions", + "category": "tools" + }, + { + "name": "pytest", + "category": "tools" + }, + { + "name": "PowerShell", + "category": "tools" } ], "timeline": [ diff --git a/content/evidence.json b/content/evidence.json new file mode 100644 index 0000000..39343b6 --- /dev/null +++ b/content/evidence.json @@ -0,0 +1,51 @@ +{ + "schemaVersion": 1, + "reviewAfter": "2026-12-22", + "records": [ + { + "id": "devdeck-maintenance", + "project": "devdeck", + "kind": "source-snapshot", + "snapshotAt": "2026-09-08", + "reviewedAt": "2026-09-22", + "titleEn": "State consistency & recovery", + "titleKo": "상태 일관성 · 복구 검증", + "value": "1,289 passed · 1 skipped", + "scopeEn": "Documented 1.37.8 candidate validation. Not a current test run or proof of release, installer acceptance, or multi-day physical-network testing.", + "scopeKo": "1.37.8 후보 버전의 문서화된 검사 결과입니다. 현재 테스트 실행·공개 출시·설치 검수·장기간 실기기 네트워크 검증을 의미하지 않습니다.", + "source": { + "repository": "writingdeveloper/devdeck", + "path": "docs/quality-review-2026-09-08.md", + "commit": "b7817547dd2100751ce46229a83810319affe82b", + "sha256": "deac81f7234aa62693414ec7fb04da8ef19200a82b0a1955fbc532423980c372" + }, + "measurements": { + "passed": 1289, + "skipped": 1 + } + }, + { + "id": "citefirst-retrieval", + "project": "citefirst", + "kind": "source-snapshot", + "snapshotAt": "2026-07-29", + "reviewedAt": "2026-09-22", + "titleEn": "Retrieval measured on one corpus", + "titleKo": "명시된 코퍼스에서 측정한 검색 품질", + "value": "recall@5 0.978 · MRR@10 0.834", + "scopeEn": "46 PostgreSQL 17 manual questions in the committed July configuration. The separate 56-question local experiment is uncommitted and is not published as this baseline. Citation-ID validity is not answer correctness.", + "scopeKo": "커밋된 7월 구성으로 PostgreSQL 17 매뉴얼 질문 46개를 평가한 기록입니다. 별도의 56문항 로컬 실험은 미커밋 상태라 이 기준값으로 공개하지 않습니다. 인용 ID 유효성은 답변 정확도와 다릅니다.", + "source": { + "repository": "writingdeveloper/citefirst", + "path": "README.md", + "commit": "bf835b6a138b36f1ddfaa5be21702645973d1293", + "sha256": "1e597f7044e288800845e2feba3ddf1ed11c7717a511d536404a40ff9b6173df" + }, + "measurements": { + "questions": 46, + "recall5": 0.978, + "mrr10": 0.834 + } + } + ] +} diff --git a/content/posts/en/agent-engineering-ownership/index.mdx b/content/posts/en/agent-engineering-ownership/index.mdx new file mode 100644 index 0000000..83a311c --- /dev/null +++ b/content/posts/en/agent-engineering-ownership/index.mdx @@ -0,0 +1,96 @@ +--- +title: "How I Use Coding Agents Without Handing Them Ownership" +excerpt: "My workflow changed from AI-assisted coding to parallel agent execution. The important part is not how much code the agents write, but how architecture, evidence, gates, and release decisions stay explicit." +publishedAt: "2026-09-22" +author: "이시형" +category: development +tags: ["ai", "agents", "developer-tools", "evals", "mcp"] +project: devdeck +--- + +I no longer use coding AI mainly as autocomplete. Most of the time I give an agent a bounded job, let it inspect the repository and execute across files, and review the result as a system change. + +That sounds like delegating engineering. The distinction I care about is **what gets delegated**. + +Implementation can be delegated. Ownership cannot. + +## The unit of work got bigger + +A year ago, the useful unit was often a function or a file. Now I routinely ask Claude Code or Codex to investigate a failure, trace it across several layers, change the implementation, add regression coverage, and run the relevant gates. + +That changes the engineering bottleneck. Typing is less important. The difficult parts become: + +- defining the boundary of the task, +- making the source of truth explicit, +- deciding what evidence counts as done, +- separating model mistakes from system mistakes, +- and preventing a plausible-looking result from becoming a release. + +My recent projects are increasingly built around those boundaries. + +## DevDeck: parallel agents need state ownership + +[DevDeck](/en/projects/devdeck) started as a way to stop losing track of coding sessions across repositories. It grew into a local-first control plane for Claude Code, Codex, and Antigravity sessions. + +The interesting problem was not rendering more terminals. It was deciding who owns shared state. + +A session title edited from one machine cannot become true merely because one renderer displayed it. The host must own the write, persist it, acknowledge it, and make every observer converge on the same result. Failure, reconnect, stale responses, and restart all have to preserve that rule. + +The 1.37.7 review recorded **1,257 passing checks and one skip**. The dated 2026-09-08 maintenance candidate later recorded **1,289 passing checks and one skip**. These are version-scoped historical records, not a live test total. Separate source and packaged-application gates cover the later synchronization work; automated checks are not human or multi-day physical-network acceptance. + +The number matters less than what the tests are protecting: ownership rules around agent work. + +## studios: generation is not verification + +My [studios](/en/studio) platform exposes image, video, 3D, voice, and music generation through MCP tools. + +I deliberately split the pipeline into different responsibilities: + +1. the tool generates, +2. a machine gate rejects obvious failures, +3. the calling agent inspects the returned artifact, +4. the verdict and reason are persisted with the asset. + +The generator does not get to declare its own output good. + +That pattern now feels more important than any particular model choice. Models will change. A pipeline that makes quality boundaries inspectable survives the model swap. + +## Creator Learning OS: unfinished means blocked + +Creator Learning OS is moving toward a commercial SaaS that turns channel data into one concrete next action. + +Its release logic is intentionally conservative. Customer OAuth, billing, provider readiness, managed persistence, backup and recovery are not marketing checkboxes. If a production dependency is missing, release readiness should fail closed. + +I would rather have the system say **not ready** than let an agent reinterpret an incomplete check as approval. + +The same principle applies to AI features: an eval is useful only when failure has a consequence. + +## Worktrees before multi-agent orchestration + +When several agents work in parallel, I prefer isolated git worktrees over having them share one mutable checkout. + +The rule is simple: + +- one task, one worktree, +- explicit acceptance criteria, +- task-specific tests, +- inspect the diff, +- integrate only after the gate passes. + +This is not sophisticated multi-agent research. It is mostly ordinary software isolation applied to agents. That is exactly why it works. + +## What I still keep human-owned + +I use agents heavily, but there are boundaries I do not want to blur: + +- architecture and irreversible product decisions, +- what evidence is sufficient, +- security and privacy tradeoffs, +- whether a failed gate can be waived, +- and the final release decision. + +The goal is not to maximize the percentage of code written by AI. + +The goal is to increase the amount of useful work I can safely supervise while making the system easier to inspect when something goes wrong. + +That is the direction my current work is converging on: **agent systems, tool use, evals, state, observability, and production reliability around the model**. diff --git a/content/posts/ko/agent-engineering-ownership/index.mdx b/content/posts/ko/agent-engineering-ownership/index.mdx new file mode 100644 index 0000000..73d2e31 --- /dev/null +++ b/content/posts/ko/agent-engineering-ownership/index.mdx @@ -0,0 +1,96 @@ +--- +title: "코딩 에이전트에게 구현은 맡겨도 소유권은 넘기지 않는 방법" +excerpt: "AI 보조 코딩에서 병렬 에이전트 실행으로 작업 방식이 바뀌었습니다. 중요한 것은 AI가 코드를 얼마나 많이 쓰느냐가 아니라 아키텍처, 증거, 게이트, 릴리스 결정이 명시적으로 남는가입니다." +publishedAt: "2026-09-22" +author: "이시형" +category: development +tags: ["ai", "agents", "developer-tools", "evals", "mcp"] +project: devdeck +--- + +이제 코딩 AI를 주로 자동완성처럼 쓰지는 않습니다. 범위가 정해진 작업을 에이전트에게 주고, 저장소를 직접 조사하게 한 뒤 여러 파일에 걸쳐 구현하고 검증하게 하는 경우가 더 많습니다. + +겉으로 보면 엔지니어링 자체를 위임하는 것처럼 보입니다. 제가 중요하게 보는 구분은 **무엇을 위임하느냐**입니다. + +구현은 위임할 수 있습니다. 소유권은 위임하지 않습니다. + +## 작업의 단위가 커졌습니다 + +예전에는 함수나 파일 하나가 AI에게 맡기기 좋은 단위였다면, 지금은 Claude Code나 Codex에게 오류 원인을 추적하고, 여러 레이어를 수정하고, 회귀 테스트를 추가하고, 필요한 게이트까지 실행하게 하는 일이 흔합니다. + +그러면 병목도 달라집니다. 타이핑보다 아래 문제가 더 중요해집니다. + +- 작업 경계를 어디까지 둘지, +- source of truth가 무엇인지, +- 어떤 증거를 완료로 인정할지, +- 모델 오류와 시스템 오류를 어떻게 분리할지, +- 그럴듯한 결과가 바로 릴리스가 되지 않게 어떻게 막을지. + +최근 프로젝트들은 점점 이 경계를 중심으로 설계하고 있습니다. + +## DevDeck: 병렬 에이전트에는 상태 소유권이 필요합니다 + +[DevDeck](/projects/devdeck)은 여러 저장소의 코딩 세션을 놓치지 않기 위한 도구로 시작했고, 지금은 Claude Code·Codex·Antigravity 세션을 다루는 local-first control plane에 가깝습니다. + +어려운 문제는 터미널을 더 많이 그리는 것이 아니었습니다. 공유 상태를 누가 소유하는지 정하는 일이었습니다. + +한 머신에서 세션 제목을 바꿨다고 그 renderer가 보여주는 값이 곧 진실이 되어서는 안 됩니다. host가 쓰기를 소유하고, 디스크에 저장하고, 성공을 응답하고, 다른 observer들이 같은 결과로 수렴해야 합니다. 실패·재연결·stale response·재시작이 있어도 이 규칙이 유지돼야 합니다. + +1.37.7 검토에는 **1,257개 통과·1개 생략**, 2026-09-08 유지보수 후보 기록에는 **1,289개 통과·1개 생략**이 있습니다. 서로 다른 버전의 과거 검증 기록이며 현재 실행한 테스트 수가 아닙니다. 이후 동기화 작업은 소스·패키지 게이트를 별도로 유지하고, 자동 검사를 사람의 시각 검수나 장기간 물리 네트워크 검증과 동일시하지 않습니다. + +숫자 자체보다 중요한 것은 그 테스트가 에이전트 작업의 **소유권 규칙**을 지키고 있다는 점입니다. + +## studios: 생성과 검수는 같은 책임이 아닙니다 + +[studios](/studio)는 이미지·영상·3D·음성·음악 생성을 MCP 툴로 노출합니다. + +파이프라인의 책임을 일부러 나눴습니다. + +1. 툴이 생성하고, +2. 기계 게이트가 명백한 실패를 제거하고, +3. 호출한 에이전트가 결과물을 직접 보고, +4. 판정과 이유를 자산과 함께 저장합니다. + +생성기가 자기 결과를 스스로 합격시키지 못하게 한 것입니다. + +이 구조는 특정 모델보다 오래 갈 수 있다고 봅니다. 모델은 바뀌어도 품질 경계가 관찰 가능하게 남는 파이프라인은 유지할 수 있습니다. + +## Creator Learning OS: 미완료는 승인으로 해석하지 않습니다 + +Creator Learning OS는 채널 데이터를 한 가지 구체적인 다음 행동으로 바꾸는 상용 SaaS 방향으로 개발하고 있습니다. + +릴리스 판정은 의도적으로 보수적으로 만들고 있습니다. 고객 OAuth, 결제, provider readiness, 영속 DB, 백업·복구는 마케팅 체크박스가 아닙니다. 프로덕션 의존성이 빠져 있으면 readiness가 fail-closed 해야 합니다. + +에이전트가 불완전한 검사를 승인으로 재해석하는 것보다 시스템이 **아직 준비되지 않음**이라고 말하는 편이 낫습니다. + +AI 기능의 eval도 마찬가지입니다. 실패했을 때 실제로 막히는 것이 있어야 평가가 의미를 가집니다. + +## 멀티 에이전트보다 먼저 git worktree + +여러 에이전트를 병렬로 돌릴 때는 하나의 checkout을 공유시키기보다 격리된 git worktree를 선호합니다. + +규칙은 단순합니다. + +- 작업 하나당 worktree 하나, +- 명시적인 acceptance criteria, +- 작업별 테스트, +- diff 검수, +- gate 통과 후에만 통합. + +복잡한 multi-agent 연구라기보다 기존 소프트웨어 격리 원칙을 에이전트에 적용한 것입니다. 그래서 오히려 안정적으로 작동합니다. + +## 여전히 사람이 소유하는 것 + +에이전트를 많이 사용하지만 아래 경계는 흐리지 않으려고 합니다. + +- 아키텍처와 되돌리기 어려운 제품 결정, +- 어떤 증거면 충분한지, +- 보안·프라이버시 trade-off, +- 실패한 게이트를 예외 처리할 수 있는지, +- 최종 릴리스 결정. + +목표는 AI가 작성한 코드 비율을 최대화하는 것이 아닙니다. + +문제가 생겼을 때 더 쉽게 추적할 수 있는 상태를 유지하면서, 한 사람이 안전하게 감독할 수 있는 유용한 작업량을 늘리는 것이 목표입니다. + +현재 제 작업은 점점 **모델 주변의 agent systems, tool use, evals, state, observability, production reliability** 쪽으로 모이고 있습니다. diff --git a/content/projects.json b/content/projects.json index 6eb3c59..bb0075b 100644 --- a/content/projects.json +++ b/content/projects.json @@ -40,8 +40,8 @@ { "name": "citefirst", "slug": "citefirst", - "descriptionKo": "문서 기반 질의응답(RAG)에서 인용을 화면에 내보내기 전에 검색된 청크와 대조해 검증하고, 검색 품질을 주장이 아니라 측정으로 답하는 시스템. pg_dump와 pg_dumpall, 다섯 종류의 work_mem 설정처럼 거의 똑같아 보이는 문단이 가득한 PostgreSQL 17 공식 매뉴얼 약 3,000쪽을 코퍼스로 골라, 순진한 벡터 검색이 조용히 엉뚱한 문단을 돌려주는 지점을 드러냈습니다. 46개 질문 평가에서 크로스 인코더 재순위화를 켜면 recall@5 0.978, MRR@10 0.834로 평문 벡터 검색의 0.652를 크게 웃돌고, 인용 유효성은 1.000으로 168건 중 환각 인용이 0건입니다. 임베딩과 재순위화가 로컬 ONNX로 돌아 색인 단계에는 외부 호출이 전혀 없습니다.", - "descriptionEn": "A RAG system that verifies every citation against the retrieved chunks before it ever reaches the screen, and answers the question of retrieval quality by measuring it rather than asserting it. The corpus is ~3,000 pages of the PostgreSQL 17 manual — full of passages that look nearly identical (pg_dump vs pg_dumpall, five different work_mem settings), exactly where naive vector search quietly returns the wrong paragraph. Across 46 evaluation questions, cross-encoder reranking scores recall@5 0.978 and MRR@10 0.834 against 0.652 for plain vector search, with citation validity at 1.000 and zero hallucinated citations out of 168. Embeddings and reranking run locally through ONNX, so ingestion makes no outbound calls at all.", + "descriptionKo": "PostgreSQL 17 매뉴얼을 대상으로 로컬 임베딩·재순위화, 질의 재작성, 인용 ID 검증을 결합한 RAG 시스템입니다. 커밋된 46개 질문 구성에서 recall@5 0.978·MRR@10 0.834를 기록했습니다. 인용 ID 포함 여부·모델이 판정한 근거성·답변 정확도는 별도 평가이며, 이후 56문항 로컬 실험은 공개 기준값이 아닌 검토 후보로 남겨 두었습니다.", + "descriptionEn": "A RAG system over the PostgreSQL 17 manual with locally executed embeddings/reranking, query rewriting and citation-ID validation. The committed 46-question configuration records recall@5 0.978 and MRR@10 0.834. Citation membership, model-judged grounding and answer correctness are evaluated separately. A newer 56-question local experiment remains a review candidate, not a published baseline.", "techStack": [ "TypeScript", "Next.js", @@ -65,8 +65,8 @@ "problemEn": "A RAG answer having citations does not prove that the citations support it or that retrieval found the right passage.", "decisionKo": "PostgreSQL 17 매뉴얼처럼 유사 문단이 많은 코퍼스를 평가셋으로 삼고 로컬 임베딩·크로스 인코더 재순위화·출력 전 인용 검증을 분리해 측정했습니다.", "decisionEn": "I used the PostgreSQL 17 manual as a deliberately confusable corpus, then measured local embeddings, cross-encoder reranking, and pre-output citation validation separately.", - "evidenceKo": "46개 평가 질문에서 재순위화 구성은 recall@5 0.978, MRR@10 0.834를 기록했고 인용 유효성은 1.000으로 168건 중 환각 인용이 0건이었습니다.", - "evidenceEn": "Across 46 evaluation questions, reranking reached recall@5 0.978 and MRR@10 0.834; citation validity was 1.000 with zero hallucinated citations in 168.", + "evidenceKo": "고정된 7월 소스에서 PostgreSQL 17 질문 46개, 재순위화 구성 recall@5 0.978·MRR@10 0.834를 기록했습니다. 인용 유효성은 검색 청크에 ID가 있는지 확인하는 것으로 답변의 진실성 보장이 아닙니다. 56문항 작업본 결과는 미커밋 상태이므로 공개 기준값을 자동 대체하지 않습니다.", + "evidenceEn": "Pinned July source: 46 PostgreSQL 17 questions, reranking-on recall@5 0.978 and MRR@10 0.834. Citation validity checks membership in retrieved chunks, not truth of the answer. The 56-question worktree experiment has not been committed and must not silently replace this published reference.", "resultKo": "검색 품질과 인용 정확도를 반복 가능한 수치로 비교할 수 있는 RAG 평가·검증 시스템이 됐습니다.", "resultEn": "Retrieval quality and citation correctness became repeatable measurements instead of qualitative claims." } @@ -107,8 +107,8 @@ { "name": "DevDeck", "slug": "devdeck", - "descriptionKo": "여러 프로젝트를 Claude Code·Codex·Antigravity로 굴리는 개발자를 위한 Electron 관제 데스크톱 앱. 설정한 폴더의 git 레포를 스캔해 git 상태와 방치 기간, 에이전트별 세션 이력을 카드로 보여주고 클릭 한 번으로 마지막 세션을 이어 갑니다. Windows에서는 외부 터미널이 우르르 뜨는 대신 앱 안에 터미널을 여는 조종석을 제공해, 세션마다 모델과 작업 시간, 한계에 가까워질수록 색이 짙어지는 컨텍스트 퍼센트, 그리고 그 세션이 지금 무엇을 하고 있는지 한 줄 요약을 함께 보여주고 급한 순서로 묶어 정렬합니다. 요약을 AI로 다듬을 때는 그 세션을 연 에이전트의 CLI가 직접 처리해 한쪽 벤더의 사용량이 다른 쪽 작업에 쓰이지 않게 했습니다. contextIsolation·sandbox·argv 인젝션 방어 등 Electron 보안을 1급 관심사로 설계하고 465개 테스트와 Playwright+axe e2e 게이트로 검증했습니다.", - "descriptionEn": "An Electron command deck for developers juggling a pile of Claude Code, Codex and Antigravity projects. It scans git repos under configured folders and surfaces git state, how long each has been neglected, and per-agent session history as cards, resuming your last session in one click. On Windows a Cockpit replaces the wall of external terminals with in-app ones: each session shows its model, active working time, a context percentage that colors up as it nears the limit, and a one-line summary of what it is actually working on — grouped by urgency, so you can see who is waiting on you. When AI refinement is on, each summary is condensed by that session's own agent CLI, so one vendor's quota is never spent on another's work. I treated Electron security as a first-class concern (contextIsolation, sandbox, argv-not-string-interpolation against command injection) and backed it with 465 tests and a Playwright + axe e2e gate.", + "descriptionKo": "여러 저장소의 Claude Code·Codex·Antigravity 작업을 모아 보는 local-first Electron 관제 앱입니다. 저장소·세션 상태, 내장 터미널, usage/context 신호를 연결합니다. 문서화된 1.37.8 후보 버전에서는 host-owned 메타데이터·영속 저장·명시적 충돌 복구를 다룹니다. 자동 검증과 실제 출시·설치·물리 네트워크 검수를 구분해 기록합니다.", + "descriptionEn": "A local-first Electron command center for Claude Code, Codex and Antigravity work across repositories. It brings repository/session state, embedded terminals and usage/context signals together. A documented 1.37.8 candidate adds host-owned metadata, persisted writes and explicit conflict recovery. The engineering record separates automated checks from release, installer and physical-network acceptance.", "techStack": [ "TypeScript", "Electron", @@ -122,7 +122,7 @@ "github": "https://github.com/writingdeveloper/devdeck", "private": false, "featured": true, - "updatedAt": "2026-08-26", + "updatedAt": "2026-09-08", "screenshot": "/images/projects/devdeck.webp", "screenshotAltKo": "DevDeck 프로젝트 관제 화면. 여러 Git 프로젝트와 상태, 작업 재개 진입점을 한 화면에 모은 실제 Electron UI.", "screenshotAltEn": "The real DevDeck Electron project command center, listing multiple Git projects with status and resume entry points.", @@ -131,10 +131,10 @@ "problemEn": "When many projects run across different coding agents, a wall of terminals makes it hard to see which session stalled and which needs a human decision.", "decisionKo": "Git 상태·방치 시간·세션 이력을 모으는 Electron 관제판과 앱 내부 Cockpit을 만들고 요약은 각 세션을 연 에이전트 CLI가 담당하도록 분리했습니다.", "decisionEn": "I built an Electron command deck over Git state, neglect time, and session history, plus an in-app Cockpit; each session is summarized by the agent CLI that owns it.", - "evidenceKo": "공개 저장소에는 프로젝트·Cockpit·사용량 화면의 실제 QA 스크린샷과 Electron 보안 및 Playwright/axe 검증 흐름이 함께 유지됩니다.", - "evidenceEn": "The public repository keeps real QA screenshots for projects, Cockpit, and usage alongside Electron-security and Playwright/axe verification paths.", - "resultKo": "여러 에이전트 세션을 작업 우선순위와 재개 지점 중심으로 보는 단일 데스크톱 관제면을 만들었습니다.", - "resultEn": "The result is one desktop control surface organized around agent-session priority and resumability rather than terminal windows." + "evidenceKo": "2026-09-08 유지보수 기록은 1.37.8 후보에서 단위 검사 1,289개 통과·1개 생략과 maintenance/resilience 시나리오를 보고합니다. 이후 동기화 작업은 별도 게이트가 있습니다. 오늘의 실행 결과나 공개 출시 증거가 아닌, 버전과 범위를 한정한 기록입니다.", + "evidenceEn": "The 2026-09-08 maintenance record reports 1,289 passed and one skipped unit check for the 1.37.8 candidate, plus maintenance and resilience journeys. Later synchronization work has its own gate. These are historical, version-scoped records, not today's test count or proof of public release.", + "resultKo": "여러 머신·실패·재연결·재시작에서도 소유권과 동기화 규칙이 유지되는, 병렬 코딩 에이전트 작업용 검증 가능한 control plane을 만들었습니다.", + "resultEn": "The result is an inspectable control plane for parallel coding-agent work, with ownership and synchronization rules that survive multiple machines, failures, reconnects and restarts." } }, { @@ -506,6 +506,35 @@ "private": true, "featured": true }, + { + "name": "Creator Learning OS", + "slug": "creator-learning-os", + "descriptionKo": "YouTube 채널 데이터를 '그래서 지금 무엇을 만들거나 고쳐야 하는가?'라는 하나의 실행 항목으로 바꾸는 evidence-first Creator SaaS. 내부 Load Path 데이터와 고객 CSV 흐름을 같은 모델로 다루고 Today·Video diagnostics·Briefs·Experiments·Playbook을 연결했습니다. SQLite/PostgreSQL 어댑터, tenant 경계, desktop/mobile Playwright QA, fail-closed release readiness와 PostgreSQL backup/recovery tooling까지 구현했으며, 고객 OAuth·billing 등 미완료 요소는 출시로 포장하지 않고 명시적으로 차단합니다. 아직 public/paid SaaS는 출시하지 않았습니다.", + "descriptionEn": "An evidence-first creator SaaS built around one question: what should I create or improve now? It turns YouTube/channel evidence into one concrete next task while keeping the supporting detail on demand. The product connects Today, video diagnostics, saved Briefs, Experiments and a channel Playbook across internal reference data and customer CSV flows, with SQLite/PostgreSQL adapters, tenant boundaries, desktop/mobile Playwright QA, fail-closed release readiness, and PostgreSQL backup/recovery tooling. Customer OAuth, billing and other unfinished production requirements stay explicitly blocked rather than being relabeled as shipped. Public/paid SaaS is not released yet.", + "techStack": [ + "TypeScript", + "Next.js", + "PostgreSQL", + "SQLite", + "Playwright", + "Vitest", + "YouTube Data API" + ], + "status": "building", + "private": true, + "featured": false, + "updatedAt": "2026-09-22", + "caseStudy": { + "problemKo": "크리에이터 분석 도구는 지표를 많이 보여줘도 사용자가 다음에 무엇을 해야 하는지 다시 해석해야 하는 경우가 많습니다.", + "problemEn": "Creator analytics often expose more metrics while still making the user decide what to do next.", + "decisionKo": "대시보드의 중심을 점수나 차트가 아니라 '지금 할 한 가지'로 두고, 근거와 진단은 필요할 때만 펼치도록 설계했습니다. 릴리스 준비도는 미완료 의존성이 있으면 fail-closed 처리합니다.", + "decisionEn": "I centered the product on one concrete next action rather than an opaque score, with evidence and diagnostics available on demand. Release readiness fails closed when production dependencies remain incomplete.", + "evidenceKo": "SQLite/PostgreSQL 어댑터, tenant 경계, desktop/Pixel 7 Playwright QA, provider readiness gate, 4080 배포 검증, PostgreSQL backup/recovery bundle이 저장소에 구현되어 있습니다.", + "evidenceEn": "The repository includes SQLite/PostgreSQL adapters, tenant boundaries, desktop/Pixel 7 Playwright QA, provider-readiness gates, 4080 deployment verification, and PostgreSQL backup/recovery tooling.", + "resultKo": "분석을 읽는 제품에서, 근거를 보존하면서 바로 실행할 작업을 주는 운영 도구로 방향을 좁혔습니다. 아직 미출시 요소는 명시적으로 미출시로 남깁니다.", + "resultEn": "The product is converging from a reporting surface into an operating tool that gives one evidence-backed action. Unfinished release requirements remain explicitly unshipped." + } + }, { "name": "til-shorts", "slug": "til-shorts", diff --git a/content/resume-manifest.json b/content/resume-manifest.json new file mode 100644 index 0000000..9e85df1 --- /dev/null +++ b/content/resume-manifest.json @@ -0,0 +1,18 @@ +{ + "schemaVersion": 1, + "snapshotAt": "2026-09-14", + "files": [ + { + "file": "Sihyeong-Lee-Resume.pdf", + "sha256": "ab4933e15c7516cf455d0547daf4ba4b766c8d1d06a4fddfd8b4ab50a28b6b64" + }, + { + "file": "Sihyeong-Lee-Resume-DevEx.pdf", + "sha256": "9850dc45ed639d0e0998876ea2983bd3ee092c6f88ff45d3a62a9f30f3c4449f" + }, + { + "file": "Sihyeong-Lee-Resume-FDE.pdf", + "sha256": "406ab1da5b66058b831530ad3b99d46a4299586207a586665e7aba5db9919350" + } + ] +} diff --git a/docs/operations/evidence-workflow.md b/docs/operations/evidence-workflow.md new file mode 100644 index 0000000..4f1f9bd --- /dev/null +++ b/docs/operations/evidence-workflow.md @@ -0,0 +1,29 @@ +# Evidence workflow + +Plane Portfolio (FOLIO) is the execution source of truth. Source code and decision/evidence documents live here; local files are not a second task-status database. + +## Public facts versus collection + +- `content/evidence.json`: reviewed source snapshots with version/date/scope, pinned commit and SHA-256. +- `npm run evidence:check`: checks publication metadata, display/measurement consistency, résumé manifest and exact PDF bytes. Offline/CI safe. +- `npm run evidence:collect`: reads only allowlisted DevDeck/citefirst documents, verifies pinned blobs, reports later committed and uncommitted worktree candidates into ignored `.qa/evidence-candidates.json`. **Public content is never modified.** +- `npm run evidence:verify`: verifies pinned source bytes and parsed measurements against local repositories. Set `PORTFOLIO_SOURCE_ROOT` to their parent when they are not siblings. +- `npm run evidence:check -- --require-current-review`: also fails after the review deadline. Elapsed time does not change a historical measurement. + +The collector does not run providers, source-repository tests, Git pushes or deployment. Its parsers fail on unknown upstream formats. Before accepting a candidate, inspect raw runs, version, sample denominator, skipped cases and method, then edit the public manifest in a reviewed change. A source check is not human visual approval. + +## Verification and release + +1. Run type/lint/unit/format/evidence checks and build production assets. +2. Start production preview: `npm start -- -p 3100 -H localhost`. +3. Run `npm run qa:portfolio` and both locales of `qa:navigation`. `QA_BASE_URL` selects another preview; no live account is needed. +4. Preserve `.qa/portfolio/report.json` and screenshots. Its source fingerprint includes uncommitted source files. +5. Report automated QA, image review, production deployment and physical-device testing separately. A captured image is not human approval. A passing source build is not public deployment. + +Vercel analytics endpoints load only on a Vercel production deployment at the canonical public host. Third-party telemetry stays off on local/Tailnet previews. A public self-host may opt in with `PORTFOLIO_ENABLE_TELEMETRY=1`; this does not load Vercel-only endpoints. + +Public résumé PDFs remain a byte-verified **2026-09-14 document snapshot**. Their historical DevDeck numeric wording should be refreshed through the notebook-first hangar workflow. A portfolio collector must not silently rewrite authoritative job-search documents. + +### Local origin constraint + +On the checked Next.js 16.3.3 Windows build, a server explicitly bound to 127.0.0.1 rewrote Korean paths through a localhost origin and entered a self-redirect loop. An initial localhost probe reached an older preview on that port, so that result was not accepted as candidate evidence. On a fresh, isolated port, **both binding and requests set to localhost** returned 200 for EN/KO routes. Browser scripts, CI startup and probes therefore consistently use localhost, which remains loopback-only. This is a local preview configuration finding; the review does not claim a production redirect defect. diff --git a/docs/research/ai-positioning-2026-09-22.md b/docs/research/ai-positioning-2026-09-22.md new file mode 100644 index 0000000..f5ded70 --- /dev/null +++ b/docs/research/ai-positioning-2026-09-22.md @@ -0,0 +1,26 @@ +# AI positioning review — 2026-09-22 + +## Decision and limits + +Keep AI-native product engineering / agent systems as the portfolio specialization, backed by TypeScript/Python, product, backend and infrastructure work. This is an editorial fit decision, not a measured ranking of the whole hiring market. One live posting and three official engineering articles are a limited sample. Articles explain practice, not job-market share or the author's skills. + +## Sources checked + +- [OpenAI: AI Systems Engineer, Codex Agents](https://openai.com/careers/ai-systems-engineer-codex-agents-san-francisco/) — live posting checked 2026-09-22; publication date unstated. Requests harnesses, sandboxing, state, evals, observability and performance, alongside production engineering. It also requests low-level/ML capabilities; do not imply Rust, kernel or GPU-fleet expertise merely because some keywords align. +- [OpenAI: Harness engineering](https://openai.com/index/harness-engineering/) — published 2026-02-11. Reference for repository legibility, acceptance boundaries and inspectable testing. It does not establish universal productivity gains. +- [Anthropic: Demystifying evals for AI agents](https://www.anthropic.com/engineering/demystifying-evals-for-ai-agents) — published 2026-01-09. Separates transcripts from actual end-state outcomes and deterministic, model and human grading. Supports checking artifacts instead of trusting a success report. +- [Anthropic: Effective context engineering](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents) — published 2025-09-29. Foundation for context/tool selection, not a new September 2026 announcement. + +## Evidence mapping + +| Focus | Portfolio evidence | Limitation | +| --- | --- | --- | +| Tool use and agent workflow | DevDeck; studios MCP and persisted verification | Tool availability alone is not autonomous task success | +| Evals and evidence quality | citefirst committed 46-question record | 56-question local changes are uncommitted; LLM judgment is not deterministic truth | +| State and reliability | DevDeck host-owned metadata and recovery records | Candidate evidence is not installed release or physical-network acceptance | +| Production integration | ITEMBOX integrations/billing; GEOMEC infrastructure; Creator OS | Creator OS is unlaunched; do not invent customers, revenue or OAuth readiness | +| Cost and latency | A useful next case-study dimension | Require task, configuration, sample and run artifact before claiming measurements | + +## Next review + +Review by **2026-12-22**, earlier when target roles change. Sample several relevant employers and the user's actual preferred roles before changing weights. No recurring job was scheduled in this pass. Track due work in Plane; do not imply automatic review exists. diff --git a/docs/reviews/2026-10-11-live-site-refresh-audit.md b/docs/reviews/2026-10-11-live-site-refresh-audit.md new file mode 100644 index 0000000..8e7cd9d --- /dev/null +++ b/docs/reviews/2026-10-11-live-site-refresh-audit.md @@ -0,0 +1,96 @@ +# WritingDeveloper live-site and project refresh audit — 2026-10-11 PT + +Status: **reviewed findings; implementation/release not approved by this document**. Existing uncommitted changes must be preserved. No claim that public deployment, visual acceptance, or Plane issue mutation has occurred. + +## Sources inspected + +- Live https://writingdeveloper.blog/ and public routes, HTTP response headers, GitHub repository / Actions. +- 4080 MAIN: `Documents/GitHub/portfolio`, selected adjacent repositories and their current README/Git states. +- Notebook (SIHYEONG-4080): selected creator-learning-os, studios, google-video-lab, music-mv-studio, soursea-site and hangar repositories. +- The existing Portfolio execution guide, 2026-09-22 source/evidence QA review and FOLIO workflow. + +## Verified production facts + +- Public response: HTTP 200; `Server: Vercel`, Next.js routing. **This does not establish Notebook as the HTTP serving host.** +- `/en`, `/ko`, both Hire pages, Studio, Projects, Blog, Play, sitemap, robots, llms.txt: HTTP 200. +- `/resume/Sihyeong-Lee-Resume.pdf`: **HTTP 404** on live at this review. The separate 4080 working tree has three dated PDF snapshots and a checksum manifest; this is a deployment/release discrepancy, not an automatically approved document publication. +- Observed response bodies without compression negotiation: `/en/projects` about 509 KB; `/en/play` about 273 KB; `/en` about 129 KB. These are **not** Lighthouse/Web Vitals measurements. Investigate streaming/server payload and client behavior before optimizing. +- Latest GitHub main observed: `689354e` (2026-09-27). Local MAIN working branch `fix/positioning-alignment-2026-09` has 36 modified/untracked paths; preserve it. +- Live indexed blog section exposes latest highlighted article dated 2026-08-27. The working tree contains an unpublished bilingual agent-engineering article; publication requires editorial and factual QA. + +## Verified quality/CI findings + +- Existing 4080 worktree (before any new edits here): TypeScript, ESLint, Prettier, 224 Vitest tests, evidence manifest/checksums, translation parity, and `next build` all passed on 2026-10-11. +- Open GitHub PR [#32](https://github.com/writingdeveloper/portfolio/pull/32) attempted Next.js 16.3.8 but [GitHub CI run](https://github.com/writingdeveloper/portfolio/actions/runs/37216106114) failed in `npm ci` because `yaml@2.9.1` was missing from package-lock. **No code-test result can be inferred for that PR.** +- Dependency repair is isolated in `../portfolio-security-20261011`, branch `fix/next-security-lockfile-20261011` from GitHub main. Follow the clean-install, type/lint/test, production build and CVE/audit gates before any merge. + +## Project evidence and public-content decisions + +| Candidate | Source checked | 2026-10-11 interpretation | Public treatment | +| --- | --- | --- | --- | +| Creator Learning OS / Creator OS | Notebook creator-learning-os README, 2026-10-07 commit | Backup restore QA documented; customer OAuth and external launch gates remain | Existing entry: update only with source-backed milestones, not launch claims | +| Studio / Studio Gallery | Notebook studios 2026-10-11 commit, working state | Active five-modality production tooling; substantial uncommitted work | Refresh case study after representative screenshots, privacy and model-output approval | +| MingleStage / CrowdStage | MAIN README and staged release notes | Invitation-pilot, open-signup release gates outstanding | Honor prior FOLIO-33 deferral; do not promote as generally launched | +| RailForge | MAIN local research-first README, many uncommitted changes | Browser railway-game R&D | Draft engineering-log case study, label prototype/research | +| Project STRATA | MAIN Unreal spike README | Exploration-game technical spike, runtime/vertical-slice acceptance open | Blog engineering diary candidate, not shipped flagship | +| OpenMontage Reference Lab | MAIN 2026-10-11 latest commit | Video analysis, generation and face-flicker QA experiments | Private/prototype; do not publish personal media or third-party faces by default | +| Music/MV Studio, YuE2, VOCALOID MCP | Notebook and MAIN READMEs | Audio/music toolchains, work-in-progress licensing/output acceptance | Architecture/lessons only after license and attribution review | +| Google Video Lab | Notebook README, 2026-10-03 benchmark commit | Flow/Veo benchmark with private mirror | Research post candidate with redacted benchmark evidence | +| Soursea LLC site | Notebook soursea-site README, 2026-10-11 commit | Separate corporate website on Cloudflare Worker | Cross-link only where audience and brand are appropriate | + +This is a candidate inventory, not a declaration of commercial readiness, users, revenue or successful publication. + +## Proposed FOLIO execution mapping (not synced to live issues yet) + +1. **P0 — FOLIO-36 continuation:** verify résumé content/approval and deploy reviewed changes; check public PDF MIME/SHA, all locale CTAs, rollback. Keep human review separate. +2. **P0 — new security task (check live FOLIO board for duplicate):** resolve PR #32 broken dependency lock, prove clean `npm ci` and CI, merge with dependency-review gate. +3. **P1 — FOLIO-34 continuation:** reconcile MAIN uncommitted feature/evidence work with GitHub main; review localized article and original résumé snapshots. No force push. +4. **P1 — new curation task:** classify recent projects into shipped/pilot/prototype/private, require dated source screenshot and claim-level evidence before publication. +5. **P1 — new UX task:** review Hire CTA and mobile conversion path; test real public endpoints and email links with browser. +6. **P2 — new performance/SEO task:** profile projects page payload, font preloads, image priority, structured data, crawlability; record baseline and after metrics, avoid speculative LCP claims. +7. **P2 — FOLIO-35:** preserve next 2026-12-22 AI positioning review; no automatic market claim. + +## Release guardrails + +Keep changes in isolated branches; do not force-push, expose secrets, auto-publish resumes, launch an invitation pilot as public, or overstate AI/quality metrics. Require immutable source evidence, automated QA, human visual review, physical-device review where applicable, production verification and rollback separately. + +## Plane synchronization state + +Existing workspace `soursea`, project `FOLIO` confirmed by prior registry / repo guide. The project registry was refreshed on the MAIN PC; **issue-level live read/write was not confirmed in this pass**. This report is a source-of-evidence handoff, not a substitute for writing/updating the Plane work items. + +## Same-day security implementation addendum (2026-10-11 PT) + +- Isolated from the 36 pre-existing local WIP paths: `C:\\Users\\SIHYEONG\\Documents\\GitHub\\portfolio-security-20261011`. +- Implemented Next.js 16.4.0 + synchronized npm lockfile. Resolved earlier GitHub Dependabot #32 failure due to missing `yaml` lock entry. Applied compatible transitive patches via `npm audit fix` **without** `--force`. +- GitHub branch `fix/next-security-lockfile-20261011`, commit `bbd749b` pushed. +- Opened **draft** PR [#33](https://github.com/writingdeveloper/portfolio/pull/33), not merged/deployed. +- Verified clean `npm ci` on original security candidate; final repaired lock `npm ci --dry-run` PASS; types, lint, formatting, 197 tests (21 files), i18n parity, production build and `git diff --check` all PASS. This branch starts from public GitHub main and therefore has fewer tests than 4080's uncommitted WIP 224-test branch. +- `npm audit --omit=dev --audit-level=high` still reports **3 high advisories** from `braces` dependency chains (`@keystatic/next` / `chokidar`, Next ESLint tooling). Complete audit reports 7 high. The suggested `npm audit fix --force` would break Keystatic compatibility, so it was intentionally not used. +- GitHub's security alert on default main requires separate review; this source task does not attest that vulnerabilities are eliminated. +- Pending: GitHub Linux CI on draft PR #33, security exception triage, preview browser QA, review and merge, actual Vercel deployment and live smoke test. Do not confuse successful local `next build` with production release. + + +## Linux GitHub CI read-back for draft PR #33 + +- [Run 38195978378](https://github.com/writingdeveloper/portfolio/actions/runs/38195978378): **FAIL overall**, but successful separately: checkout/setup, `npm ci`, type checking, lint, formatting, unit tests, translation parity, hero-image verification and production build. +- Sole failing step: **Audit dependencies**, due to the remaining `braces` advisory (7 High in full dependency audit). That security gate was **not bypassed**; PR remains draft and unmerged. +- This confirms the lockfile/clean-install problem from #32 is resolved in GitHub Linux CI, independently of local Windows checks. + +## Live visual first-viewport review (public routes) + +Captured actual Chromium screenshots at 2026-10-11 PT, saved under ignored `.qa/portfolio/live-20261011/`: + +- `desktop.png`: `/en` at 1440×900. +- `mobile.png`: `/` at 390×844 (Korean). +- `hire-mobile.png`: `/en/hire` at 390×844. +- `projects-desktop.png`: `/en/projects` at 1440×900. + +**Observations (review candidates, not measured conversion or accessibility failures):** + +1. The brutalist/dark editorial visual identity is consistent, readable and distinctive. Preserve it instead of redesigning indiscriminately. +2. English desktop home first viewport is almost entirely the large typographic hero with major open space to the right; no clearly visible work/evidence/contact CTA above fold. Consider a concise featured proof or CTA with A/B and mobile review, without diluting the visual theme. +3. Korean mobile home exposes six tightly spaced textual nav targets across the top; English mobile Hire uses a hamburger/settings language header. Review route-consistent small-screen navigation and actual interactive target geometry against WCAG; screenshots alone do not establish failure. +4. English mobile Hire presents full-time positioning and explanatory text first. The résumé/contact action is not visible in the initial 390×844 viewport. Ensure at least one unambiguous, functional contact/resume CTA is reachable promptly and the public PDF path returns 200 with reviewed content before surfacing the link. +5. Projects desktop selected-work cards have very dense multi-paragraph copy and stacks of skill tags; Studio card lacks a visible screenshot compared to DevDeck. Propose concise 2–3-line outcomes plus scannable evidence/roles/status, with expandable case-study detail. Do **not** invent production scale, release status, or adoption. + +No full-page/mobile interaction or physical-device acceptance is asserted by this static viewport review. Browser screenshots were taken from **public Vercel production**; local uncommitted visual changes were not used. diff --git a/docs/reviews/minglestage-case-study-2026-09-22.md b/docs/reviews/minglestage-case-study-2026-09-22.md new file mode 100644 index 0000000..16da5ca --- /dev/null +++ b/docs/reviews/minglestage-case-study-2026-09-22.md @@ -0,0 +1,11 @@ +# MingleStage case-study decision — 2026-09-22 + +Source reviewed: crowdstage README on 4080. README file revision: 2194ec131083ce9a12ab362579a52255278e5ba1. Repository HEAD during the read: c2422d675076a93b29d3229497e8deb9830e9746. Active development may move these references. + +**Decision: do not promote this to a publicly launched portfolio case study in this pass.** This preserves the distinction between engineering work and public readiness. + +The README reports an invitation-only pilot, with runtime source 613abf5bfdb5a701f9901dcecfd7fc02b8dd3881. The new direction is open signup, password-protected private rooms and restricted guests; these have separate source and production gates. Staged signup implementation is not proof that the public journey is available. + +Promotion requires a stable public entry flow, a version-matched deployment/readiness record, synthetic-account screenshots, media/cross-client evidence, and explicit physical-device/group/Safari limitations. The portfolio review did not operate production accounts, create rooms, change MingleStage code, or invent adoption/performance numbers. + +Keep the existing AI-focused selected work. Revisit MingleStage when its own public-entry and release gates pass. This decision resolves the portfolio selection question without claiming the underlying product is finished. diff --git a/docs/reviews/portfolio-qa-2026-09-22.md b/docs/reviews/portfolio-qa-2026-09-22.md new file mode 100644 index 0000000..da69edd --- /dev/null +++ b/docs/reviews/portfolio-qa-2026-09-22.md @@ -0,0 +1,66 @@ +# Portfolio implementation and QA record — 2026-09-22 (Pacific Time) + +## Result + +Implementation and local automated verification completed. **Not committed, pushed or deployed.** GitHub CI was configured and its YAML parsed; no remote CI run was claimed. Human visual approval and physical-device acceptance remain pending. + +Working branch: `fix/positioning-alignment-2026-09`. +Local production-preview source fingerprint: `6d5c4a9c88c92bdc30f58d50a0bf410f6d498d3c028b78df5f3f6e7feeb1fe8c`. +Browser report recorded at `2026-09-23T05:53:35.646Z` (September 22 in Los Angeles). + +## Verified changes + +- Shared AI-first skill grouping for standard pages and the 3D SkillsSection. +- Corrected résumé CTA background token and mobile project-card badge wrapping. +- Home links to résumé/hire, Studio and every selected project's case study, including private studios. +- Local/preview telemetry no longer requests Vercel-only analytics endpoints or sends production analytics. +- Reviewed evidence manifest pins source commit, normalized text SHA-256, date, numeric measurements and limitations. +- Read-only evidence collection produces ignored review candidates; it never rewrites public content. +- Hire exposes source-linked evidence and the English résumé PDF snapshot date (2026-09-14). +- Persisted browser QA and CI artifact retention replace temporary QA scripts. + +## Corrected evidence claims + +DevDeck's 1,257 passing tests belonged to historical 1.37.7 validation. The published evidence panel now references the dated 1.37.8 maintenance-candidate record: 1,289 passed, one skip. This is not a newly run DevDeck suite, proof of public release or physical-network acceptance. + +citefirst's working README contained 56-question results, but these changes were uncommitted. The collector caught the mismatch against the pinned Git source. Published figures remain the committed 46-question record: recall@5 0.978, MRR@10 0.834. The 56-question figures (0.982 / 0.785) appear only in the private candidate report. Citation-ID validity is not answer correctness. + +## Checks + +| Check | Result | +| --- | --- | +| TypeScript, ESLint, Prettier | Pass | +| Unit/regression suite | 23 files; 223 passed | +| Evidence and résumé-byte checks | Pass; 2 pinned sources verified | +| Evidence candidates | 1 uncommitted-worktree difference; no automatic publication | +| Bilingual posts | 11/11 pairs | +| Production build | 138/138 generation tasks complete | +| Chromium EN/KO × 1440/390px × dark/light | All 8 combinations pass | +| Console/page/network assertions | Pass for matrix routes; no unexpected errors | +| Résumé CTA contrast | Dark 15.28:1; light 5.47:1 | +| New article and Creator OS routes | HTTP 200 in both languages | +| Served PDF integrity | 3/3 application/pdf responses with expected SHA-256 | +| EN and KO navigation suites | Both pass | +| npm audit | 0 known reported vulnerabilities at check time | +| git diff --check | Pass | + +Machine report and eight full-page captures are under `.qa/portfolio/`. Earlier failed origin checks are retained separately. Capturing screenshots and checking geometry/contrast do not amount to human visual acceptance. + +## Preview origin finding + +The Windows Next.js 16.3.3 preview needed consistent `localhost` binding and request origin. An explicit 127.0.0.1 bind produced an unprefixed-locale rewrite loop. An older preview also existed on port 3100, so isolated final verification used `localhost:3190` and a newly started candidate process. Do not treat the earlier mixed-origin result as a production defect or passing candidate evidence. + +## Plane read-back + +- FOLIO-33: Done — selection review complete; defer public MingleStage promotion until its own release gates pass. +- FOLIO-34: QA — implementation and automated QA evidence; not public deployment. +- FOLIO-35: Todo, target 2026-12-22 — first review recorded; next review queued, no automation scheduled. +- FOLIO-36: Todo — newly separated public deployment and live résumé/evidence QA. + +The QA column's display-order change was not applied. Existing statuses remain in use. + +## Remaining release work + +Read-only public check: `/en/hire` returned 200 without the new evidence section; `/resume/Sihyeong-Lee-Resume.pdf` returned 404. Review/commit/push/deployment and same-release public URL verification are therefore still needed under FOLIO-36. + +The authoritative résumé originals in notebook/hangar were not edited. Their numeric wording needs a separate editorial refresh before regenerating public PDFs. No customer adoption, revenue, production deployment or human approval was invented. diff --git a/messages/en.json b/messages/en.json index bd0eb6b..7c7f06d 100644 --- a/messages/en.json +++ b/messages/en.json @@ -1,7 +1,7 @@ { "metadata": { "title": "WritingDeveloper", - "description": "Build logs and engineering notes from Sihyeong Lee — an AI-native product engineer shipping developer tools, applied AI systems, and production full-stack products." + "description": "Build logs and engineering notes from Sihyeong Lee — an AI-native product engineer building agent systems, evals, developer tools, and production full-stack products." }, "nav": { "home": "Home", @@ -16,15 +16,15 @@ "hero": { "greeting": "Hello", "name": "Sihyeong Lee", - "role": "AI-Native Product Engineer", - "description": "I design, ship, and operate AI-native products and developer infrastructure." + "role": "AI-Native Product & Agent Systems Engineer", + "description": "I build production AI systems, developer tools, and full-stack products — with agent workflows, evals, and infrastructure designed for reliability." }, "latestPosts": "Latest Posts", "viewAll": "View All", "featuredProjects": "Projects", "noPosts": "No posts yet.", "explore": "Explore my world", - "metaDescription": "Sihyeong Lee — AI-native product engineer in Los Angeles. I build and operate developer tools, RAG systems, local-AI/GPU infrastructure, and production full-stack products." + "metaDescription": "Sihyeong Lee — AI-native product and agent-systems engineer in Los Angeles. Agent tooling, MCP, evals, RAG, local GPU infrastructure, and production full-stack systems." }, "blog": { "title": "Blog", @@ -75,7 +75,7 @@ "archived": "Archived" }, "selectedWork": "Selected Work", - "selectedWorkDescription": "Five projects selected to show agent tooling, AI infrastructure, measured RAG, production full-stack work, and desktop systems engineering.", + "selectedWorkDescription": "Five projects selected to show agent tooling, AI infrastructure, measured RAG, safety-gated AI product engineering, and production full-stack ownership.", "fullLedger": "Full Ledger", "fullLedgerDescription": "The rest of the record, including work that is still being built.", "caseStudy": { @@ -112,28 +112,28 @@ }, "about": { "title": "About", - "description": "AI-native product engineering, from architecture to production operations", - "metaTitle": "About — AI-Native Product Engineer & Senior Full-Stack", - "metaDescription": "Sihyeong Lee — AI-native product engineer and former CTO in Los Angeles. Developer tooling, applied AI, full-stack products, local GPU infrastructure, and the decisions behind them.", - "body": "I am an AI-native product engineer and former CTO who owns the full path from architecture and implementation through testing, deployment, and production operations. I use coding agents heavily, but the engineering decisions stay explicit: constraints, acceptance criteria, failure analysis, and what ships. Recent work spans developer tooling such as DevDeck, measured RAG in citefirst, civic-tech systems such as RentRights, and a self-hosted MCP/GPU generation platform running across my own infrastructure.", + "description": "AI-native product and agent-systems engineering, from architecture and evals to production operations", + "metaTitle": "About — AI-Native Product & Agent Systems Engineer", + "metaDescription": "Sihyeong Lee — AI-native product and agent-systems engineer and former CTO in Los Angeles. Agent tooling, MCP, evals, applied AI, full-stack systems, and production infrastructure.", + "body": "I am an AI-native product engineer and former CTO who builds the systems around modern models, not just prompts: agent workflows, MCP/tool integrations, evaluation harnesses, retrieval systems, developer tooling, and the full-stack infrastructure that carries them into production. I use coding agents heavily as execution leverage while retaining ownership of architecture, acceptance criteria, code review, testing, debugging, deployment, and release decisions. Recent work includes DevDeck, a command center for coding agents; studios, a multi-modal MCP/GPU platform with persisted verification; citefirst, a measured RAG system; and production SaaS work with explicit safety and release gates.", "skills": "Tech Stack", "timeline": "Timeline" }, "hire": { "title": "Work with me", - "description": "AI-native product engineer open to senior product, applied AI / AI platform, and senior full-stack roles — plus focused project work.", - "metaTitle": "Sihyeong Lee — AI-Native Product Engineer | Senior Full-Stack", - "metaDescription": "AI-native product engineer in Los Angeles, open to remote senior product, applied AI / AI platform, and senior full-stack roles. {shipped} shipped products with a public demo or store listing.", - "badgeRemote": "Los Angeles · Fully remote · US permanent resident", + "description": "AI-native product engineer open to senior product, AI systems / agent platform, and senior full-stack roles — plus focused project work.", + "metaTitle": "Sihyeong Lee — AI-Native Product & Agent Systems Engineer", + "metaDescription": "AI-native product and agent-systems engineer in Los Angeles, open to remote-first senior product, AI systems / agent platform, and senior full-stack roles. {shipped} shipped products with a public demo or store listing.", + "badgeRemote": "Los Angeles · Remote-first · LA hybrid/on-site · US permanent resident", "badgeNow": "Available now", "fulltime": { "heading": "Full-time", "rolesLabel": "Roles", - "roles": "Senior Product Engineer · Applied AI / AI Platform Engineer · Senior Full-Stack Engineer", + "roles": "Senior Product Engineer · AI Systems / Agent Platform Engineer · Senior Full-Stack Engineer", "modeLabel": "Working style", - "mode": "Fully remote (US, Pacific Time) · US permanent resident — no sponsorship required", + "mode": "Remote-first (US, Pacific Time) · open to LA hybrid/on-site and US domestic travel · US permanent resident — no sponsorship required", "bringLabel": "What I bring", - "bring": "Nearly five years owning engineering as a CTO across two companies, plus hands-on AI-native product work spanning agent tooling, RAG evaluation, full-stack systems, CI/QA, and local GPU infrastructure." + "bring": "Nearly five years owning engineering as a CTO across two companies, plus hands-on agent systems, MCP/tool integrations, evals, developer tooling, full-stack products, and production infrastructure." }, "contract": { "heading": "Project work", @@ -152,7 +152,33 @@ "caseHeading": "Selected work" }, "stack": "Tech Stack", - "contactHeading": "Get in touch" + "contactHeading": "Get in touch", + "resume": { + "heading": "Résumé", + "primary": "View résumé", + "specializedLabel": "Specialized versions", + "devex": "Developer Experience / Agent Tooling", + "fde": "Forward Deployed / Production Integration" + }, + "experience": { + "heading": "Experience snapshot", + "soursea": { + "title": "Soursea LLC · Founder & Software Engineer · 2025–Present", + "body": "Agent systems, MCP servers, eval harnesses, full-stack products, and self-hosted GPU/cloud infrastructure." + }, + "itembox": { + "title": "ITEMBOX / Bitnara · CTO · 2024–2025", + "body": "Led nine engineers across Korea and Vietnam while owning a 20-module NestJS platform, integrations, billing, AI services, and AWS operations." + }, + "geomec": { + "title": "GEOMEC · CTO · 2021–2024", + "body": "Sole engineer for desktop software, Linux/network infrastructure, virtualization, access control, and backups." + }, + "casefarms": { + "title": "Case Farms · Quality Assurance · 2023–2024", + "body": "U.S. manufacturing-floor role; moved from production into quality assurance after five months." + } + } }, "studio": { "title": "The Studio", diff --git a/messages/ko.json b/messages/ko.json index dec7cbc..de532b6 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -1,7 +1,7 @@ { "metadata": { "title": "WritingDeveloper", - "description": "AI 네이티브 제품 엔지니어 이시형의 개발 기록. 개발자 도구, Applied AI, 프로덕션 풀스택 제품과 실제 운영 과정을 다룹니다." + "description": "이시형의 빌드 로그와 엔지니어링 기록 — 에이전트 시스템·평가·개발자 도구·프로덕션 풀스택 제품을 만드는 AI 네이티브 제품 엔지니어." }, "nav": { "home": "홈", @@ -16,15 +16,15 @@ "hero": { "greeting": "안녕하세요", "name": "이시형", - "role": "AI 네이티브 제품 엔지니어", - "description": "AI 네이티브 제품과 개발 인프라를 설계하고 배포·운영합니다." + "role": "AI 네이티브 제품 · 에이전트 시스템 엔지니어", + "description": "에이전트 워크플로·평가·신뢰성 인프라를 포함한 프로덕션 AI 시스템, 개발자 도구, 풀스택 제품을 만듭니다." }, "latestPosts": "최근 글", "viewAll": "모두 보기", "featuredProjects": "프로젝트", "noPosts": "글이 없습니다.", "explore": "내 세계를 탐험하기", - "metaDescription": "로스앤젤레스의 AI 네이티브 제품 엔지니어 이시형. 개발자 도구, RAG 시스템, 로컬 AI/GPU 인프라, 프로덕션 풀스택 제품을 직접 구축·운영합니다." + "metaDescription": "로스앤젤레스의 AI 네이티브 제품·에이전트 시스템 엔지니어 이시형. 에이전트 도구, MCP, eval, RAG, 로컬 GPU 인프라, 프로덕션 풀스택 시스템을 구축합니다." }, "blog": { "title": "블로그", @@ -75,7 +75,7 @@ "archived": "보관됨" }, "selectedWork": "대표 작업", - "selectedWorkDescription": "에이전트 도구, AI 인프라, 측정 가능한 RAG, 프로덕션 풀스택, 데스크톱 시스템 엔지니어링을 보여주는 대표 프로젝트 5개입니다.", + "selectedWorkDescription": "에이전트 도구, AI 인프라, 측정 가능한 RAG, 안전 게이트가 있는 AI 제품, 프로덕션 풀스택 소유권을 보여주는 다섯 프로젝트입니다.", "fullLedger": "전체 원장", "fullLedgerDescription": "진행 중인 것까지 포함한 나머지 프로젝트 기록입니다.", "caseStudy": { @@ -112,28 +112,28 @@ }, "about": { "title": "소개", - "description": "아키텍처부터 프로덕션 운영까지 이어지는 AI 네이티브 제품 엔지니어링", - "metaTitle": "이시형 · AI 네이티브 제품 엔지니어 & 시니어 풀스택", - "metaDescription": "로스앤젤레스의 AI 네이티브 제품 엔지니어이자 전 CTO 이시형. 개발자 도구, Applied AI, 풀스택 제품, 로컬 GPU 인프라와 그 안의 엔지니어링 판단을 기록합니다.", - "body": "AI 네이티브 제품 엔지니어이자 전 CTO로서 아키텍처와 구현부터 테스트, 배포, 프로덕션 운영까지 전체 경로를 직접 책임집니다. Claude Code와 Codex 같은 코딩 에이전트를 적극적으로 사용하지만, 제약조건·완료 기준·실패 분석·출시 판단은 명시적으로 소유합니다. 최근에는 DevDeck 같은 개발자 도구, citefirst의 측정형 RAG, RentRights 같은 시빅테크, 직접 운영하는 MCP/GPU 생성 플랫폼을 만들고 운영하고 있습니다.", + "description": "아키텍처·평가부터 프로덕션 운영까지 책임지는 AI 네이티브 제품·에이전트 시스템 엔지니어링", + "metaTitle": "소개 — AI 네이티브 제품 · 에이전트 시스템 엔지니어", + "metaDescription": "로스앤젤레스의 AI 네이티브 제품·에이전트 시스템 엔지니어이자 전 CTO 이시형. 에이전트 도구, MCP, eval, Applied AI, 풀스택 시스템, 프로덕션 인프라.", + "body": "저는 최신 모델 자체보다 그 모델이 실제 일을 하게 만드는 주변 시스템까지 만드는 AI 네이티브 제품 엔지니어이자 전 CTO입니다. 에이전트 워크플로, MCP·툴 연동, 평가 하니스, 검색 시스템, 개발자 도구, 그리고 이를 프로덕션까지 운반하는 풀스택 인프라를 직접 다룹니다. 코딩 에이전트를 적극적으로 실행 레버리지로 사용하지만 아키텍처, 수용 기준, 코드 리뷰, 테스트, 디버깅, 배포, 릴리스 결정은 제가 책임집니다.", "skills": "기술 스택", "timeline": "타임라인" }, "hire": { "title": "함께 일하기", - "description": "시니어 제품·Applied AI / AI 플랫폼·시니어 풀스택 역할과 집중형 프로젝트 의뢰를 받고 있습니다.", - "metaTitle": "이시형 — AI 네이티브 제품 엔지니어 | 시니어 풀스택", - "metaDescription": "로스앤젤레스의 AI 네이티브 제품 엔지니어. 원격 시니어 제품·Applied AI / AI 플랫폼·시니어 풀스택 역할에 지원 중이며, 공개 데모·스토어가 있는 제품 {shipped}건을 직접 출시했습니다.", - "badgeRemote": "로스앤젤레스 · 전면 원격 · 미국 영주권자", + "description": "시니어 제품, AI 시스템 / 에이전트 플랫폼, 시니어 풀스택 역할과 집중형 프로젝트 의뢰를 받고 있습니다.", + "metaTitle": "이시형 — AI 네이티브 제품 · 에이전트 시스템 엔지니어", + "metaDescription": "로스앤젤레스의 AI 네이티브 제품·에이전트 시스템 엔지니어. 원격 우선 시니어 제품·AI 시스템/에이전트 플랫폼·시니어 풀스택 역할에 열려 있으며, 공개 데모·스토어가 있는 제품 {shipped}건을 직접 출시했습니다.", + "badgeRemote": "로스앤젤레스 · 원격 우선 · LA 하이브리드/출근 가능 · 미국 영주권자", "badgeNow": "지금 바로 시작 가능", "fulltime": { "heading": "정규직", "rolesLabel": "찾는 역할", - "roles": "시니어 제품 엔지니어 · Applied AI / AI 플랫폼 엔지니어 · 시니어 풀스택 엔지니어", + "roles": "시니어 제품 엔지니어 · AI 시스템 / 에이전트 플랫폼 엔지니어 · 시니어 풀스택 엔지니어", "modeLabel": "근무 형태", - "mode": "전면 원격(미국, 태평양 표준시) · 영주권자(취업 스폰서 불필요)", + "mode": "미국 원격 우선(태평양 시간) · LA 하이브리드/출근 및 미국 국내 출장 가능 · 영주권자(취업 스폰서 불필요)", "bringLabel": "가져오는 것", - "bring": "두 회사에서 5년 가까이 엔지니어링을 책임진 CTO 경험과, 에이전트 도구·RAG 평가·풀스택 시스템·CI/QA·로컬 GPU 인프라를 직접 만드는 최근 AI 네이티브 제품 경험." + "bring": "두 회사에서 5년 가까이 엔지니어링을 책임진 CTO 경험과, 에이전트 시스템·MCP/툴 연동·eval·개발자 도구·풀스택 제품·프로덕션 인프라를 직접 만드는 최근 경험." }, "contract": { "heading": "프로젝트 의뢰", @@ -152,7 +152,33 @@ "caseHeading": "대표 사례" }, "stack": "기술 스택", - "contactHeading": "연락" + "contactHeading": "연락", + "resume": { + "heading": "이력서", + "primary": "이력서 보기", + "specializedLabel": "직무별 버전", + "devex": "Developer Experience / Agent Tooling", + "fde": "Forward Deployed / Production Integration" + }, + "experience": { + "heading": "경력 요약", + "soursea": { + "title": "Soursea LLC · Founder & Software Engineer · 2025–현재", + "body": "에이전트 시스템, MCP 서버, eval 하니스, 풀스택 제품, 셀프호스트 GPU/클라우드 인프라." + }, + "itembox": { + "title": "ITEMBOX / Bitnara · CTO · 2024–2025", + "body": "한국·베트남 9인 개발팀을 이끌며 20모듈 NestJS 플랫폼, 외부 연동, 결제, AI 서비스, AWS 운영을 직접 책임." + }, + "geomec": { + "title": "GEOMEC · CTO · 2021–2024", + "body": "데스크톱 소프트웨어, Linux/네트워크 인프라, 가상화, 접근제어, 백업을 담당한 단독 엔지니어." + }, + "casefarms": { + "title": "Case Farms · Quality Assurance · 2023–2024", + "body": "미국 제조 현장 근무. 생산라인에서 시작해 5개월 뒤 품질보증으로 이동." + } + } }, "studio": { "title": "스튜디오", diff --git a/package.json b/package.json index a1730dc..2735240 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,11 @@ "verify:hero": "tsx scripts/verify-hero.ts", "capture:screenshots": "tsx scripts/capture-screenshots.ts", "fetch:fonts": "tsx scripts/fetch-pretendard-subset.ts", - "qa:navigation": "tsx scripts/qa-navigation.ts" + "qa:navigation": "tsx scripts/qa-navigation.ts", + "evidence:check": "tsx scripts/evidence.mts", + "evidence:collect": "tsx scripts/evidence.mts --collect", + "evidence:verify": "tsx scripts/evidence.mts --verify-local", + "qa:portfolio": "tsx scripts/qa-portfolio.mts" }, "dependencies": { "@keystatic/core": "^0.5.48", diff --git a/public/resume/Sihyeong-Lee-Resume-DevEx.pdf b/public/resume/Sihyeong-Lee-Resume-DevEx.pdf new file mode 100644 index 0000000000000000000000000000000000000000..aea15c5637f503c5567c2c9b524284bac188a568 GIT binary patch literal 84927 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 MBT`X`D@q{#A6EUYDgXcg literal 0 HcmV?d00001 diff --git a/public/resume/Sihyeong-Lee-Resume-FDE.pdf b/public/resume/Sihyeong-Lee-Resume-FDE.pdf new file mode 100644 index 0000000000000000000000000000000000000000..efb608f1585dcb4434a8829c3159aa6c461adb3e GIT binary patch literal 88049 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ⅈ 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 Vsp(S}2aSsO!sZ?x8zO?t{{=Jq0CxZY literal 0 HcmV?d00001 diff --git a/public/resume/Sihyeong-Lee-Resume.pdf b/public/resume/Sihyeong-Lee-Resume.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c1bf6ab1880b4626778c38486d21067960b32a77 GIT binary patch literal 87672 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 ^PxU3P_)722^7UbBQ*`(>wjiMI=Rqpf;Kbeu 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 Ns!L$thPY^#e*u;p?mPeh literal 0 HcmV?d00001 diff --git a/scripts/evidence.mts b/scripts/evidence.mts new file mode 100644 index 0000000..5fa8a89 --- /dev/null +++ b/scripts/evidence.mts @@ -0,0 +1,106 @@ +import fs from 'node:fs' +import path from 'node:path' +import { createHash } from 'node:crypto' +import { execFileSync } from 'node:child_process' +import manifest from '../content/evidence.json' +import resume from '../content/resume-manifest.json' +import { EVIDENCE_SOURCES, evidenceProblems, evidenceValue, extractMeasurements } from '../src/lib/evidence-policy' + +const sha = (text: string | Buffer) => createHash('sha256').update(text).digest('hex') +const args = new Set(process.argv.slice(2)) +const allowed = new Set(['--collect', '--verify-local', '--require-current-review']) +for (const arg of args) if (!allowed.has(arg)) throw new Error('Unsupported evidence option: ' + arg) +const errors = evidenceProblems(manifest) +const expectedFiles = new Set([ + 'Sihyeong-Lee-Resume.pdf', + 'Sihyeong-Lee-Resume-DevEx.pdf', + 'Sihyeong-Lee-Resume-FDE.pdf', +]) +for (const entry of resume.files) { + if (!expectedFiles.delete(entry.file)) { + errors.push('Unknown/duplicate résumé file') + continue + } + const file = fs.readFileSync(path.join('public/resume', entry.file)) + if (file.subarray(0, 5).toString() !== '%PDF-' || sha(file) !== entry.sha256) + errors.push('Résumé bytes changed: ' + entry.file) +} +if (expectedFiles.size) errors.push('Missing résumé manifest entries') +const reviewDue = new Date().toISOString().slice(0, 10) > manifest.reviewAfter +if (reviewDue && args.has('--require-current-review')) errors.push('Evidence review overdue: ' + manifest.reviewAfter) +if (errors.length) throw new Error(errors.join('\n')) + +if (args.has('--collect') || args.has('--verify-local')) { + const sourceRoot = path.resolve(process.env.PORTFOLIO_SOURCE_ROOT ?? '..') + const candidates = [] + for (const record of manifest.records) { + const spec = EVIDENCE_SOURCES[record.id] + const cwd = path.resolve(sourceRoot, spec.localDirectory) + const git = (a: string[]) => + execFileSync('git', a, { cwd, encoding: 'utf8', timeout: 15_000, maxBuffer: 2_000_000 }) + .replace(/\r\n/g, '\n') + .trimEnd() + // git show reads the committed blob, never a worktree file, secret or arbitrary command. + const pinned = execFileSync('git', ['show', record.source.commit + ':' + spec.path], { + cwd, + encoding: 'utf8', + timeout: 15_000, + maxBuffer: 2_000_000, + }).replace(/\r\n/g, '\n') + if (sha(pinned) !== record.source.sha256) throw new Error('Pinned source digest mismatch: ' + record.id) + const parsed = extractMeasurements(record.id, pinned) + if (JSON.stringify(parsed) !== JSON.stringify(record.measurements)) + throw new Error('Measurement/source mismatch: ' + record.id) + const commit = git(['log', '-1', '--format=%H', '--', spec.path]) + if (!/^[a-f0-9]{40}$/.test(commit)) throw new Error('Source revision missing') + const text = execFileSync('git', ['show', commit + ':' + spec.path], { + cwd, + encoding: 'utf8', + timeout: 15_000, + maxBuffer: 2_000_000, + }).replace(/\r\n/g, '\n') + const measurements = extractMeasurements(record.id, text) + const candidate = { + id: record.id, + source: { repository: spec.repository, path: spec.path, commit, sha256: sha(text) }, + measurements, + changed: + commit !== record.source.commit || + sha(text) !== record.source.sha256 || + JSON.stringify(measurements) !== JSON.stringify(record.measurements), + requiresReview: true, + } + const worktreeText = fs.readFileSync(path.join(cwd, spec.path), 'utf8').replace(/\r\n/g, '\n') + const worktreeDiffers = sha(worktreeText) !== sha(text) + let worktreeMeasurements: Record | null = null + if (worktreeDiffers) { + try { + worktreeMeasurements = extractMeasurements(record.id, worktreeText) + } catch { + /* report changed bytes, do not guess */ + } + } + candidates.push({ ...candidate, worktreeDiffers, worktreeMeasurements, worktreePublished: false }) + console.log('SOURCE VERIFIED', record.id, evidenceValue(record)) + } + if (args.has('--collect')) { + fs.mkdirSync('.qa', { recursive: true }) + fs.writeFileSync( + '.qa/evidence-candidates.json', + JSON.stringify({ collectedAt: new Date().toISOString(), publicContentModified: false, candidates }, null, 2) + + '\n' + ) + console.log( + 'COLLECTED', + candidates.length, + 'candidates; changed:', + candidates.filter((c) => c.changed || c.worktreeDiffers).length, + '; public content unchanged' + ) + } +} +console.log( + 'PASS evidence structure, scope, résumé bytes; next review:', + manifest.reviewAfter, + reviewDue ? '(DUE)' : '' +) diff --git a/scripts/qa-navigation.ts b/scripts/qa-navigation.ts index d44f0f1..68968c9 100644 --- a/scripts/qa-navigation.ts +++ b/scripts/qa-navigation.ts @@ -2,7 +2,7 @@ import { chromium, type Page } from 'playwright' import enMessages from '../messages/en.json' import koMessages from '../messages/ko.json' -const BASE_URL = (process.env.QA_BASE_URL ?? 'http://127.0.0.1:3100').replace(/\/$/, '') +const BASE_URL = (process.env.QA_BASE_URL ?? 'http://localhost:3100').replace(/\/$/, '') const LOCALE = process.env.QA_LOCALE ?? 'en' const prefix = LOCALE === 'ko' ? '' : `/${LOCALE}` const navMessages = LOCALE === 'ko' ? koMessages.nav : enMessages.nav diff --git a/scripts/qa-portfolio.mts b/scripts/qa-portfolio.mts new file mode 100644 index 0000000..e51ccc1 --- /dev/null +++ b/scripts/qa-portfolio.mts @@ -0,0 +1,157 @@ +import fs from 'node:fs' +import path from 'node:path' +import { execFileSync } from 'node:child_process' +import { createHash } from 'node:crypto' +import { chromium } from 'playwright' +import resumes from '../content/resume-manifest.json' + +const base = (process.env.QA_BASE_URL ?? 'http://localhost:3100').replace(/\/$/, '') +const output = path.resolve('.qa/portfolio') +fs.mkdirSync(output, { recursive: true }) +const sha = (data: Buffer | string) => createHash('sha256').update(data).digest('hex') +const sources = execFileSync('git', ['ls-files', '--cached', '--others', '--exclude-standard'], { encoding: 'utf8' }) + .split(/\r?\n/) + .filter((p) => /^(src|content|messages|scripts)\//.test(p) || /^(package.*json|next.config.ts)$/.test(p)) + .sort() +const sourceFingerprint = sha(sources.map((p) => p + ':' + sha(fs.readFileSync(p))).join('\n')) +const results: object[] = [] +const failures: string[] = [] +function assert(ok: unknown, message: string): asserts ok { + if (!ok) throw new Error(message) +} +function luminance(css: string) { + const rgb = css + .match(/[\d.]+/g) + ?.slice(0, 3) + .map(Number) + if (!rgb || rgb.length !== 3) throw new Error('Unrecognized computed color: ' + css) + const c = rgb.map((v) => { + const s = v / 255 + return s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4 + }) + return 0.2126 * c[0] + 0.7152 * c[1] + 0.0722 * c[2] +} +const browser = await chromium.launch({ headless: true }) +try { + for (const locale of ['en', 'ko']) + for (const width of [1440, 390]) + for (const theme of ['dark', 'light'] as const) { + const label = locale + '-' + width + '-' + theme + const ctx = await browser.newContext({ + viewport: { width, height: width === 390 ? 844 : 1000 }, + colorScheme: theme, + }) + await ctx.addInitScript((t) => localStorage.setItem('theme', t), theme) + const page = await ctx.newPage() + const errors: string[] = [] + const requests: string[] = [] + page.on('pageerror', (e) => errors.push('pageerror: ' + e.message)) + page.on('console', (m) => { + if (m.type() === 'error') errors.push('console: ' + m.text() + ' @ ' + m.location().url) + }) + // ERR_ABORTED is an expected browser cancellation when deliberately navigating; all other failures are fatal. + page.on('requestfailed', (req) => { + if (req.failure()?.errorText !== 'net::ERR_ABORTED') + errors.push('request: ' + req.url() + ' ' + req.failure()?.errorText) + }) + page.on('response', (r) => { + if (r.status() >= 400) errors.push('HTTP ' + r.status() + ' ' + r.url()) + }) + page.on('request', (r) => requests.push(r.url())) + const prefix = locale === 'ko' ? '' : '/en' + try { + for (const route of ['/hire', '/about', '']) { + const response = await page.goto(base + prefix + route, { waitUntil: 'networkidle', timeout: 30000 }) + assert(response?.ok(), 'route unavailable: ' + route) + await page.evaluate(() => document.fonts.ready) + assert((await page.locator('h1').count()) === 1, 'Expected one H1 at ' + route) + assert( + !(await page.evaluate(() => document.documentElement.scrollWidth > innerWidth + 1)), + 'Horizontal overflow at ' + route + ) + if (route === '/hire') { + const primary = page.locator('a[href="/resume/Sihyeong-Lee-Resume.pdf"]') + assert(await primary.isVisible(), 'Primary résumé CTA missing') + const colors = await primary.evaluate((el) => ({ + bg: getComputedStyle(el).backgroundColor, + fg: getComputedStyle(el).color, + })) + assert(colors.bg !== 'rgba(0, 0, 0, 0)', 'Résumé CTA background is transparent') + const a = luminance(colors.bg), + b = luminance(colors.fg) + const contrast = (Math.max(a, b) + 0.05) / (Math.min(a, b) + 0.05) + assert(contrast >= 4.5, 'Résumé CTA contrast ' + contrast.toFixed(2)) + assert(await page.locator('#engineering-evidence').isVisible(), 'Evidence section missing') + assert((await page.locator('a[href*="/blob/"]').count()) >= 2, 'Pinned evidence links missing') + await page.screenshot({ path: path.join(output, label + '-hire.png'), fullPage: true }) + results.push({ label, route, contrast: Number(contrast.toFixed(2)), screenshot: label + '-hire.png' }) + } + if (route === '/about') + assert( + (await page.locator('body').innerText()).includes( + locale === 'ko' ? 'AI / 에이전트 시스템' : 'AI / Agent Systems' + ), + 'AI skill category missing' + ) + if (!route) { + const link = page.locator('a[href="' + prefix + '/projects/studios"]').first() + assert((await link.count()) === 1, 'Private studios card has no case-study link') + await link.click() + await page.waitForURL('**' + prefix + '/projects/studios') + assert( + (await page.locator('h1').innerText()).toLowerCase().includes('studios'), + 'Case study navigation failed' + ) + } + } + assert( + !requests.some((url) => /_vercel\/(?:insights|speed-insights)/.test(url)), + 'Local preview requested Vercel-only endpoints' + ) + assert(errors.length === 0, errors.join(' | ')) + console.log('PASS', label, 'home/hire/about/case-study; console/network clean') + } catch (e) { + failures.push(label + ': ' + (e instanceof Error ? e.message : String(e))) + await page.screenshot({ path: path.join(output, label + '-failure.png'), fullPage: true }).catch(() => {}) + } finally { + await ctx.close() + } + } + const ctx = await browser.newContext() + const page = await ctx.newPage() + for (const prefix of ['', '/en']) + for (const route of ['/projects/creator-learning-os', '/blog/agent-engineering-ownership']) { + const r = await page.goto(base + prefix + route, { waitUntil: 'domcontentloaded' }) + assert(r?.ok() && (await page.locator('h1').count()) === 1, 'New content failed: ' + route) + results.push({ route: prefix + route, status: r?.status() }) + } + for (const file of resumes.files) { + const r = await ctx.request.get(base + '/resume/' + file.file) + assert(r.ok() && r.headers()['content-type']?.includes('application/pdf'), 'PDF response invalid') + assert(sha(await r.body()) === file.sha256, 'Served résumé bytes mismatch: ' + file.file) + results.push({ file: file.file, hashVerified: true }) + console.log('PASS PDF', file.file) + } + await ctx.close() +} catch (e) { + failures.push(e instanceof Error ? e.message : String(e)) +} finally { + await browser.close() + const report = { + checkedAt: new Date().toISOString(), + base, + sourceFingerprint, + status: failures.length ? 'FAIL' : 'PASS', + browser: 'Chromium headless', + humanVisualAcceptance: false, + productionDeploymentVerified: false, + results, + failures, + } + fs.writeFileSync(path.join(output, 'report.json'), JSON.stringify(report, null, 2) + '\n') + console.log(report.status, 'portfolio QA; report:', path.join(output, 'report.json')) + if (failures.length) { + console.error(failures.join('\n')) + process.exitCode = 1 + } +} diff --git a/src/app/[locale]/LedgerHome.tsx b/src/app/[locale]/LedgerHome.tsx index 0b26135..2949636 100644 --- a/src/app/[locale]/LedgerHome.tsx +++ b/src/app/[locale]/LedgerHome.tsx @@ -22,7 +22,7 @@ const CARD = 'var(--l-card)' const ELEV = 'var(--l-elev)' const BORDER = 'var(--l-border)' -const STACK = ['TypeScript', 'Next.js', 'React', 'Three.js', 'NestJS', 'Electron', 'Python'] +const STACK = ['MCP', 'Agent Evals', 'Claude Code', 'Codex', 'TypeScript', 'Python', 'Next.js', 'PostgreSQL'] // YAML frontmatter dates (`publishedAt: 2026-06-10`) parse to a Date at runtime // even though PostMeta types it as string — normalize to a YYYY-MM-DD string so @@ -153,6 +153,13 @@ function FeaturedCard({ project, locale }: { project: Project; locale: string }) )} - {/* Counts come from the ledger, never from prose. */} + + + {/* Counts are a secondary inventory, not proof of quality. */}

{t('evidence.heading')}

diff --git a/src/app/[locale]/layout.tsx b/src/app/[locale]/layout.tsx index e83d94b..9d036fe 100644 --- a/src/app/[locale]/layout.tsx +++ b/src/app/[locale]/layout.tsx @@ -14,6 +14,7 @@ import { SpeedInsights } from '@vercel/speed-insights/next' import { GoogleAdSense } from '@/components/analytics/GoogleAdSense' import { GoogleAnalytics } from '@/components/analytics/GoogleAnalytics' import { OutboundTracker } from '@/components/analytics/OutboundTracker' +import { telemetryPolicy } from '@/lib/telemetry-policy' import '../globals.css' // Noto Sans KR is gone. It was added (FOLIO-22) as *the* Korean face, before @@ -112,6 +113,10 @@ export default async function LocaleLayout({ const messages = await getMessages() const headersList = await headers() const nonce = headersList.get('x-nonce') ?? undefined + const telemetry = telemetryPolicy( + { VERCEL_ENV: process.env.VERCEL_ENV, PORTFOLIO_ENABLE_TELEMETRY: process.env.PORTFOLIO_ENABLE_TELEMETRY }, + headersList.get('host') + ) return ( @@ -136,13 +141,13 @@ export default async function LocaleLayout({ {/* Third-party analytics/ads load after hydration (next/script afterInteractive) so they stay off the critical render path. */} - + {telemetry.thirdParty && } {/* One delegated listener turns departures (demo, code, store, mail) into named GA4 events, without making any card a client component. */} - - - - + {telemetry.thirdParty && } + {telemetry.thirdParty && } + {telemetry.vercel && } + {telemetry.vercel && } ) diff --git a/src/app/[locale]/play/sections/SkillsSection.tsx b/src/app/[locale]/play/sections/SkillsSection.tsx index 2de02ae..99d53ce 100644 --- a/src/app/[locale]/play/sections/SkillsSection.tsx +++ b/src/app/[locale]/play/sections/SkillsSection.tsx @@ -2,13 +2,15 @@ import type { Skill } from '@/types/content' import { skillCategories } from '@/types/content' +import { groupSkills } from '@/lib/skill-groups' import { GlowOrb } from '../components/GlowOrb' import { SectionLabel } from '../components/SectionLabel' import { SectionDivider } from '../components/SectionDivider' import { SECTION_SPACING } from '../scene/CameraRig' import { categoryX } from '@/lib/skills-layout' -const CATEGORY_COLORS: Record = { +const CATEGORY_COLORS: Record = { + ai: '#c6f24e', frontend: '#7b6f99', backend: '#8b7355', tools: '#6b6891', @@ -24,12 +26,7 @@ interface SkillsSectionProps { export function SkillsSection({ skills, locale, sectionLabel }: SkillsSectionProps) { const sectionY = -SECTION_SPACING * 2 - const grouped = { - frontend: skills.filter((s) => s.category === 'frontend'), - backend: skills.filter((s) => s.category === 'backend'), - tools: skills.filter((s) => s.category === 'tools'), - infra: skills.filter((s) => s.category === 'infra'), - } + const grouped = groupSkills(skills) const categoryLabel = (cat: string) => skillCategories[cat as keyof typeof skillCategories]?.[locale as 'ko' | 'en'] ?? cat @@ -54,7 +51,7 @@ export function SkillsSection({ skills, locale, sectionLabel }: SkillsSectionPro key={skill.name} position={[x, y, z]} label={skill.name} - color={CATEGORY_COLORS[category] ?? '#7c6cf0'} + color={CATEGORY_COLORS[category as Skill['category']]} /> ) })} diff --git a/src/components/projects/EvidencePanel.tsx b/src/components/projects/EvidencePanel.tsx new file mode 100644 index 0000000..d5f84b2 --- /dev/null +++ b/src/components/projects/EvidencePanel.tsx @@ -0,0 +1,41 @@ +import { useLocale } from 'next-intl' +import manifest from '../../../content/evidence.json' +import { evidenceUrl } from '@/lib/evidence-policy' + +export function EvidencePanel() { + const ko = useLocale() === 'ko' + return ( +
+

+ {ko ? '검증 범위가 있는 엔지니어링 증거' : 'Engineering evidence, with scope'} +

+

+ {ko + ? '숫자만 제시하지 않습니다. 기록 시점, 소스 버전, 검증하지 않은 범위를 함께 남깁니다.' + : 'Each figure is tied to a dated source version and states what was not validated.'} +

+
+ {manifest.records.map((record) => ( + + ))} +
+
+ ) +} diff --git a/src/components/projects/ProjectCard.tsx b/src/components/projects/ProjectCard.tsx index 0bedd0e..40d0d9b 100644 --- a/src/components/projects/ProjectCard.tsx +++ b/src/components/projects/ProjectCard.tsx @@ -78,7 +78,7 @@ export function ProjectCard({ project, priority = false, relatedPost }: ProjectC
-
+
{/* The name is the route into the project's own page — every card needs one inbound link or those pages are orphans. */}

diff --git a/src/components/ui/SkillGrid.tsx b/src/components/ui/SkillGrid.tsx index 424dfba..25f95b8 100644 --- a/src/components/ui/SkillGrid.tsx +++ b/src/components/ui/SkillGrid.tsx @@ -1,6 +1,7 @@ import { useLocale } from 'next-intl' import type { Skill } from '@/types/content' import { skillCategories } from '@/types/content' +import { groupSkills } from '@/lib/skill-groups' /** * The stack, grouped by category. @@ -12,12 +13,7 @@ import { skillCategories } from '@/types/content' */ export function SkillGrid({ skills }: { skills: Skill[] }) { const locale = useLocale() - const grouped = { - frontend: skills.filter((s) => s.category === 'frontend'), - backend: skills.filter((s) => s.category === 'backend'), - tools: skills.filter((s) => s.category === 'tools'), - infra: skills.filter((s) => s.category === 'infra'), - } + const grouped = groupSkills(skills) return (
diff --git a/src/lib/__tests__/employment-positioning.test.ts b/src/lib/__tests__/employment-positioning.test.ts index ec97df6..360bc77 100644 --- a/src/lib/__tests__/employment-positioning.test.ts +++ b/src/lib/__tests__/employment-positioning.test.ts @@ -8,19 +8,19 @@ import ko from '../../../messages/ko.json' describe('employment positioning', () => { it('leads the home page with the AI-native product-engineer positioning', () => { const home = readFileSync(join(process.cwd(), 'src/app/[locale]/LedgerHome.tsx'), 'utf8') - expect(home).toContain('AI-NATIVE PRODUCT ENGINEER') + expect(home).toContain('AI-NATIVE PRODUCT · AGENT SYSTEMS ENGINEER') expect(home).not.toContain('SOLO FULL-STACK BUILDER') - expect(home).toContain('AI-native products and developer infrastructure') + expect(home).toContain('systems that let AI agents do real work') expect(home).toContain('SELECTED_WORK.map') }) - it('targets senior product, applied AI, and senior full-stack roles in English', () => { - expect(en.home.metaDescription).toContain('AI-native product engineer') - expect(en.about.metaTitle).toContain('AI-Native Product Engineer') - expect(en.hire.metaTitle).toContain('AI-Native Product Engineer') - expect(en.hire.badgeRemote).toBe('Los Angeles · Fully remote · US permanent resident') + it('targets senior product, agent systems, and senior full-stack roles in English', () => { + expect(en.home.metaDescription).toContain('AI-native product and agent-systems engineer') + expect(en.about.metaTitle).toContain('AI-Native Product & Agent Systems Engineer') + expect(en.hire.metaTitle).toContain('AI-Native Product & Agent Systems Engineer') + expect(en.hire.badgeRemote).toBe('Los Angeles · Remote-first · LA hybrid/on-site · US permanent resident') expect(en.hire.fulltime.roles).toBe( - 'Senior Product Engineer · Applied AI / AI Platform Engineer · Senior Full-Stack Engineer' + 'Senior Product Engineer · AI Systems / Agent Platform Engineer · Senior Full-Stack Engineer' ) expect(en.hire.fulltime.bring).toContain('Nearly five years owning engineering as a CTO') }) @@ -50,12 +50,12 @@ describe('employment positioning', () => { }) it('keeps the Korean positioning aligned with the English profile', () => { - expect(ko.home.metaDescription).toContain('AI 네이티브 제품 엔지니어') - expect(ko.about.metaTitle).toContain('AI 네이티브 제품 엔지니어') - expect(ko.hire.metaTitle).toContain('AI 네이티브 제품 엔지니어') - expect(ko.hire.badgeRemote).toBe('로스앤젤레스 · 전면 원격 · 미국 영주권자') + expect(ko.home.metaDescription).toContain('AI 네이티브 제품·에이전트 시스템 엔지니어') + expect(ko.about.metaTitle).toContain('AI 네이티브 제품 · 에이전트 시스템 엔지니어') + expect(ko.hire.metaTitle).toContain('AI 네이티브 제품 · 에이전트 시스템 엔지니어') + expect(ko.hire.badgeRemote).toBe('로스앤젤레스 · 원격 우선 · LA 하이브리드/출근 가능 · 미국 영주권자') expect(ko.hire.fulltime.roles).toBe( - '시니어 제품 엔지니어 · Applied AI / AI 플랫폼 엔지니어 · 시니어 풀스택 엔지니어' + '시니어 제품 엔지니어 · AI 시스템 / 에이전트 플랫폼 엔지니어 · 시니어 풀스택 엔지니어' ) }) }) diff --git a/src/lib/__tests__/evidence-policy.test.ts b/src/lib/__tests__/evidence-policy.test.ts new file mode 100644 index 0000000..7289306 --- /dev/null +++ b/src/lib/__tests__/evidence-policy.test.ts @@ -0,0 +1,87 @@ +import { describe, expect, it } from 'vitest' +import data from '../../../content/evidence.json' +import { evidenceProblems, evidenceUrl, evidenceValue, extractMeasurements } from '../evidence-policy' +const now = new Date('2026-09-22T23:59:00Z') +describe('evidence policy', () => { + it('accepts the curated, dated snapshots', () => expect(evidenceProblems(data, now)).toEqual([])) + it('rejects mutable branch refs', () => { + const m = structuredClone(data) + m.records[0].source.commit = 'main' + expect(evidenceProblems(m, now)).toContain('Source must use a full commit SHA') + }) + it('rejects arbitrary paths and private sources', () => { + const m = structuredClone(data) + m.records[0].source.path = '../../.env' + expect(evidenceProblems(m, now).some((x) => x.includes('allowlisted'))).toBe(true) + }) + it('rejects duplicate records', () => { + const m = structuredClone(data) + m.records.push(m.records[0]) + expect(evidenceProblems(m, now).some((x) => x.includes('Duplicate'))).toBe(true) + }) + it('rejects future dates and unscoped claims', () => { + const m = structuredClone(data) + m.records[0].snapshotAt = '2027-01-01' + m.records[0].scopeKo = '' + expect(evidenceProblems(m, now)).toContain('Invalid/future evidence date') + expect(evidenceProblems(m, now)).toContain('Missing localized evidence/scope') + }) + it('does not permit changing the displayed count independently', () => { + const m = structuredClone(data) + m.records[0].value = '999,999 passed' + expect(evidenceProblems(m, now)).toContain('Display value differs from measurements') + }) + it('ties visible numbers to their measurement record', () => { + for (const r of data.records) { + expect(evidenceValue(r)).toBe(r.value) + expect(evidenceUrl(r)).toContain(r.source.commit) + } + }) + it('extracts pass and skip counts from the exact validation row', () => { + expect( + extractMeasurements( + 'devdeck-maintenance', + '| Unit suite including validation, CAS and real TLS conflict | 108 files; 1,289 passed, 1 pre-existing skip |' + ) + ).toEqual({ passed: 1289, skipped: 1 }) + }) + it('retains the evaluation denominator, recall and MRR', () => { + expect( + extractMeasurements( + 'citefirst-retrieval', + '56 questions, in the shipped configuration\n| recall@5 | **0.982** |\n| MRR@10 | **0.785** |' + ) + ).toEqual({ questions: 56, recall5: 0.982, mrr10: 0.785 }) + }) + it('fails on an unknown format rather than manufacturing a metric', () => { + expect(() => extractMeasurements('devdeck-maintenance', 'all tests great')).toThrow() + expect(() => extractMeasurements('citefirst-retrieval', 'no numbers')).toThrow() + expect(() => extractMeasurements('unknown', 'anything')).toThrow() + }) +}) + +describe('measurement boundaries', () => { + it('rejects a missing required field without throwing', () => { + const m = structuredClone(data) + Reflect.deleteProperty(m.records[0].measurements, 'passed') + expect(evidenceProblems(m, now)).toContain('Invalid measurements') + }) + it('rejects an out-of-range fraction', () => { + const m = structuredClone(data) + m.records[1].measurements.recall5 = 2 + expect(evidenceProblems(m, now)).toContain('Invalid measurements') + }) + it('rejects a missing denominator', () => { + const m = structuredClone(data) + m.records[1].measurements.questions = 0 + expect(evidenceProblems(m, now)).toContain('Invalid measurements') + }) + it('reads the committed two-configuration table without confusing the baseline', () => { + expect( + extractMeasurements( + 'citefirst-retrieval', + '46 questions, in the shipped configuration\n| recall@5 | 0.957 | **0.978** |\n| MRR@10 | 0.778 | **0.834** |' + ) + ).toEqual({ questions: 46, recall5: 0.978, mrr10: 0.834 }) + }) +}) diff --git a/src/lib/__tests__/evidence-regressions.test.ts b/src/lib/__tests__/evidence-regressions.test.ts new file mode 100644 index 0000000..11f3793 --- /dev/null +++ b/src/lib/__tests__/evidence-regressions.test.ts @@ -0,0 +1,49 @@ +import { describe, expect, it } from 'vitest' +import { readFileSync } from 'node:fs' +import { groupSkills } from '../skill-groups' +import { telemetryPolicy } from '../telemetry-policy' +import { skillCategories, type Skill } from '@/types/content' +import about from '../../../content/about.json' + +describe('skills and preview regressions', () => { + it('renders every skill exactly once with AI first', () => { + const groups = groupSkills(about.skills as Skill[]) + expect(Object.keys(groups)).toEqual(Object.keys(skillCategories)) + expect(Object.keys(groups)[0]).toBe('ai') + expect(Object.values(groups).flat()).toHaveLength(about.skills.length) + expect(groups.ai.some((s) => s.name === 'Claude Code')).toBe(true) + }) + it.each(['src/components/ui/SkillGrid.tsx', 'src/app/[locale]/play/sections/SkillsSection.tsx'])( + 'uses shared categories in %s', + (file) => { + expect(readFileSync(file, 'utf8')).toContain('groupSkills(skills)') + } + ) + it.each([null, 'localhost:3100', '100.96.248.54:3100', 'branch.vercel.app', 'writingdeveloper.blog.evil.example'])( + 'keeps telemetry off at %s', + (host) => { + expect(telemetryPolicy({ VERCEL_ENV: 'production' }, host)).toEqual({ thirdParty: false, vercel: false }) + } + ) + it('keeps preview deployments silent even on a canonical host', () => { + expect(telemetryPolicy({ VERCEL_ENV: 'preview' }, 'writingdeveloper.blog').vercel).toBe(false) + }) + it('enables production Vercel analytics only on the public host', () => { + expect(telemetryPolicy({ VERCEL_ENV: 'production' }, 'writingdeveloper.blog')).toEqual({ + thirdParty: true, + vercel: true, + }) + }) + it('allows an explicit public self-host opt-in without Vercel scripts', () => { + expect(telemetryPolicy({ PORTFOLIO_ENABLE_TELEMETRY: '1' }, 'writingdeveloper.blog')).toEqual({ + thirdParty: true, + vercel: false, + }) + }) + it('has a defined résumé button token and case-study route for private work', () => { + const hire = readFileSync('src/app/[locale]/hire/page.tsx', 'utf8') + expect(hire).not.toContain('bg-[var(--accent)]') + expect(hire).toContain('bg-[var(--accent-text)]') + expect(readFileSync('src/app/[locale]/LedgerHome.tsx', 'utf8')).toContain('Case study & evidence') + }) +}) diff --git a/src/lib/__tests__/projects.test.ts b/src/lib/__tests__/projects.test.ts index 6952afe..c4fbd34 100644 --- a/src/lib/__tests__/projects.test.ts +++ b/src/lib/__tests__/projects.test.ts @@ -230,16 +230,17 @@ describe('portfolio selection and truthful stats', () => { }) }) -describe('selected ledger refresh', () => { +describe('2026-09 ledger refresh', () => { const ledger = projectsData.projects as Project[] - it('keeps JuiceBar and adds the public BRAIN//VAT case study', () => { - expect(ledger).toHaveLength(43) - const juicebar = ledger.find((project) => project.slug === 'juicebar') - expect(juicebar).toBeDefined() - expect(juicebar?.github).toBe('https://github.com/writingdeveloper/JuiceBar') - expect(juicebar?.screenshot).toBe('/images/projects/juicebar.webp') - expect(juicebar?.caseStudy?.evidenceEn).toBeTruthy() + it('adds Creator Learning OS to the ledger without pretending it has shipped', () => { + expect(ledger).toHaveLength(44) + const creator = ledger.find((project) => project.slug === 'creator-learning-os') + expect(creator).toBeDefined() + expect(creator?.status).toBe('building') + expect(creator?.private).toBe(true) + expect(creator?.website).toBeUndefined() + expect(creator?.caseStudy?.evidenceEn).toBeTruthy() }) it('adds BRAIN//VAT as a public demo without exposing a private repo', () => { @@ -260,8 +261,8 @@ describe('selected ledger refresh', () => { }) describe('portfolio information architecture', () => { - it('aligns hire case studies with agent tooling, production full-stack, RAG, and MCP infrastructure', () => { - expect(HIRE_CASE_STUDIES).toEqual(['devdeck', 'rentrights', 'citefirst', 'studios']) + it('aligns hire case studies with agent tooling, MCP infrastructure, RAG, and safety-gated AI product work', () => { + expect(HIRE_CASE_STUDIES).toEqual(['devdeck', 'studios', 'citefirst', 'healframe']) }) it('partitions selected work in editorial order without duplicating it in the full ledger', () => { diff --git a/src/lib/evidence-policy.ts b/src/lib/evidence-policy.ts new file mode 100644 index 0000000..64c3d0d --- /dev/null +++ b/src/lib/evidence-policy.ts @@ -0,0 +1,98 @@ +export interface EvidenceRecord { + id: string + project: string + kind: string + snapshotAt: string + reviewedAt: string + titleEn: string + titleKo: string + value: string + measurements: Record + scopeEn: string + scopeKo: string + source: { repository: string; path: string; commit: string; sha256: string } +} +export interface EvidenceManifest { + schemaVersion: number + reviewAfter: string + records: EvidenceRecord[] +} + +// A repository/filename allowlist prevents the collector from reading arbitrary private files. +export const EVIDENCE_SOURCES: Record = { + 'devdeck-maintenance': { + repository: 'writingdeveloper/devdeck', + path: 'docs/quality-review-2026-09-08.md', + localDirectory: 'devdeck', + }, + 'citefirst-retrieval': { repository: 'writingdeveloper/citefirst', path: 'README.md', localDirectory: 'citefirst' }, +} +const validDate = (value: string) => + /^\d{4}-\d{2}-\d{2}$/.test(value) && + !Number.isNaN(Date.parse(value)) && + new Date(value).toISOString().slice(0, 10) === value + +export function evidenceProblems(manifest: EvidenceManifest, now = new Date()): string[] { + const issues: string[] = [] + if (manifest.schemaVersion !== 1) issues.push('Unsupported evidence schema') + if (!validDate(manifest.reviewAfter)) issues.push('Invalid reviewAfter') + const seen = new Set() + for (const record of manifest.records) { + if (seen.has(record.id)) issues.push('Duplicate evidence: ' + record.id) + seen.add(record.id) + const source = EVIDENCE_SOURCES[record.id] + if (!source || source.repository !== record.source.repository || source.path !== record.source.path) + issues.push('Source not allowlisted: ' + record.id) + const m = record.measurements + const nonnegativeInt = (v: number | undefined) => typeof v === 'number' && Number.isInteger(v) && v >= 0 + const fraction = (v: number | undefined) => typeof v === 'number' && Number.isFinite(v) && v >= 0 && v <= 1 + const validMeasurements = + Boolean(m) && + (record.id === 'devdeck-maintenance' + ? nonnegativeInt(m.passed) && nonnegativeInt(m.skipped) + : record.id === 'citefirst-retrieval' + ? nonnegativeInt(m.questions) && m.questions! > 0 && fraction(m.recall5) && fraction(m.mrr10) + : false) + if (!validMeasurements) issues.push('Invalid measurements') + else if (evidenceValue(record) !== record.value) issues.push('Display value differs from measurements') + if (record.kind !== 'source-snapshot') issues.push('Only source snapshots may be published here') + if (!/^[a-f0-9]{40}$/.test(record.source.commit)) issues.push('Source must use a full commit SHA') + if (!/^[a-f0-9]{64}$/.test(record.source.sha256)) issues.push('Invalid source digest') + for (const date of [record.snapshotAt, record.reviewedAt]) + if (!validDate(date) || Date.parse(date) > now.getTime()) issues.push('Invalid/future evidence date') + if (record.snapshotAt > record.reviewedAt) issues.push('Review predates snapshot') + if (record.reviewedAt > manifest.reviewAfter) issues.push('Review deadline predates verification') + for (const text of [record.titleEn, record.titleKo, record.scopeEn, record.scopeKo, record.value]) + if (!text?.trim()) issues.push('Missing localized evidence/scope') + } + if (manifest.records.length === 0) issues.push('Missing evidence records') + return issues +} +export function evidenceUrl(record: EvidenceRecord): string { + return 'https://github.com/' + record.source.repository + '/blob/' + record.source.commit + '/' + record.source.path +} + +/** These narrow parsers fail when upstream formats change instead of inventing a new count. */ +export function extractMeasurements(id: string, text: string): Record { + if (id === 'devdeck-maintenance') { + const match = text.match(/Unit suite including[^|]*\|\s*\d+ files; ([\d,]+) passed, (\d+) pre-existing skip/) + if (!match) throw new Error('DevDeck validation row not recognized') + return { passed: Number(match[1].replaceAll(',', '')), skipped: Number(match[2]) } + } + if (id === 'citefirst-retrieval') { + const questions = text.match(/(\d+) questions, in the shipped configuration/) + const recall = text.match(/^\| recall@5 \|[^\n]*?\*\*([\d.]+)\*\*/m) + const mrr = text.match(/^\| MRR@10 \|[^\n]*?\*\*([\d.]+)\*\*/m) + if (!questions || !recall || !mrr) throw new Error('citefirst evaluation table not recognized') + return { questions: Number(questions[1]), recall5: Number(recall[1]), mrr10: Number(mrr[1]) } + } + throw new Error('Unapproved evidence source: ' + id) +} +export function evidenceValue(record: EvidenceRecord): string { + const m = record.measurements + if (record.id === 'devdeck-maintenance') + return m.passed!.toLocaleString('en-US') + ' passed · ' + m.skipped + ' skipped' + if (record.id === 'citefirst-retrieval') + return 'recall@5 ' + m.recall5!.toFixed(3) + ' · MRR@10 ' + m.mrr10!.toFixed(3) + throw new Error('Unknown evidence kind') +} diff --git a/src/lib/projects.ts b/src/lib/projects.ts index 358ac28..0dd3101 100644 --- a/src/lib/projects.ts +++ b/src/lib/projects.ts @@ -156,7 +156,7 @@ export function getHireStats(projects: Pick[]) * infrastructure. Chosen for engineering evidence rather than product count. * A slug that stops resolving fails the test suite rather than the page. */ -export const HIRE_CASE_STUDIES = ['devdeck', 'rentrights', 'citefirst', 'studios'] as const +export const HIRE_CASE_STUDIES = ['devdeck', 'studios', 'citefirst', 'healframe'] as const /** * How the home page's ALL WORK section groups the ledger, in render order. @@ -204,10 +204,11 @@ export const HOME_GROUPS: Record<'products' | 'games' | 'tools', string[]> = { 'studio-apartment', ], tools: [ - 'citefirst', - 'juicebar', 'devdeck', 'studios', + 'creator-learning-os', + 'citefirst', + 'juicebar', 'til-shorts', 'mv-analyzer', 'sitedeck', diff --git a/src/lib/skill-groups.ts b/src/lib/skill-groups.ts new file mode 100644 index 0000000..5d36711 --- /dev/null +++ b/src/lib/skill-groups.ts @@ -0,0 +1,8 @@ +import { skillCategories, type Skill } from '@/types/content' + +/** Shared by the standard pages and the 3D scene: categories cannot silently disappear. */ +export function groupSkills(skills: Skill[]): Record { + return Object.fromEntries( + Object.keys(skillCategories).map((category) => [category, skills.filter((skill) => skill.category === category)]) + ) as Record +} diff --git a/src/lib/telemetry-policy.ts b/src/lib/telemetry-policy.ts new file mode 100644 index 0000000..577f2b2 --- /dev/null +++ b/src/lib/telemetry-policy.ts @@ -0,0 +1,11 @@ +export interface TelemetryEnvironment { + VERCEL_ENV?: string + PORTFOLIO_ENABLE_TELEMETRY?: string +} + +/** Local/previews must not request Vercel-only endpoints or pollute real visitor analytics. */ +export function telemetryPolicy(env: TelemetryEnvironment, host: string | null) { + const canonicalHost = host?.toLowerCase().replace(/:443$/, '') === 'writingdeveloper.blog' + const publicProduction = canonicalHost && (env.VERCEL_ENV === 'production' || env.PORTFOLIO_ENABLE_TELEMETRY === '1') + return { thirdParty: publicProduction, vercel: publicProduction && env.VERCEL_ENV === 'production' } +} diff --git a/src/types/content.ts b/src/types/content.ts index 7e9af7a..7fc7081 100644 --- a/src/types/content.ts +++ b/src/types/content.ts @@ -65,7 +65,7 @@ export interface Tombstone { export interface Skill { name: string - category: 'frontend' | 'backend' | 'tools' | 'infra' + category: 'ai' | 'frontend' | 'backend' | 'tools' | 'infra' } export interface TimelineItem { @@ -88,6 +88,7 @@ export interface PostSummary { } export const skillCategories = { + ai: { ko: 'AI / 에이전트 시스템', en: 'AI / Agent Systems' }, frontend: { ko: '프론트엔드', en: 'Frontend' }, backend: { ko: '백엔드', en: 'Backend' }, tools: { ko: '도구', en: 'Tools' }, From 2ad65c44639be66160a5dfde25d51ee4939c5393 Mon Sep 17 00:00:00 2001 From: Si Hyeong Lee Date: Sun, 11 Oct 2026 21:42:34 -0700 Subject: [PATCH 05/10] feat(portfolio): surface verified 2026 prototypes and improve hiring UX --- content/projects.json | 78 +++++++++++++++++++++++++ src/app/[locale]/LedgerHome.tsx | 42 +++++++------ src/app/[locale]/hire/page.tsx | 16 ++++- src/components/projects/ProjectCard.tsx | 9 ++- src/lib/__tests__/projects.test.ts | 20 ++++++- src/lib/projects.ts | 3 + 6 files changed, 145 insertions(+), 23 deletions(-) diff --git a/content/projects.json b/content/projects.json index 6891169..623f52e 100644 --- a/content/projects.json +++ b/content/projects.json @@ -564,6 +564,84 @@ "resultEn": "The product is converging from a reporting surface into an operating tool that gives one evidence-backed action. Unfinished release requirements remain explicitly unshipped." } }, + { + "name": "RailForge", + "slug": "railforge", + "descriptionKo": "철도 건설·운영·운전을 하나의 3D 웹 세계에서 연결하려는 브라우저 게임 프로토타입입니다. 선로 곡선·대차 움직임·연동장치·공유 운전 권한을 독립 실험으로 검증하고 있습니다. 현재 개발·테스트 중인 연구 프로젝트이며 정식 멀티플레이 게임으로 출시하지 않았습니다.", + "descriptionEn": "A research-first 3D browser railway prototype combining network construction, dispatch, and direct train driving. Separate experiments probe spline/bogie motion, interlocking, multiplayer authority, and a playable two-town loop. The integrated multiplayer game is not a public release.", + "techStack": [ + "TypeScript", + "Three.js", + "Vite", + "Vitest" + ], + "status": "building", + "private": true, + "featured": false, + "updatedAt": "2026-09-29", + "caseStudy": { + "problemKo": "철도 시뮬레이션에서 네트워크 설계·운영·운전자 조작을 같은 세계의 일관된 상태로 연결하기 어렵습니다.", + "problemEn": "Railway games often separate network planning, dispatch operations, and interactive driving into disconnected experiences.", + "decisionKo": "하나의 거대한 게임을 먼저 만들기보다 선형·대차·분기기 연동·공유 권한의 핵심 위험을 작은 독립 실험으로 분해했습니다.", + "decisionEn": "Instead of declaring a full game complete, I split core risks into isolated experiments for rail geometry, bogies, interlocking, and shared driving authority.", + "evidenceKo": "4080 PC의 RailForge 저장소에 Three.js/Vite 기반 playable-toy, dispatcher, multiplayer 및 spline-bogie 실험 코드와 검사 스크립트가 존재합니다. 일부 작업은 미커밋이며 전체 플레이 경험 검증은 별도입니다.", + "evidenceEn": "The MAIN-PC repository contains a Three.js/Vite playable-toy and separate dispatcher, multiplayer, and spline-bogie experiments with verification scripts. Some work remains uncommitted; end-to-end player acceptance is a separate gate.", + "resultKo": "연구용 프로토타입과 기술 실험 단계입니다. 안정적인 정식 출시나 만족스러운 전체 게임플레이는 아직 입증하지 않았습니다.", + "resultEn": "Prototype and engineering research only. Stable public launch and accepted end-to-end gameplay have not been demonstrated." + } + }, + { + "name": "Project STRATA", + "slug": "project-strata", + "descriptionKo": "거대한 폐허 산업 도시를 탐험하며 시설을 복구하는 Unreal Engine 5.8 싱글플레이 게임 기술 스파이크입니다. 차량 MULE과 인프라 퍼즐의 핵심 감각을 검증하고 있으며 30~45분 버티컬 슬라이스 승인 전에는 정식 제작·출시로 주장하지 않습니다.", + "descriptionEn": "An Unreal Engine 5.8 technical spike for an atmospheric, vehicle-led exploration game set in a vast abandoned industrial city. MULE traversal and infrastructure-reactivation puzzles remain subject to a 30–45-minute vertical-slice acceptance gate; it is not a shipped game.", + "techStack": [ + "Unreal Engine 5.8", + "3D Gameplay", + "Prototyping" + ], + "status": "building", + "private": true, + "featured": false, + "updatedAt": "2026-10-06", + "caseStudy": { + "problemKo": "전투 없이 이동·탐색·시설 복구만으로 몰입도 있는 게임 흐름이 성립하는지 검증해야 했습니다.", + "problemEn": "The central question is whether traversal, discovery, and restoring dead infrastructure form a satisfying loop without combat.", + "decisionKo": "전면 제작보다 MULE 이동·환경 탐색·복구의 시각적 보상이 연결되는 버티컬 슬라이스를 먼저 설정했습니다.", + "decisionEn": "I set a vertical-slice gate for MULE traversal, environmental exploration, and visible world-state changes before committing to full production.", + "evidenceKo": "MAIN PC의 project-strata/game/Strata/Strata.uproject와 설계·QA 문서, 2026-10-06 커밋을 확인했습니다. 게임플레이 수용 QA는 미완료입니다.", + "evidenceEn": "The MAIN-PC repository contains a Strata.uproject, implementation and QA plans, and a 2026-10-06 committed technical-spike update. Gameplay acceptance remains open.", + "resultKo": "Unreal 기술 검증 단계로 플레이 가능성과 재미가 충분히 입증되지 않아 출시작으로 표시하지 않습니다.", + "resultEn": "An Unreal feasibility experiment, not a released product. Full gameplay and fun-factor acceptance remain open." + } + }, + { + "name": "Music / MV Studio", + "slug": "music-mv-studio", + "descriptionKo": "여러 로컬 생성 모델의 음악 결과물을 원본 이동 없이 프로젝트 단위로 정리하고 비교·선정하며 MV 컷을 계획하는 비공개 제작 도구입니다. Notebook의 WebUI/SQLite와 MAIN PC의 생성 작업을 연결하고 있지만 실제 H3 렌더 제출 연동은 아직 구현 중입니다.", + "descriptionEn": "A private project-first control surface for multi-model music and music-video creation. It catalogs immutable generator outputs across Notebook and MAIN, supports A/B listening and approval states, and plans MV shots. H3 render submission remains explicitly unwired.", + "techStack": [ + "Node.js", + "SQLite", + "Vite", + "Python", + "ComfyUI" + ], + "status": "building", + "private": true, + "featured": false, + "updatedAt": "2026-10-09", + "caseStudy": { + "problemKo": "음악 모델마다 산재한 생성 결과를 원본을 훼손하지 않고 비교·선정·영상화하기 어렵습니다.", + "problemEn": "Music-model outputs become scattered artifacts, making review, version selection, and MV planning hard without mutating source files.", + "decisionKo": "엔진 출력 폴더는 읽기 전용 이력으로 유지하고, 작업 상태·승인·A/B 비교·스토리보드와 작업 큐를 별도 SQLite 카탈로그로 관리합니다.", + "decisionEn": "I leave engine output folders immutable while a SQLite catalog manages project state, approvals, synchronized A/B review, MV shot windows, and queued work.", + "evidenceKo": "Notebook의 music-mv-studio README와 구현에 WebUI, SQLite 카탈로그, lazy 오디오 캐시, A/B 청취, 검증 스크립트가 있으며 H3 워크플로 바인딩 미완료가 명시되어 있습니다.", + "evidenceEn": "The Notebook music-mv-studio README and implementation document its WebUI, SQLite catalog, lazy audio cache, A/B listening, and QA scripts; H3 workflow binding is explicitly incomplete.", + "resultKo": "개인 연구·제작 과정에서 사용하는 비공개 도구입니다. 공개 음악 SaaS나 완성된 자동 MV 제작기로 오인하지 않도록 구분합니다.", + "resultEn": "A private creative-workflow tool under active development, not a public music SaaS or finished automated MV generator." + } + }, { "name": "til-shorts", "slug": "til-shorts", diff --git a/src/app/[locale]/LedgerHome.tsx b/src/app/[locale]/LedgerHome.tsx index 2949636..ceb0eb9 100644 --- a/src/app/[locale]/LedgerHome.tsx +++ b/src/app/[locale]/LedgerHome.tsx @@ -269,7 +269,7 @@ export function LedgerHome({
{/* Hero */} -
+
+
+ + {locale === 'ko' ? '경력 · 이력서 보기' : 'Experience & résumé'} → + + + {locale === 'ko' ? 'AI 파이프라인 사례' : 'Inside the AI pipeline'} → + + + {locale === 'ko' ? '검증된 작업 사례 보기' : 'Explore selected work'} → + +
-
- - {locale === 'ko' ? '경력 · 이력서 보기' : 'Experience & résumé'} → - - - {locale === 'ko' ? 'AI 파이프라인 사례' : 'Inside the AI pipeline'} → - -
- {/* Stats ribbon */}
{stats.map((s) => ( diff --git a/src/app/[locale]/hire/page.tsx b/src/app/[locale]/hire/page.tsx index 3e4f730..8f56538 100644 --- a/src/app/[locale]/hire/page.tsx +++ b/src/app/[locale]/hire/page.tsx @@ -114,9 +114,23 @@ function HireContent() { ))}
+ -
+

{t('resume.heading')}

diff --git a/src/components/projects/ProjectCard.tsx b/src/components/projects/ProjectCard.tsx index 40d0d9b..c8d04af 100644 --- a/src/components/projects/ProjectCard.tsx +++ b/src/components/projects/ProjectCard.tsx @@ -100,7 +100,7 @@ export function ProjectCard({ project, priority = false, relatedPost }: ProjectC )}

{project.descriptionKo && ( -

+

{locale === 'en' ? project.descriptionEn || project.descriptionKo : project.descriptionKo}

)} @@ -109,7 +109,7 @@ export function ProjectCard({ project, priority = false, relatedPost }: ProjectC {project.techStack?.length > 0 && (
- {project.techStack.map((tech) => ( + {project.techStack.slice(0, 6).map((tech) => ( ))} + {project.techStack.length > 6 && ( + + +{project.techStack.length - 6} + + )}
)} diff --git a/src/lib/__tests__/projects.test.ts b/src/lib/__tests__/projects.test.ts index bfee224..be0bea5 100644 --- a/src/lib/__tests__/projects.test.ts +++ b/src/lib/__tests__/projects.test.ts @@ -230,11 +230,27 @@ describe('portfolio selection and truthful stats', () => { }) }) +describe('2026-10 verified source-backed research entries', () => { + const ledger = projectsData.projects as Project[] + it('does not conflate unfinished private prototypes with public releases', () => { + for (const slug of ['railforge', 'project-strata', 'music-mv-studio']) { + const project = ledger.find((item) => item.slug === slug) + expect(project).toBeDefined() + expect(project?.status).toBe('building') + expect(project?.private).toBe(true) + expect(project?.website).toBeUndefined() + expect(project?.github).toBeUndefined() + expect(project?.featured).toBe(false) + expect(project?.caseStudy?.resultEn).toBeTruthy() + } + }) +}) + describe('2026-09 ledger refresh', () => { const ledger = projectsData.projects as Project[] it('adds Creator Learning OS to the ledger without pretending it has shipped', () => { - expect(ledger).toHaveLength(45) + expect(ledger).toHaveLength(48) const creator = ledger.find((project) => project.slug === 'creator-learning-os') expect(creator).toBeDefined() expect(creator?.status).toBe('building') @@ -254,7 +270,7 @@ describe('2026-09 ledger refresh', () => { }) it('keeps JuiceBar in the expanded portfolio ledger', () => { - expect(ledger).toHaveLength(45) + expect(ledger).toHaveLength(48) const juicebar = ledger.find((project) => project.slug === 'juicebar') expect(juicebar).toBeDefined() expect(juicebar?.github).toBe('https://github.com/writingdeveloper/JuiceBar') diff --git a/src/lib/projects.ts b/src/lib/projects.ts index 9284fbb..52b1cd7 100644 --- a/src/lib/projects.ts +++ b/src/lib/projects.ts @@ -193,6 +193,8 @@ export const HOME_GROUPS: Record<'products' | 'games' | 'tools', string[]> = { ], games: [ 'brain-vat-siege', + 'railforge', + 'project-strata', 'coinrace', 'wishing-stones', 'hoverslam', @@ -207,6 +209,7 @@ export const HOME_GROUPS: Record<'products' | 'games' | 'tools', string[]> = { tools: [ 'devdeck', 'studios', + 'music-mv-studio', 'creator-learning-os', 'citefirst', 'juicebar', From 6f3c198fea64e0d7766da464dd812073cc91af26 Mon Sep 17 00:00:00 2001 From: Si Hyeong Lee Date: Sun, 11 Oct 2026 21:53:05 -0700 Subject: [PATCH 06/10] perf(portfolio): trim ledger payload and document release gates --- .../2026-10-11-live-site-refresh-audit.md | 29 +++++++++++++++++ .../2026-10-11-next-braces-dependency-gate.md | 31 +++++++++++++++++++ scripts/qa-portfolio.mts | 8 +++++ src/app/[locale]/LedgerHome.tsx | 2 +- src/app/[locale]/projects/page.tsx | 4 +-- src/components/projects/ProjectCard.tsx | 6 ++-- src/lib/__tests__/projects.test.ts | 13 ++++++++ src/lib/projects.ts | 10 ++++++ 8 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 docs/reviews/2026-10-11-next-braces-dependency-gate.md diff --git a/docs/reviews/2026-10-11-live-site-refresh-audit.md b/docs/reviews/2026-10-11-live-site-refresh-audit.md index 8e7cd9d..3897ad6 100644 --- a/docs/reviews/2026-10-11-live-site-refresh-audit.md +++ b/docs/reviews/2026-10-11-live-site-refresh-audit.md @@ -94,3 +94,32 @@ Captured actual Chromium screenshots at 2026-10-11 PT, saved under ignored `.qa/ 5. Projects desktop selected-work cards have very dense multi-paragraph copy and stacks of skill tags; Studio card lacks a visible screenshot compared to DevDeck. Propose concise 2–3-line outcomes plus scannable evidence/roles/status, with expandable case-study detail. Do **not** invent production scale, release status, or adoption. No full-page/mobile interaction or physical-device acceptance is asserted by this static viewport review. Browser screenshots were taken from **public Vercel production**; local uncommitted visual changes were not used. + +## Follow-up implementation — 2026-10-11 21:45 PT + +This continued user-approved maintenance pass is staged, **not yet deployed**. Public site remains the earlier Vercel release. + +### Live Plane (confirmed via authenticated REST) +- Read 44 pre-existing FOLIO work items, including FOLIO-34 QA, FOLIO-35 Todo and FOLIO-36 Todo. +- Created FOLIO-45 urgent/In Progress for the strict security audit and Next release, FOLIO-46 high/Todo for source-backed project curation, FOLIO-47 high/Todo for Hiring UX and FOLIO-48 medium/Todo for measured performance/SEO. +- Added source QA/release read-back comments to FOLIO-34 and FOLIO-36. Do not mark release Done before production evidence exists. + +### Source integration +- Preserved the original `portfolio` checkout and all 36 modified/untracked paths. Created a separate `portfolio-reconcile-20261011` Git worktree, branch `feat/reconcile-evidence-20261011`. +- Snapshotted evidence/resume work from WIP and merged current public GitHub main `689354e`. Five content/test conflicts were manually reconciled, preserving the AI/agent engineering identity and the later paid-work-oriented Hire case studies, with remote-first and LA hybrid/on-site eligibility accurately stated. +- The project ledger now has 48 entries after adding **RailForge, Project STRATA, Music / MV Studio** as `building` / `private` research and development; bilingual evidence sections clearly decline a shipped/public claim. Existing selected-work and project release labels were left intact. +- Hero positions early résumé/portfolio/AI-pipeline links within the first viewport while retaining the editorial visual identity. The Hire first viewport has contact email and résumé options. Mobile home navigation targets are given a min-height. Project listing card copy and ProjectList JSON-LD use bounded, non-destructive excerpts; full technical details remain on linked case-study pages. +- Added browser acceptance for visible Hire contact button/anchor in each viewport; added tests for guarded summary behavior and private-prototype classification. +- Integrated security branch `fix/next-security-lockfile-20261011` (Next.js 16.4.0 + compatible transitive patches) into the candidate, so the final release candidate does not regress to the older vulnerable Next.js. + +### Verification (progressively confirmed, do not conflate versions) +- **Before integrating Next.js 16.4.0**, the reconciled Next 16.3.3 branch passed 226 Vitest tests, TypeScript, ESLint, Prettier, evidence/PDF hashes, translations and production build. Chromium QA passed EN/KO × 1440/390 × dark/light, three versioned PDF byte hashes, and both locale navigation suites. Local candidate /en/projects/railforge, /project-strata and /music-mv-studio returned HTTP 200. Real first-viewport desktop and mobile screenshots were reviewed and CTA placement looked correct. All previews stayed loopback-only. +- The fresh Next 16.4.0 build, security audit, updated browser acceptance and production recheck are a **separate** final gate. The upstream `braces` high vulnerability is still unresolved; see `2026-10-11-next-braces-dependency-gate.md`. +## Final localhost candidate QA — 2026-10-11 21:51 PT + +- The isolated candidate merged Next.js 16.4.0 and its compatible dependency patches from draft PR #33. Clean npm installation succeeded. +- Current source: TypeScript, ESLint, Prettier, 228 unit tests (23 suites), evidence/PDF checks and bilingual posts (11/11) PASS. Optimized build PASS (148 prerender tasks). +- Chromium review on Next.js 16.4.0: all eight EN/KO × 1440/390 × light/dark combinations PASS. All three résumé PDFs have valid MIME type and exact expected SHA-256. New prototype case-study links respond HTTP 200; no unexpected browser errors. +- Bounded project excerpts are rendered in catalogue cards and summary JSON-LD; full technical copy stays on detail pages. +- One read-only lab snapshot at `.qa/portfolio/performance-20261011.json`: /en/projects public decoded HTML 509,187 bytes; localhost candidate 484,503 bytes. Public compressed document transfer about 47 KB vs local about 66 KB because origins and compression differ. These are **different content versions and server environments**, not comparable Core Web Vitals, controlled A/B, or proof of deployed speed gains. The lab sampled TTFB/FCP/LCP; tested views had no horizontal overflow. +- STRICT dependency audit still fails on the unpatched braces advisory. PR #33 remains draft, and Vercel production has not been updated. Preserve release gate FOLIO-36. diff --git a/docs/reviews/2026-10-11-next-braces-dependency-gate.md b/docs/reviews/2026-10-11-next-braces-dependency-gate.md new file mode 100644 index 0000000..ad43e0c --- /dev/null +++ b/docs/reviews/2026-10-11-next-braces-dependency-gate.md @@ -0,0 +1,31 @@ +# Remaining dependency security gate — 2026-10-11 (America/Los_Angeles) + +## Status and scope + +The latest compatible maintenance candidate is GitHub draft [PR #33](https://github.com/writingdeveloper/portfolio/pull/33), Next.js **16.4.0** plus synchronized lockfile, `sharp@0.35.5`, `source-map-js@1.2.2`, and `brace-expansion@2.1.7`. GitHub Actions Linux passed `npm ci`, typecheck, lint, format, unit, bilingual parity, hero verification, and build. The only red step is the unchanged strict dependency audit. + +## Outstanding advisory + +[GHSA-vfj7-8cjw-p6xm](https://github.com/advisories/GHSA-vfj7-8cjw-p6xm) concerns malicious/deeply nested brace glob patterns that could exhaust the JS stack. `npm view braces version` reported **3.0.3** on 2026-10-11; no officially patched version was available. `npm audit --omit=dev --audit-level=high` reported 3 High entries from this dependency group; full `npm audit --audit-level=high` reported 7 High. Grouped alerts are **not necessarily seven independently reachable exploit paths**. + +The dependency paths observed in the patched lockfile are: + +- `@keystatic/next@5.0.5 → chokidar@3.6.0 → braces@3.0.3` (CMS/tooling, installed via production package). +- `eslint-config-next@16.4.0 → @next/eslint-plugin-next → fast-glob@3.3.1 → micromatch@4.0.8 → braces@3.0.3` (lint/build tooling). + +The website uses local file-backed content with a configured Keystatic admin UI. Production access guards exist for `/keystatic` and `/api/keystatic` in local storage mode; **this is a route-level observation, not proof that every vulnerable call path is unreachable**. No arbitrary user-submitted glob pattern was identified in portfolio request handlers during this source review; full security threat modeling remains outstanding. + +## Disallowed shortcuts + +- Do **not** use `npm audit fix --force` for this dependency: npm offered `@keystatic/next@0.0.6`, a breaking and incompatible downgrade. +- Do **not** claim `npm audit` passed; it did not. +- Do **not** globally disable audits, blindly omit production dependencies, or publish a fabricated patched version. + +## Remaining path to release + +1. Review advisory against actual input sources and affected internal call sites, including Keystatic import/runtime paths; record threat model and exposure. +2. Seek upstream maintained release or carefully reviewed compatibility-preserving patch/vendor route. Re-run all unit, integration, browser, and clean-CI checks afterward. +3. If no compatible fix becomes available and an earlier release is still required, seek an **explicit, time-limited security risk decision** with reason, scope, mitigation, owner, and expiry. A blanket request for general maintenance is not such acceptance. +4. PR #33 and its stacked portfolio refresh remain draft until gate resolution. Vercel production deployment and public résumé verification are separate FOLIO-36 acceptance. + +Plane: FOLIO-45 (dependency gate), FOLIO-36 (actual release). diff --git a/scripts/qa-portfolio.mts b/scripts/qa-portfolio.mts index e51ccc1..a934d80 100644 --- a/scripts/qa-portfolio.mts +++ b/scripts/qa-portfolio.mts @@ -70,6 +70,14 @@ try { 'Horizontal overflow at ' + route ) if (route === '/hire') { + const contact = page + .getByRole('link', { name: locale === 'ko' ? /이메일로 연락하기/ : /Email me/ }) + .first() + assert(await contact.isVisible(), 'Above-fold contact CTA missing') + const rect = await contact.boundingBox() + assert(rect && rect.y < (width === 390 ? 844 : 1000), 'Contact CTA not visible in initial viewport') + assert(await page.locator('a[href="#resume"]').isVisible(), 'Résumé shortcut missing') + assert((await page.locator('#resume').count()) === 1, 'Résumé anchor missing') const primary = page.locator('a[href="/resume/Sihyeong-Lee-Resume.pdf"]') assert(await primary.isVisible(), 'Primary résumé CTA missing') const colors = await primary.evaluate((el) => ({ diff --git a/src/app/[locale]/LedgerHome.tsx b/src/app/[locale]/LedgerHome.tsx index ceb0eb9..ba3fa09 100644 --- a/src/app/[locale]/LedgerHome.tsx +++ b/src/app/[locale]/LedgerHome.tsx @@ -255,7 +255,7 @@ export function LedgerHome({ diff --git a/src/app/[locale]/projects/page.tsx b/src/app/[locale]/projects/page.tsx index 2200bbf..4c29931 100644 --- a/src/app/[locale]/projects/page.tsx +++ b/src/app/[locale]/projects/page.tsx @@ -7,7 +7,7 @@ import { SITE_URL } from '@/lib/constants' import { ProjectCard } from '@/components/projects/ProjectCard' import { PageTransition } from '@/components/ui/PageTransition' import { generateBreadcrumbJsonLd, generateProjectListJsonLd, safeJsonLd, toAbsoluteUrl } from '@/lib/seo' -import { APP_CATEGORY, partitionProjects } from '@/lib/projects' +import { APP_CATEGORY, partitionProjects, projectExcerpt } from '@/lib/projects' import { getAllPosts } from '@/lib/mdx' import { buildProjectPostMap, type LinkedPost } from '@/lib/post-project-links' import { useLocale } from 'next-intl' @@ -70,7 +70,7 @@ function ProjectsContent({ projectPosts }: { projectPosts: Map ({ name: project.name, - description: locale === 'ko' ? project.descriptionKo : project.descriptionEn, + description: projectExcerpt(locale === 'ko' ? project.descriptionKo : project.descriptionEn), url: project.website ?? (!project.private && project.github ? project.github : undefined), techStack: project.techStack, ...(project.screenshot ? { image: toAbsoluteUrl(project.screenshot) } : {}), diff --git a/src/components/projects/ProjectCard.tsx b/src/components/projects/ProjectCard.tsx index c8d04af..186f641 100644 --- a/src/components/projects/ProjectCard.tsx +++ b/src/components/projects/ProjectCard.tsx @@ -3,7 +3,7 @@ import { useTranslations, useLocale } from 'next-intl' import Image from 'next/image' import type { Project } from '@/types/content' import { predecessorOf } from '@/lib/lineage' -import { projectHref } from '@/lib/projects' +import { projectHref, projectExcerpt } from '@/lib/projects' interface ProjectCardProps { project: Project @@ -101,7 +101,9 @@ export function ProjectCard({ project, priority = false, relatedPost }: ProjectC

{project.descriptionKo && (

- {locale === 'en' ? project.descriptionEn || project.descriptionKo : project.descriptionKo} + {projectExcerpt( + locale === 'en' ? project.descriptionEn || project.descriptionKo : project.descriptionKo + )}

)}
diff --git a/src/lib/__tests__/projects.test.ts b/src/lib/__tests__/projects.test.ts index be0bea5..525d880 100644 --- a/src/lib/__tests__/projects.test.ts +++ b/src/lib/__tests__/projects.test.ts @@ -3,6 +3,7 @@ import { getHireStats, getPortfolioStats, getProjectCaseStudySections, + projectExcerpt, hasIndexablePage, HIRE_CASE_STUDIES, HOME_GROUPS, @@ -25,6 +26,18 @@ const p = (name: string, featured: boolean): Project => ({ featured, }) +describe('projectExcerpt', () => { + it('preserves concise text unchanged and trims whitespace', () => { + expect(projectExcerpt(' hello world ')).toBe('hello world') + }) + it('shortens long descriptions without removing the detail page copy', () => { + const text = 'Accessible evidence for a shipped product. '.repeat(20) + const excerpt = projectExcerpt(text, 110) + expect(excerpt.length).toBeLessThanOrEqual(111) + expect(excerpt.endsWith('…')).toBe(true) + }) +}) + describe('sortProjectsFeaturedFirst', () => { it('places featured projects before non-featured', () => { const out = sortProjectsFeaturedFirst([p('A', false), p('B', true), p('C', false), p('D', true)]) diff --git a/src/lib/projects.ts b/src/lib/projects.ts index 52b1cd7..c249b2c 100644 --- a/src/lib/projects.ts +++ b/src/lib/projects.ts @@ -1,5 +1,15 @@ import type { Project } from '@/types/content' +/** Concise catalogue copy; full detail remains on project-specific pages. */ +export function projectExcerpt(description: string, maxLength = 220): string { + const text = description.trim().replace(/\s+/g, ' ') + if (text.length <= maxLength) return text + const limit = text.slice(0, maxLength) + const boundary = limit.lastIndexOf(' ') + const cut = boundary >= maxLength * 0.6 ? boundary : maxLength + return limit.slice(0, cut).trimEnd() + '…' +} + export const SELECTED_WORK = ['devdeck', 'studios', 'citefirst', 'brain-vat-siege', 'healframe'] as const export type ProjectCaseStudyKey = 'problem' | 'decision' | 'evidence' | 'result' From 29b8919f0039c2f4ed23854def4e06d558b4f110 Mon Sep 17 00:00:00 2001 From: Si Hyeong Lee Date: Mon, 12 Oct 2026 01:52:16 -0700 Subject: [PATCH 07/10] feat(portfolio): lead with verifiable engineering outcomes over AI tool use --- ...26-10-12-ai-commoditization-positioning.md | 48 ++++++++++ .../reviews/2026-10-12-ai-era-portfolio-qa.md | 34 +++++++ messages/en.json | 45 ++++++--- messages/ko.json | 45 ++++++--- scripts/qa-portfolio.mts | 13 +++ src/app/[locale]/LedgerHome.tsx | 23 +++-- src/app/[locale]/hire/page.tsx | 36 ++++++++ .../projects/EvidenceSnapshotStrip.tsx | 92 +++++++++++++++++++ .../__tests__/ai-differentiation-2026.test.ts | 63 +++++++++++++ .../__tests__/employment-positioning.test.ts | 2 +- 10 files changed, 367 insertions(+), 34 deletions(-) create mode 100644 docs/research/2026-10-12-ai-commoditization-positioning.md create mode 100644 docs/reviews/2026-10-12-ai-era-portfolio-qa.md create mode 100644 src/components/projects/EvidenceSnapshotStrip.tsx create mode 100644 src/lib/__tests__/ai-differentiation-2026.test.ts diff --git a/docs/research/2026-10-12-ai-commoditization-positioning.md b/docs/research/2026-10-12-ai-commoditization-positioning.md new file mode 100644 index 0000000..36af205 --- /dev/null +++ b/docs/research/2026-10-12-ai-commoditization-positioning.md @@ -0,0 +1,48 @@ +# AI adoption is not the differentiator — portfolio positioning review + +Reviewed: 2026-10-12 (America/Los_Angeles) +Execution: Plane FOLIO-35/46/47, source branch `feat/reconcile-evidence-20261011` +Status: editorial and source-work review; not proof of public deployment, hiring outcomes, customer adoption, or independently measured business impact. + +## Premise + +Using a coding assistant, agent, MCP server, or model is no longer a distinguishing résumé headline. The harder questions a hiring manager or customer can evaluate are: what production or workflow problem was solved; what constraints were chosen; how correctness and failure paths were measured; who accepts release risk; and whether the stated outcome can be independently inspected. + +### External context, with sampling limits + +- Stack Overflow Developer Survey 2026, [AI overview](https://survey.stackoverflow.co/2026/ai): 73% of the survey's respondents were reported as daily AI users; coding assistants and agents were widely reported. The survey is self-selected, not a census of all engineers or an individual employment-market ranking. +- The survey's [trust question](https://survey.stackoverflow.co/2026/ai/data/ai-trust) (`n=14,304`) reports that **48.0%** trust AI when output is easy to verify, while **6.6%** trust it for many tasks *including important work decisions*. Do not paraphrase this as “everyone distrusts AI” or “93% distrust code.” +- Its [knowledge / attribution section](https://survey.stackoverflow.co/2026/knowledge) reports that 93% considered information sourcing at least somewhat important to confidence in AI-generated answers. Attribution is a survey finding, not measured effectiveness of this portfolio. +- The [2025 DORA State of AI-Assisted Software Development](https://dora.dev/research/2025/dora-report/) describes AI as an amplifier of an organization's existing strengths and weaknesses. It does not prove a specific developer's value. +- OpenAI's [Harness engineering](https://openai.com/index/harness-engineering/) (2026-02-11) describes a team in which human engineers shape intent, environments and feedback loops while agents write code. That is an example of a workflow model; it does not imply this site's author achieved its timing, scale or release metrics. + +Editorial decision: **put proof and reasoning before tool names**. No percentage from these external surveys is necessary on the public site; publish concrete project evidence instead. + +## Three portfolio stories with different evidence quality + +| Case study | Engineering judgment to show | Verifiable record and its limit | What not to claim | +| --- | --- | --- | --- | +| DevDeck | Ownership of state across coding agents, restart/reconnect recovery and conflict handling | `content/evidence.json` pins candidate **1.37.8** review: 1,289 passed, 1 skipped. Source commit and hash are recorded; not an installed release or current live test. | “1,289 tests passed today”, deployed reliability over months, enterprise adoption | +| citefirst | Retrieval evaluation rather than general AI/RAG enthusiasm | A committed **46-question** PostgreSQL 17 manual evaluation: recall@5 **0.978**, MRR@10 **0.834**. Search quality, *not answer correctness*. | Confusing private uncommitted 56-question experiment or valid citation IDs with factual-answer accuracy | +| Creator OS | Separating implementation/build success from release readiness: backups, data boundaries, OAuth/policy/operator gates | Project case study and source review describe a private-staging release with explicit unsatisfied external gates. Numbers on other source trees require their own dated evidence approval. | Public commercial launch, external customers, revenue, universal production-readiness guarantee | + +Studio / MingleStage / RailForge / STRATA / Music-MV show breadth of exploration. Label them as private, pilot, technical spike or development—not as business outcomes. A project count is an inventory count, not proof of quality or customer value. + +## Copy and UX contract + +1. Keep the distinctive `I build. I ship. I bury the dead.` identity. Under it, say how engineering output is accepted, not how many AI models are used. +2. Home: display two source-pinned evidence snapshots with dates, scope and limitations, plus direct project and immutable source links. The `PUBLIC LINKS` count should not imply commercial launch or active users. +3. Hire: lead with the customer's current workflow or problem, not “AI expert.” Show **problem definition → verification → release or deliberate stop**. Link each stage to an inspectable example and keep full-time vs paid project offers separate. +4. Ledger: public work, private experiments and active prototypes remain distinct. Descriptions and search metadata must not claim every build has a public URL. All case studies should contain problem, decision, evidence and result; missing evidence should remain explicitly unresolved. +5. Source honesty: a green source test is not a production release; skipped tests are not successes; a private staging screenshot is not public availability. Site credibility falls if any of these boundaries disappear. + +## Acceptance tests + +- EN/KO translation keys remain consistent; first-screen CTA, explicit evidence scope, real internal and Git commit links are tested in the existing browser matrix. +- New regression tests pin the three examples and guard against blanket public-release claims. +- Production build, type check, lint, unit, evidence checksum and browser tests must pass *on the final branch*. +- An unresolved dependency audit, privacy/authoritative résumé approval, and actual Vercel deployment remain **separate release gates**. PR #33 and PR #34 are draft until those are resolved and do not create an implied approval. + +## Follow-up research / measurable improvements + +Review target-job descriptions by actual employer/contract scope before declaring a globally optimal job title. Add a verifiable test artifact for one client-shaped workflow: a failure case, recovery proof, versioned test run, and concrete user-facing acceptance, rather than adding another model badge. Record a 2026-12-22 positioning review in FOLIO-35; do not claim it is an automatic reminder. diff --git a/docs/reviews/2026-10-12-ai-era-portfolio-qa.md b/docs/reviews/2026-10-12-ai-era-portfolio-qa.md new file mode 100644 index 0000000..0d5cb59 --- /dev/null +++ b/docs/reviews/2026-10-12-ai-era-portfolio-qa.md @@ -0,0 +1,34 @@ +# AI-era portfolio positioning and browser acceptance — 2026-10-12 PT + +Branch: `feat/reconcile-evidence-20261011` (stacked draft PR #34 over blocked security PR #33) +Host/source: MAIN 4080, separate worktree `portfolio-reconcile-20261011` +Status: candidate source verified locally; public release remains **blocked** + +## Goal + +AI-tool usage is common among software engineers. Demonstrate human engineering responsibility and verifiable outcomes rather than presenting Claude, Codex, model counts or generation volume as unique value. Source research and limitations: [2026-10-12-ai-commoditization-positioning.md](../research/2026-10-12-ai-commoditization-positioning.md). + +## Implementation + +- Home hero paragraph uses the same translated source as SEO messaging and explicitly distinguishes AI-assisted code from acceptance criteria, failures and release safety. The original ledger branding is preserved. +- Home `#verified-work` contains both snapshots from `content/evidence.json` (DevDeck candidate and citefirst committed retrieval evaluation) with source timestamps, scope, unverified conditions, project links and pinned Git commit links. Metrics were **not changed** by this update. +- The ledger's `PUBLIC LINKS` label counts public destinations without claiming that these are commercial launches; the page clarifies that builds include unfinished prototypes, not customers or revenue. +- The Hire `#delivery-method` section shows **frame problem → verify outcome → ship or block**, each with a concrete project-case link: DevDeck, citefirst and Creator OS. Copy avoids implying that code generated by an agent is itself a production outcome. +- EN/KO metadata and visible projects catalogue descriptions distinguish public links from private or unfinished work and eliminate earlier blanket demo-link claims. +- Added five regression tests and browser assertions that validate render presence, proof count/source pins, source limitations, and the three linked case studies. + +## Local check read-back + +- TypeScript, ESLint, Prettier: PASS. +- Vitest: **233 passing tests / 24 files** (compared with 228 before this change). +- Source evidence structure and all versioned résumé PDF hashes: PASS. +- Bilingual posts: **11/11 pairs**, no unmatched translations. +- Next.js 16.4.0 production build: PASS; **148 prerendered static-generation tasks**. +- Browser source build on localhost-only port 3193: EN/KO × desktop 1440px/mobile 390px × dark/light, **8/8 PASS**, with no unexpected console/page/network errors. Dated résumé PDFs: 3/3 MIME and SHA-256 PASS. EN and KO navigation suites both PASS. +- Captured EN/KO desktop/mobile screenshots of `#verified-work` and `#delivery-method` under ignored `.qa/portfolio/ai-evidence-20261012/`. Screenshot review: legible two-column proof on desktop and stacked proof/method cards on mobile, no measured horizontal overflow. A sticky header can overlay an element screenshot during automatic element-scroll; the method section now has a scroll-margin offset. This is not physical-device/human launch acceptance. + +## Open gates + +- `npm audit --audit-level=high`: **nonzero**, seven High findings due to upstream unpatched `braces` dependency paths. `npm view braces version` on 2026-10-12 returned **3.0.3**; not a fix. No unsafe `--force` downgrade, blanket audit bypass, or acceptance of residual risk was applied. +- The original 4080 portfolio worktree has been left untouched. Vercel public `writingdeveloper.blog` still serves its prior release; public résumé PDF path remains a known 404 until FOLIO-36 has a reviewed merge, deployment and live hash/MIME/link verification. +- Pinned metrics have historical scope, and curated project's commercial outcomes remain **unmeasured**. Editorial review, external hiring-market validation, security remediation and production release are separate decisions. diff --git a/messages/en.json b/messages/en.json index 49d4e85..e0a5160 100644 --- a/messages/en.json +++ b/messages/en.json @@ -1,7 +1,7 @@ { "metadata": { "title": "WritingDeveloper", - "description": "Build logs and engineering notes from Sihyeong Lee — an AI-native product engineer building agent systems, evals, developer tools, and production full-stack products." + "description": "Engineering notes and source-backed case studies on browser automation, evaluated retrieval, agent tooling, and production release decisions by Sihyeong Lee." }, "nav": { "home": "Home", @@ -17,14 +17,14 @@ "greeting": "Hello", "name": "Sihyeong Lee", "role": "AI-Native Product & Agent Systems Engineer", - "description": "I build production AI systems, developer tools, and full-stack products — with agent workflows, evals, and infrastructure designed for reliability." + "description": "AI-assisted code is a starting point. I define acceptance criteria, test real workflows, investigate failure modes, and distinguish successful builds from safe releases." }, "latestPosts": "Latest Posts", "viewAll": "View All", "featuredProjects": "Projects", "noPosts": "No posts yet.", "explore": "Explore my world", - "metaDescription": "Sihyeong Lee — AI-native product and agent-systems engineer in Los Angeles. Agent tooling, MCP, evals, RAG, local GPU infrastructure, and production full-stack systems." + "metaDescription": "Sihyeong Lee — AI-native product and agent-systems engineer in Los Angeles. Source-backed automation, measured retrieval, recovery design, and accountable software delivery." }, "blog": { "title": "Blog", @@ -54,9 +54,9 @@ }, "projects": { "title": "Projects", - "description": "Things I'm building", + "description": "A documented ledger of released software, active prototypes, and unfinished experiments", "metaTitle": "{count} Projects — Web, Games, Dev Tools", - "metaDescription": "{count} projects built solo by Sihyeong Lee — SaaS, developer tools, games and AI experiments, each with a live demo or store link.", + "metaDescription": "{count} documented software projects, from public products to private prototypes. Live demos, source links and measured claims are shown only where available.", "viewProject": "View Project", "viewShowcase": "See the work", "viewCode": "View Code", @@ -75,9 +75,9 @@ "archived": "Archived" }, "selectedWork": "Selected Work", - "selectedWorkDescription": "Five projects selected to show agent tooling, AI infrastructure, measured RAG, safety-gated AI product engineering, and production full-stack ownership.", + "selectedWorkDescription": "Engineering decisions and verifiable evidence across developer tooling, measured retrieval, recovery, and production release gates.", "fullLedger": "Full Ledger", - "fullLedgerDescription": "The rest of the record, including work that is still being built.", + "fullLedgerDescription": "Research, prototypes, and private work are included. A build count is not a release or customer count.", "caseStudy": { "heading": "How it was solved", "problem": "Problem", @@ -112,7 +112,7 @@ }, "about": { "title": "About", - "description": "AI-native product and agent-systems engineering, from architecture and evals to production operations", + "description": "Engineering judgment across architecture, evaluation, failure recovery, and release decisions", "metaTitle": "About — AI-Native Product & Agent Systems Engineer", "metaDescription": "Sihyeong Lee — AI-native product and agent-systems engineer and former CTO in Los Angeles. Agent tooling, MCP, evals, applied AI, full-stack systems, and production infrastructure.", "body": "I am an AI-native product engineer and former CTO who builds the systems around modern models, not just prompts: agent workflows, MCP/tool integrations, evaluation harnesses, retrieval systems, developer tooling, and the full-stack infrastructure that carries them into production. I use coding agents heavily as execution leverage while retaining ownership of architecture, acceptance criteria, code review, testing, debugging, deployment, and release decisions. Recent work includes DevDeck, a command center for coding agents; studios, a multi-modal MCP/GPU platform with persisted verification; citefirst, a measured RAG system; and production SaaS work with explicit safety and release gates.", @@ -121,9 +121,9 @@ }, "hire": { "title": "Work with me", - "description": "Senior product and full-stack engineer for browser automation, AI integration, and production release work — open to full-time roles and focused projects.", + "description": "AI is part of the toolchain, not the result. I build browser automations, production integrations, and release-ready systems with verifiable acceptance criteria.", "metaTitle": "Sihyeong Lee — Browser Automation, AI Integration & Senior Full-Stack", - "metaDescription": "Los Angeles senior software engineer for Playwright/browser automation, AI integration, production Next.js/PostgreSQL systems, and release QA. {shipped} shipped products with a public demo or store listing.", + "metaDescription": "Los Angeles senior software engineer for browser automation, testable AI integration, and production release QA. {shipped} projects with a public demo or store listing; verification scope is explicit.", "badgeRemote": "Los Angeles · Remote-first · LA hybrid/on-site · US permanent resident", "badgeNow": "Available now", "fulltime": { @@ -133,12 +133,12 @@ "modeLabel": "Working style", "mode": "Remote-first (US, Pacific Time) · open to LA hybrid/on-site · US permanent resident — no sponsorship required", "bringLabel": "What I bring", - "bring": "Nearly five years owning engineering as a CTO across two companies, plus hands-on work in Playwright automation, AI-enabled products, PostgreSQL/Docker production systems, CI/release gates, RAG, and local GPU infrastructure." + "bring": "Nearly five years owning engineering as a CTO across two companies. I define technical constraints, review AI-assisted implementations, test failure and recovery paths, and separate working code from launch approval." }, "contract": { "heading": "Focused engineering projects", "workLabel": "Problems I solve", - "work": "Playwright/browser automation · AI integration into existing products · Next.js/PostgreSQL release & QA rescue", + "work": "Resilient Playwright/browser workflows · AI integration with measurable evals and human review · production release gates, recovery, and QA", "modeLabel": "Shape", "mode": "Remote-first. Small paid diagnostics and implementation sprints measured in days, with clear acceptance criteria and evidence.", "startLabel": "How to start", @@ -146,7 +146,7 @@ }, "evidence": { "heading": "Evidence", - "shipped": "products with a public demo or store listing", + "shipped": "projects with a public demo or store link (not necessarily a commercial launch)", "playStore": "apps on Google Play", "total": "builds in the ledger", "caseHeading": "Relevant case studies" @@ -178,6 +178,25 @@ "title": "Case Farms · Quality Assurance · 2023–2024", "body": "U.S. manufacturing-floor role; moved from production into quality assurance after five months." } + }, + "approach": { + "heading": "Beyond the AI-generated demo", + "intro": "AI can accelerate implementation. The differentiator is what survives a failure, a review, and the decision to deploy. Here is how I frame the engineering work, with actual examples below.", + "decision": { + "title": "Frame the real problem", + "body": "Start with workflows, constraints, state ownership, and failure cases. A model or tool is an implementation choice, not a requirements document.", + "link": "DevDeck: state & recovery" + }, + "verification": { + "title": "Verify the outcome", + "body": "Use dated, source-linked test runs and explicit denominators. Passing retrieval metrics are not the same as correct generated answers.", + "link": "citefirst: measured retrieval" + }, + "release": { + "title": "Ship — or deliberately block", + "body": "A successful build does not clear external OAuth, backups, operator decisions, or production rollout. Keep unverified gates visibly open.", + "link": "Creator OS: release gates" + } } }, "studio": { diff --git a/messages/ko.json b/messages/ko.json index 3dc0903..02612d9 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -1,7 +1,7 @@ { "metadata": { "title": "WritingDeveloper", - "description": "이시형의 빌드 로그와 엔지니어링 기록 — 에이전트 시스템·평가·개발자 도구·프로덕션 풀스택 제품을 만드는 AI 네이티브 제품 엔지니어." + "description": "브라우저 자동화, 검색 평가, 에이전트 도구, 프로덕션 출시 판단을 원본 근거와 함께 기록하는 이시형의 엔지니어링 포트폴리오." }, "nav": { "home": "홈", @@ -17,14 +17,14 @@ "greeting": "안녕하세요", "name": "이시형", "role": "AI 네이티브 제품 · 에이전트 시스템 엔지니어", - "description": "에이전트 워크플로·평가·신뢰성 인프라를 포함한 프로덕션 AI 시스템, 개발자 도구, 풀스택 제품을 만듭니다." + "description": "AI가 코드를 만드는 것은 출발점입니다. 완료 기준을 정의하고, 실제 사용 흐름과 실패 상황을 검증하며, 빌드 성공과 안전한 출시를 구분합니다." }, "latestPosts": "최근 글", "viewAll": "모두 보기", "featuredProjects": "프로젝트", "noPosts": "글이 없습니다.", "explore": "내 세계를 탐험하기", - "metaDescription": "로스앤젤레스의 AI 네이티브 제품·에이전트 시스템 엔지니어 이시형. 에이전트 도구, MCP, eval, RAG, 로컬 GPU 인프라, 프로덕션 풀스택 시스템을 구축합니다." + "metaDescription": "로스앤젤레스의 AI 네이티브 제품·에이전트 시스템 엔지니어 이시형. 검증 가능한 자동화, 측정된 검색 품질, 장애 복구와 출시 책임을 사례로 설명합니다." }, "blog": { "title": "블로그", @@ -54,9 +54,9 @@ }, "projects": { "title": "프로젝트", - "description": "만들고 있는 것들", + "description": "출시한 소프트웨어부터 개발 중인 시제품·비공개 실험까지 기록합니다", "metaTitle": "프로젝트 {count}개 · 웹·앱·게임·개발자 도구", - "metaDescription": "이시형이 직접 만든 프로젝트 {count}개. SaaS와 개발자 도구, 게임, AI 실험까지 라이브 데모·스토어 링크와 함께 정리했습니다.", + "metaDescription": "공개 제품, 연구용 프로토타입, 비공개 실험을 포함한 소프트웨어 프로젝트 {count}개의 기록. 실제 공개 가능한 데모·소스와 검증 근거만 연결합니다.", "viewProject": "프로젝트 보기", "viewShowcase": "결과물 보기", "viewCode": "코드 보기", @@ -75,9 +75,9 @@ "archived": "보관됨" }, "selectedWork": "대표 작업", - "selectedWorkDescription": "에이전트 도구, AI 인프라, 측정 가능한 RAG, 안전 게이트가 있는 AI 제품, 프로덕션 풀스택 소유권을 보여주는 다섯 프로젝트입니다.", + "selectedWorkDescription": "개발자 도구, 검색 품질 평가, 장애 복구와 출시 게이트에 대한 엔지니어링 결정 및 검증 근거를 소개합니다.", "fullLedger": "전체 원장", - "fullLedgerDescription": "진행 중인 것까지 포함한 나머지 프로젝트 기록입니다.", + "fullLedgerDescription": "연구·시제품·비공개 작업도 포함됩니다. 제작 수가 출시 수나 고객 수를 의미하지는 않습니다.", "caseStudy": { "heading": "어떻게 풀었는가", "problem": "문제", @@ -112,7 +112,7 @@ }, "about": { "title": "소개", - "description": "아키텍처·평가부터 프로덕션 운영까지 책임지는 AI 네이티브 제품·에이전트 시스템 엔지니어링", + "description": "아키텍처·평가·장애 복구·출시 결정에서 드러나는 엔지니어링 판단", "metaTitle": "소개 — AI 네이티브 제품 · 에이전트 시스템 엔지니어", "metaDescription": "로스앤젤레스의 AI 네이티브 제품·에이전트 시스템 엔지니어이자 전 CTO 이시형. 에이전트 도구, MCP, eval, Applied AI, 풀스택 시스템, 프로덕션 인프라.", "body": "저는 최신 모델 자체보다 그 모델이 실제 일을 하게 만드는 주변 시스템까지 만드는 AI 네이티브 제품 엔지니어이자 전 CTO입니다. 에이전트 워크플로, MCP·툴 연동, 평가 하니스, 검색 시스템, 개발자 도구, 그리고 이를 프로덕션까지 운반하는 풀스택 인프라를 직접 다룹니다. 코딩 에이전트를 적극적으로 실행 레버리지로 사용하지만 아키텍처, 수용 기준, 코드 리뷰, 테스트, 디버깅, 배포, 릴리스 결정은 제가 책임집니다.", @@ -121,9 +121,9 @@ }, "hire": { "title": "함께 일하기", - "description": "브라우저 자동화·기존 제품 AI 통합·프로덕션 릴리스 문제를 해결하는 시니어 제품/풀스택 엔지니어입니다. 정규직과 집중형 프로젝트 모두 가능합니다.", + "description": "AI 사용 자체가 성과는 아닙니다. 검증 가능한 완료 기준을 갖춘 브라우저 자동화, 프로덕션 연동, 출시 품질 문제를 해결합니다.", "metaTitle": "이시형 — 브라우저 자동화 · AI 통합 · 시니어 풀스택", - "metaDescription": "로스앤젤레스의 시니어 소프트웨어 엔지니어. Playwright/브라우저 자동화, 기존 제품 AI 통합, Next.js/PostgreSQL 프로덕션 시스템과 릴리스 QA를 수행합니다. 공개 데모·스토어가 있는 제품 {shipped}건.", + "metaDescription": "로스앤젤레스의 시니어 소프트웨어 엔지니어. 브라우저 자동화, 검증 가능한 AI 통합, 프로덕션 출시 QA를 다룹니다. 공개 데모·스토어 링크가 있는 프로젝트 {shipped}건을 구분해 소개합니다.", "badgeRemote": "로스앤젤레스 · 원격 우선 · LA 하이브리드/출근 가능 · 미국 영주권자", "badgeNow": "지금 바로 시작 가능", "fulltime": { @@ -133,12 +133,12 @@ "modeLabel": "근무 형태", "mode": "원격 우선(미국, 태평양 시간) · LA 하이브리드/출근 가능 · 영주권자(취업 스폰서 불필요)", "bringLabel": "가져오는 것", - "bring": "두 회사에서 5년 가까이 엔지니어링을 책임진 CTO 경험과 Playwright 자동화, AI 제품, PostgreSQL/Docker 프로덕션 시스템, CI/릴리스 게이트, RAG, 로컬 GPU 인프라를 직접 구축한 최근 경험." + "bring": "두 회사에서 5년 가까이 엔지니어링을 책임진 CTO 경험이 있습니다. 기술적 제약과 완료 기준을 정하고, AI 보조 구현물을 검토하며, 장애·복구를 검증하고 코드 완성과 실제 출시 승인을 구분합니다." }, "contract": { "heading": "집중형 엔지니어링 프로젝트", "workLabel": "해결하는 문제", - "work": "Playwright/브라우저 자동화 · 기존 제품 AI 통합 · Next.js/PostgreSQL 릴리스·QA 구조화", + "work": "장애에 강한 Playwright/브라우저 자동화 · 평가·사람 검수가 포함된 AI 통합 · 프로덕션 출시 게이트·복구·QA", "modeLabel": "규모 · 기간", "mode": "원격 우선. 완료 기준과 증거가 명확한 유료 진단·구현 스프린트를 일 단위로 진행합니다.", "startLabel": "시작하는 법", @@ -146,7 +146,7 @@ }, "evidence": { "heading": "증거", - "shipped": "공개 데모·스토어가 있는 제품", + "shipped": "공개 데모·스토어 링크가 있는 프로젝트(상용 출시와 별개)", "playStore": "Play Store 앱", "total": "총 빌드", "caseHeading": "관련 사례" @@ -178,6 +178,25 @@ "title": "Case Farms · Quality Assurance · 2023–2024", "body": "미국 제조 현장 근무. 생산라인에서 시작해 5개월 뒤 품질보증으로 이동." } + }, + "approach": { + "heading": "AI 데모를 넘어, 검증 가능한 소프트웨어", + "intro": "AI가 구현을 빠르게 해줘도 장애 대응과 배포 판단을 대신 책임지지는 않습니다. 실제 사례에 연결해 제가 문제를 정의하고 검증하는 방식을 설명합니다.", + "decision": { + "title": "문제와 실패 조건 정의", + "body": "실제 작업 흐름, 제약, 상태의 소유권과 실패 조건을 먼저 정합니다. 모델·도구 선택은 요구사항의 대체물이 아닙니다.", + "link": "DevDeck: 상태·복구 설계" + }, + "verification": { + "title": "결과를 측정하고 검증", + "body": "실행 날짜·원본 소스·평가 문항 수가 고정된 증거를 사용합니다. 검색 지표 통과가 생성 답변의 정확성을 보장하지는 않습니다.", + "link": "citefirst: 검색 평가" + }, + "release": { + "title": "출시하거나, 근거가 없으면 차단", + "body": "빌드 성공만으로 OAuth·백업·운영 판단·실서비스 배포가 검증되지는 않습니다. 미완료 게이트를 명확하게 남깁니다.", + "link": "Creator OS: 출시 게이트" + } } }, "studio": { diff --git a/scripts/qa-portfolio.mts b/scripts/qa-portfolio.mts index a934d80..2b38a0e 100644 --- a/scripts/qa-portfolio.mts +++ b/scripts/qa-portfolio.mts @@ -78,6 +78,12 @@ try { assert(rect && rect.y < (width === 390 ? 844 : 1000), 'Contact CTA not visible in initial viewport') assert(await page.locator('a[href="#resume"]').isVisible(), 'Résumé shortcut missing') assert((await page.locator('#resume').count()) === 1, 'Résumé anchor missing') + const approach = page.locator('#delivery-method') + assert(await approach.isVisible(), 'Evidence-led delivery method missing') + assert( + (await approach.locator('a[href*="/projects/"]').count()) === 3, + 'Delivery examples must link three real case studies' + ) const primary = page.locator('a[href="/resume/Sihyeong-Lee-Resume.pdf"]') assert(await primary.isVisible(), 'Primary résumé CTA missing') const colors = await primary.evaluate((el) => ({ @@ -102,6 +108,13 @@ try { 'AI skill category missing' ) if (!route) { + const proof = page.locator('#verified-work') + assert(await proof.isVisible(), 'Source-pinned proof section missing') + assert((await proof.locator('article').count()) === 2, 'Expected both pinned evidence records') + assert( + (await proof.locator('a[href*="/blob/"]').count()) === 2, + 'Evidence links must resolve to pinned Git commits' + ) const link = page.locator('a[href="' + prefix + '/projects/studios"]').first() assert((await link.count()) === 1, 'Private studios card has no case-study link') await link.click() diff --git a/src/app/[locale]/LedgerHome.tsx b/src/app/[locale]/LedgerHome.tsx index ba3fa09..1b8a9b0 100644 --- a/src/app/[locale]/LedgerHome.tsx +++ b/src/app/[locale]/LedgerHome.tsx @@ -3,6 +3,7 @@ import Image from 'next/image' import { useTranslations } from 'next-intl' import { Link } from '@/i18n/navigation' import { PRIMARY_NAV_ITEMS } from '@/components/layout/navigation' +import { EvidenceSnapshotStrip } from '@/components/projects/EvidenceSnapshotStrip' import type { Project, Tombstone } from '@/types/content' import type { PostMeta } from '@/lib/mdx' import { predecessorOf } from '@/lib/lineage' @@ -204,6 +205,7 @@ export function LedgerHome({ Boolean(project) ) const tNav = useTranslations('nav') + const tHome = useTranslations('home') const portfolioStats = getPortfolioStats(projects) const groups = (Object.keys(HOME_GROUPS) as Array).map((key) => { @@ -213,7 +215,7 @@ export function LedgerHome({ const stats = [ { n: String(portfolioStats.builds).padStart(2, '0'), label: 'BUILDS', hot: true }, - { n: String(portfolioStats.public).padStart(2, '0'), label: 'LIVE', hot: false }, + { n: String(portfolioStats.public).padStart(2, '0'), label: 'PUBLIC LINKS', hot: false }, { n: String(portfolioStats.playStore).padStart(2, '0'), label: 'ON PLAY', hot: false }, { n: String(portfolioStats.featured).padStart(2, '0'), label: 'FEATURED', hot: false }, ] @@ -300,9 +302,7 @@ export function LedgerHome({

- {locale === 'ko' - ? `에이전트가 실제 시스템에서 일하도록 만드는 AI 네이티브 제품을 설계·배포·운영합니다. MCP·툴 사용, eval, RAG, 로컬 GPU 파이프라인, 프로덕션 풀스택 인프라까지 직접 책임집니다.` - : `I build the systems that let AI agents do real work: MCP and tool use, evals, RAG, developer tooling, local GPU pipelines, and production full-stack infrastructure.`} + {tHome('hero.description')}

+

+ {locale === 'ko' + ? '전체 제작 수에는 개발 중인 시제품도 포함됩니다. 공개 링크 수는 상용 출시·실사용자·매출을 의미하지 않습니다.' + : 'Builds include unfinished prototypes. Public destinations do not establish a commercial launch, active users, or revenue.'} +

+ + {/* Evidence is pinned to reviewed commits; project counts also include prototypes. */} + + {/* Featured */}
- +
{groups.map(({ key, items }) => (
@@ -404,7 +413,7 @@ export function LedgerHome({ {/* Graveyard teaser */}
+
+

+ {t('approach.heading')} +

+

{t('approach.intro')}

+
+ {DELIVERY_STAGES.map((stage, index) => ( +
+ 0{index + 1} +

+ {t(`approach.${stage.key}.title`)} +

+

+ {t(`approach.${stage.key}.body`)} +

+ + {t(`approach.${stage.key}.link`)} → + +
+ ))} +
+
+ {/* Counts are a secondary inventory, not proof of quality. */} diff --git a/src/components/projects/EvidenceSnapshotStrip.tsx b/src/components/projects/EvidenceSnapshotStrip.tsx new file mode 100644 index 0000000..5c7bab0 --- /dev/null +++ b/src/components/projects/EvidenceSnapshotStrip.tsx @@ -0,0 +1,92 @@ +import { Link } from '@/i18n/navigation' +import evidence from '../../../content/evidence.json' +import { evidenceUrl } from '@/lib/evidence-policy' + +/** + * Public claims are read from the exact reviewed manifest used by /hire. + * Never copy a passing-test figure into free-form copy or imply a live release. + */ +export function EvidenceSnapshotStrip({ locale }: { locale: string }) { + const ko = locale === 'ko' + + return ( +
+
+
+ + {ko ? '§01 · 근거가 남는 작업' : '§01 · PROOF OVER PROMPTS'} + +

+ {ko ? 'AI 사용보다 검증 가능한 결과' : 'What survives verification'} +

+

+ {ko + ? '생성한 코드의 양이 아니라, 고정된 소스·측정 조건·검증하지 못한 범위를 함께 공개합니다.' + : 'Not how much code an AI helped produce. Each record has a source commit, dated measurement, and explicit limits.'} +

+
+ + {ko ? '근거의 범위 확인' : 'Review the evidence scope'} → + +
+
+ {evidence.records.map((record) => ( +
+
+ + {record.project} + + +
+

+ {ko ? record.titleKo : record.titleEn} +

+

+ {record.value} +

+

+ {ko ? record.scopeKo : record.scopeEn} +

+
+ + {ko ? '문제·결정·결과' : 'Problem, decision, result'} → + + + {ko ? '고정된 원본' : 'Pinned source'} ↗ + +
+
+ ))} +
+
+ ) +} diff --git a/src/lib/__tests__/ai-differentiation-2026.test.ts b/src/lib/__tests__/ai-differentiation-2026.test.ts new file mode 100644 index 0000000..c680302 --- /dev/null +++ b/src/lib/__tests__/ai-differentiation-2026.test.ts @@ -0,0 +1,63 @@ +import { readFileSync } from 'node:fs' +import { join } from 'node:path' +import { describe, expect, it } from 'vitest' +import en from '../../../messages/en.json' +import ko from '../../../messages/ko.json' +import projectsData from '../../../content/projects.json' +import evidence from '../../../content/evidence.json' + +const source = (filename: string) => readFileSync(join(process.cwd(), filename), 'utf8') + +describe('2026 portfolio: distinguish judgment and evidence from AI tool adoption', () => { + it('explains acceptance and failure ownership in both language variants', () => { + expect(en.home.hero.description).toContain('acceptance criteria') + expect(en.home.hero.description).toContain('safe releases') + expect(ko.home.hero.description).toContain('완료 기준') + expect(ko.home.hero.description).toContain('안전한 출시') + expect(source('src/app/[locale]/LedgerHome.tsx')).toContain("tHome('hero.description')") + }) + + it('renders the same source-pinned evidence records used by Hire', () => { + const home = source('src/app/[locale]/LedgerHome.tsx') + const strip = source('src/components/projects/EvidenceSnapshotStrip.tsx') + expect(home).toContain('') + expect(strip).toContain('evidence.records.map') + expect(strip).toContain('record.snapshotAt') + expect(strip).toContain('record.scopeKo') + expect(strip).toContain('record.scopeEn') + expect(strip).toContain('evidenceUrl(record)') + for (const record of evidence.records) { + expect(record.source.commit).toMatch(/^[0-9a-f]{40}$/) + expect(record.scopeEn.length).toBeGreaterThan(35) + expect(record.scopeKo.length).toBeGreaterThan(20) + } + }) + + it('never claims every ledger project is a released public demo', () => { + expect(projectsData.projects.some((p) => p.private && !p.website)).toBe(true) + expect(en.projects.metaDescription).not.toContain('each with a live demo or store link') + expect(en.projects.fullLedgerDescription).toContain('not a release') + expect(ko.projects.fullLedgerDescription).toContain('출시 수') + expect(en.hire.evidence.shipped).toContain('not necessarily a commercial launch') + }) + + it('makes the AI-assisted delivery approach concrete in both locales', () => { + const hire = source('src/app/[locale]/hire/page.tsx') + expect(hire).toContain('id="delivery-method"') + expect(hire).toContain('DELIVERY_STAGES.map') + expect(en.hire.approach.heading).toContain('AI-generated') + expect(ko.hire.approach.heading).toContain('검증 가능한') + for (const key of ['decision', 'verification', 'release'] as const) { + expect(en.hire.approach[key].body.length).toBeGreaterThan(55) + expect(ko.hire.approach[key].body.length).toBeGreaterThan(25) + } + }) + + it('keeps proof links to three actual case-study pages', () => { + const hire = source('src/app/[locale]/hire/page.tsx') + for (const slug of ['devdeck', 'citefirst', 'creator-os']) { + expect(projectsData.projects.find((p) => p.slug === slug)?.caseStudy).toBeTruthy() + expect(hire).toContain(`/projects/${slug}`) + } + }) +}) diff --git a/src/lib/__tests__/employment-positioning.test.ts b/src/lib/__tests__/employment-positioning.test.ts index 028b390..3d5951a 100644 --- a/src/lib/__tests__/employment-positioning.test.ts +++ b/src/lib/__tests__/employment-positioning.test.ts @@ -10,7 +10,7 @@ describe('employment positioning', () => { const home = readFileSync(join(process.cwd(), 'src/app/[locale]/LedgerHome.tsx'), 'utf8') expect(home).toContain('AI-NATIVE PRODUCT · AGENT SYSTEMS ENGINEER') expect(home).not.toContain('SOLO FULL-STACK BUILDER') - expect(home).toContain('systems that let AI agents do real work') + expect(home).toContain("tHome('hero.description')") expect(home).toContain('SELECTED_WORK.map') }) From a99a68f05105da2245d534681080b082aa23dce6 Mon Sep 17 00:00:00 2001 From: Si Hyeong Lee Date: Mon, 12 Oct 2026 16:55:27 -0700 Subject: [PATCH 08/10] feat(portfolio): document reproduced DevDeck session-sync failure and repair --- content/failure-cases.json | 166 +++++++++++++++ .../2026-10-12-devdeck-incident-case-study.md | 42 ++++ .../projects/devdeck-sync-qa-after.webp | Bin 0 -> 12938 bytes .../projects/devdeck-sync-qa-before.webp | Bin 0 -> 15030 bytes scripts/qa-portfolio.mts | 28 +++ src/app/[locale]/hire/page.tsx | 2 +- src/app/[locale]/projects/[slug]/page.tsx | 3 + .../projects/EvidenceSnapshotStrip.tsx | 2 +- .../projects/FailureInvestigation.tsx | 195 ++++++++++++++++++ .../__tests__/devdeck-failure-case.test.ts | 75 +++++++ 10 files changed, 511 insertions(+), 2 deletions(-) create mode 100644 content/failure-cases.json create mode 100644 docs/reviews/2026-10-12-devdeck-incident-case-study.md create mode 100644 public/images/projects/devdeck-sync-qa-after.webp create mode 100644 public/images/projects/devdeck-sync-qa-before.webp create mode 100644 src/components/projects/FailureInvestigation.tsx create mode 100644 src/lib/__tests__/devdeck-failure-case.test.ts diff --git a/content/failure-cases.json b/content/failure-cases.json new file mode 100644 index 0000000..415a016 --- /dev/null +++ b/content/failure-cases.json @@ -0,0 +1,166 @@ +{ + "schemaVersion": 1, + "incidents": [ + { + "id": "devdeck-session-title-convergence", + "project": "devdeck", + "recordedAt": "2026-09-08", + "verifiedAt": "2026-10-12", + "baselineCommit": "b7817547dd2100751ce46229a83810319affe82b", + "candidateCommit": "fa8864833b98e7d81f140e598b1f56d4d2b60c39", + "candidateVersion": "1.37.8", + "statusEn": "Validated candidate — not a public release", + "statusKo": "검증된 후보 버전 · 정식 출시 아님", + "titleEn": "The rename reached the host. The host screen stayed wrong.", + "titleKo": "이름 변경은 호스트에 도착했지만, 호스트 화면은 그대로였다.", + "introEn": "A remote viewer could rename a coding-agent terminal and the host's runtime metadata would change, yet its visible header and sidebar stayed stale. The original check inspected internal state rather than the user-facing window or disk record. A three-app regression made the visible failure reproducible.", + "introKo": "원격 뷰어에서 코딩 에이전트 세션 이름을 바꾸면 호스트의 런타임 메타데이터는 바뀌었지만, 실제 제목과 사이드바는 이전 값을 유지했습니다. 기존 검사는 내부 상태만 확인하고 화면이나 디스크 기록의 일치를 검사하지 않았습니다. Electron 앱 3개를 실행하는 회귀 테스트로 사용자가 보던 실패를 재현했습니다.", + "before": { + "image": "/images/projects/devdeck-sync-qa-before.webp", + "altEn": "Real isolated Electron QA fixture: the baseline host header and sidebar still show release-workspace after a remote rename.", + "altKo": "실제 격리 Electron QA에서 원격 이름 변경 이후에도 호스트 제목과 사이드바에 release-workspace가 남은 과거 실패 화면.", + "titleEn": "Before — host UI still shows the old title", + "titleKo": "수정 전 — 호스트 화면에 이전 제목이 남음", + "noteEn": "Historical 2026-09-08 failed fixture. The image combines two crops from the same QA screenshot; the terminal pane containing a local path is intentionally excluded.", + "noteKo": "2026-09-08 과거 실패 기록입니다. 동일한 QA 화면에서 제목과 사이드바를 잘라 합쳤으며, 로컬 경로가 있는 터미널 영역은 제외했습니다." + }, + "after": { + "image": "/images/projects/devdeck-sync-qa-after.webp", + "altEn": "Real isolated Electron QA fixture on 2026-10-12: host header and sidebar both show the committed title Converged 5.", + "altKo": "2026-10-12 격리된 실제 Electron QA에서 호스트 제목과 사이드바가 모두 Converged 5로 일치하는 화면.", + "titleEn": "After — host UI and sidebar agree", + "titleKo": "수정 후 — 호스트 제목과 사이드바가 일치", + "noteEn": "2026-10-12 fixture after eight convergence scenarios. Crops are taken from the same capture; no production conversations or customer data were used.", + "noteKo": "2026-10-12 8개 동기화 시나리오 이후의 가상 데이터 화면입니다. 한 화면의 일부를 추출했으며 실제 사용자 대화·고객 데이터는 사용하지 않았습니다." + }, + "reproduction": { + "titleEn": "Reproduce the user's failure", + "titleKo": "사용자에게 보인 실패 재현", + "stepsEn": [ + "Launch a disposable Windows Electron host and two paired viewers, each with a separate profile; pair through real loopback TLS with a harmless fixture CLI.", + "Rename a running terminal from Viewer A. On the historical baseline, host runtime metadata changed, but the host window still rendered its old header/sidebar title.", + "Assert the actual header, sidebar, saved-session list and on-disk state on all three apps—not only the transport response.", + "The historical baseline's first UI convergence check timed out. This candidate suite passes the same class of acceptance tests." + ], + "stepsKo": [ + "서로 다른 임시 프로필로 Windows Electron 호스트 1개와 뷰어 2개를 실행하고, 가짜 CLI와 실제 루프백 TLS로 연결합니다.", + "뷰어 A에서 실행 중인 터미널 이름을 변경합니다. 과거 기준 코드에서는 호스트 런타임 상태가 바뀌어도 제목·사이드바 화면은 이전 값을 표시했습니다.", + "전송 응답만 보지 않고 세 앱의 제목·사이드바·저장 목록·디스크 저장 상태까지 확인합니다.", + "과거 기준 버전에서는 첫 화면 일치 검사에서 시간이 초과됐고, 수정 후보의 동일 유형 사용자 경험 테스트는 통과했습니다." + ] + }, + "rootCause": { + "titleEn": "Root cause — a broken source of truth", + "titleKo": "원인 — 상태의 소유권이 일관되지 않음", + "textEn": "The host renderer's syncAdoptedLabel path excluded LOCAL_MACHINE_ID announcements, treating its own display as outside the update path. Older tests checked host runtime state but never the rendered title. Cached remote labels, unscoped identities, fire-and-forget renames, and stale replies introduced additional ways to display or persist the wrong value.", + "textKo": "호스트 렌더러의 syncAdoptedLabel 경로가 LOCAL_MACHINE_ID 변경 알림을 무시해 실제 호스트 화면이 갱신 경로에서 빠졌습니다. 기존 테스트는 호스트의 내부 상태만 검사하고 렌더된 제목을 검증하지 않았습니다. 오래된 캐시, 범위 없는 세션 ID, 응답 없는 변경 요청과 지연 응답도 불일치를 일으킬 수 있었습니다." + }, + "changes": [ + { + "titleEn": "Single host-owned write authority", + "titleKo": "호스트가 유일한 쓰기 권한을 보유", + "bodyEn": "Validate permissions, machine/project/provider identity, terminal incarnation and expected title revision. Reject stale writers with the owner's current snapshot.", + "bodyKo": "권한, 머신·프로젝트·공급자 ID, 터미널 인스턴스, 예상 제목 버전을 검증합니다. 오래된 수정 요청에는 호스트의 최신 스냅샷을 돌려줍니다." + }, + { + "titleEn": "Persist, then publish and acknowledge", + "titleKo": "저장 성공 후에만 화면 갱신·응답", + "bodyEn": "The host writes the disk record before updating runtime metadata, announcing the change or sending success. A disk failure leaves the previous committed title intact.", + "bodyKo": "호스트는 디스크 저장이 성공한 뒤 런타임 상태를 갱신하고 변경을 알리며 성공을 응답합니다. 저장 실패 때는 기존 제목을 유지합니다." + }, + { + "titleEn": "Keep the user's draft during conflicts", + "titleKo": "충돌 시 사용자의 편집 초안 보존", + "bodyEn": "A competing rename does not silently overwrite an open draft. Enter/Save explicitly commits; Escape discards. Delayed replies and obsolete cached titles cannot roll back newer state.", + "bodyKo": "다른 장치의 변경이 진행 중인 초안을 몰래 덮어쓰지 않습니다. Enter/저장만 확정하며 Escape는 취소합니다. 지연된 응답이나 오래된 캐시로 최신 상태를 되돌리지 못하게 합니다." + } + ], + "verification": { + "titleEn": "Verification beyond an API success response", + "titleKo": "API 응답을 넘어 실제 화면과 저장 상태 검증", + "focusedTests": 20, + "electronJourneys": 8, + "environmentEn": "Main Windows PC, three isolated Electron processes, real loopback TLS, synthetic terminal CLI, separate temporary profiles.", + "environmentKo": "MAIN Windows PC 한 대, 독립 Electron 프로세스 3개, 실제 루프백 TLS, 가짜 터미널 CLI와 별도의 임시 프로필.", + "commands": [ + "npm test -- src/main/sessionLabels.test.ts src/shared/sessionConsistency.test.ts", + "npm run qa:session-sync" + ], + "journeys": [ + { + "en": "Viewer rename updates host and both viewers", + "ko": "뷰어의 변경이 호스트·다른 뷰어에 반영" + }, + { + "en": "Host rename keeps the terminal mounted", + "ko": "호스트 이름 변경 시 터미널 재생성 방지" + }, + { + "en": "Stale edits are rejected without losing drafts", + "ko": "오래된 수정 차단·사용자 초안 보존" + }, + { + "en": "Disk failure avoids false success; retry works", + "ko": "디스크 오류 시 성공 오인 방지·재시도" + }, + { + "en": "Permission removal blocks unauthorized change", + "ko": "권한 제거 시 무단 변경 차단" + }, + { + "en": "Disconnect preserves draft; reconnect and retry", + "ko": "연결 끊김에도 초안 유지·재연결" + }, + { + "en": "Explicit clear survives viewer restart", + "ko": "제목 초기화가 뷰어 재시작 후에도 유지" + }, + { + "en": "Repeated rename cycles keep all three views aligned", + "ko": "반복 수정에도 세 화면이 일치" + } + ], + "limitationsEn": "Not two physical machines. Not long-running VPN/sleep/resume or live agent-provider acceptance. Real installer and updater journeys, human visual review and 1.37.8 public-release approval remain open. The baseline screenshot is historical, while the passing checks were rerun on 2026-10-12.", + "limitationsKo": "물리적으로 분리된 두 PC, 장기 VPN·절전 복구, 실제 AI 공급자 작업 부하는 검증하지 않았습니다. 설치 마법사·업데이터·사람의 시각 검수와 1.37.8 정식 출시 승인도 별도입니다. 실패 이미지는 과거 기록이고 통과 검사는 2026-10-12 재실행했습니다." + }, + "sources": [ + { + "kind": "baseline", + "labelEn": "Baseline commit", + "labelKo": "실패 기준 커밋", + "href": "https://github.com/writingdeveloper/devdeck/commit/b7817547dd2100751ce46229a83810319affe82b" + }, + { + "kind": "fix", + "labelEn": "Fix commit and diff", + "labelKo": "수정 커밋·변경 코드", + "href": "https://github.com/writingdeveloper/devdeck/commit/fa8864833b98e7d81f140e598b1f56d4d2b60c39" + }, + { + "kind": "review", + "labelEn": "Incident review", + "labelKo": "장애 분석·검증 기록", + "href": "https://github.com/writingdeveloper/devdeck/blob/fa8864833b98e7d81f140e598b1f56d4d2b60c39/docs/session-sync-review-2026-09-08.md" + }, + { + "kind": "unit", + "labelEn": "Focused unit tests", + "labelKo": "단위 회귀 테스트", + "href": "https://github.com/writingdeveloper/devdeck/blob/fa8864833b98e7d81f140e598b1f56d4d2b60c39/src/main/sessionLabels.test.ts" + }, + { + "kind": "harness", + "labelEn": "Three-app QA harness", + "labelKo": "Electron 3개 앱 QA 코드", + "href": "https://github.com/writingdeveloper/devdeck/blob/fa8864833b98e7d81f140e598b1f56d4d2b60c39/qa/session-sync.mjs" + }, + { + "kind": "ci", + "labelEn": "Same-commit green Windows CI", + "labelKo": "동일 커밋 Windows CI 통과", + "href": "https://github.com/writingdeveloper/devdeck/actions/runs/34319241204" + } + ] + } + ] +} diff --git a/docs/reviews/2026-10-12-devdeck-incident-case-study.md b/docs/reviews/2026-10-12-devdeck-incident-case-study.md new file mode 100644 index 0000000..b600633 --- /dev/null +++ b/docs/reviews/2026-10-12-devdeck-incident-case-study.md @@ -0,0 +1,42 @@ +# DevDeck incident reconstruction — UI convergence after a remote rename + +Reviewed: 2026-10-12 (America/Los_Angeles) +DevDeck source: [baseline `b781754`](https://github.com/writingdeveloper/devdeck/commit/b7817547dd2100751ce46229a83810319affe82b) → [fix `fa88648`](https://github.com/writingdeveloper/devdeck/commit/fa8864833b98e7d81f140e598b1f56d4d2b60c39). +Publication: **1.37.8 candidate / source and CI verified, NOT a public release**. + +## User-visible defect and the actual evidence + +A remote DevDeck viewer renamed a running terminal. The host process's live runtime metadata showed that rename but the host's visible header and sidebar retained the old name. The original acceptance check inspected host metadata only and therefore missed the user-visible failure. After adding a real three-Electron-app harness, the historical baseline's first UI convergence assertion **timed out**. + +Source: `devdeck/docs/session-sync-review-2026-09-08.md` at `fa88648`. The historical local `devdeck/qa/shots/session-sync-before/results.json` contains an empty passed list and one `TimeoutError: page.waitForFunction: Timeout 8000ms exceeded`. This historical reproduction was documented in September; **it was not rerun on the baseline on 2026-10-12**. + +Root cause: `syncAdoptedLabel` in host renderer excluded `LOCAL_MACHINE_ID` label announcements, leaving host-visible state disconnected from the runtime update. Cached titles could be mistaken for authority; unversioned fire-and-forget writes, weak session identity and stale async responses introduced additional consistency risks. + +Candidate changes: session identity scope (machine + project + provider + conversation, plus terminal incarnation); a host-owned title transaction validating authorization and expected revision, persisting to disk before runtime event/ACK; caller-visible version conflicts preserving drafts; stale-pull invalidation and read-only viewer reattachment; legacy method refusal. + +This is a specific software incident, not a broad claim that an AI coding agent wrote or fixed the bug unaided. + +## Verified now, 2026-10-12 + +All commands ran on **MAIN / SIHYEONG-MAIN**, with the source checkout at exact `fa8864833b98e7d81f140e598b1f56d4d2b60c39` and **no dirty changes**. + +- `npm test -- src/main/sessionLabels.test.ts src/shared/sessionConsistency.test.ts`: **20/20 passed**. The storage-failure test intentionally exercises an EISDIR write error and asserts no false runtime/peer commit; the expected error is a controlled test fixture, not a failed test. +- `npm run qa:session-sync`: built the Electron app and passed **8/8** host + two-viewer real loopback TLS user journeys. These include UI+disk convergence, no remount, stale edit conflict, disk failure/retry, permission removal, offline/reconnect, restart/cache clear and repeated rename cycles. +- `devdeck/qa/shots/session-sync/results.json`: 8 pass strings, `errors: []`. Its locally recorded SHA-256 at this run was `c105102941be924c13d7d64b894ec1584c617b8140bed679782d85a281388414`. +- Source [same-fix-commit Linux/macOS/Windows CI](https://github.com/writingdeveloper/devdeck/actions/runs/34319241204) was green. The Windows failure-and-recovery job includes the real host + two viewers exercise. That GitHub action belongs to `fa88648`, not any more recent/default-branch commit. + +### Real screenshot provenance and privacy + +- Original baseline fixture: `devdeck/qa/shots/session-sync-before/Build-workstation-failure.png`, SHA-256 `7b94611de24c39498ee834eb96becd5d7f93472dfc6146a4e56d3ce9b48ee5ca`. +- Original current passing fixture: `devdeck/qa/shots/session-sync/Build-workstation.png`, SHA-256 `cda5daae66e9a390199430a88469b0c98da69720003c11fd93105a0a4621f6e2`. +- Public derivative assets: `public/images/projects/devdeck-sync-qa-before.webp` and `...after.webp`. Each **composites two real crops of the same corresponding screenshot**: host title and sidebar. The terminal area containing a local user/profile path was excluded. Crops are labeled as QA fixtures, not production installations. The before and after images were captured on different dates. + +## Disclaimers and release gates + +This is **one Windows machine with three isolated Electron processes**, temporary profiles, fixture repository and harmless CLI; it is not two physical computers with changing VPN/wifi/sleep. It does not validate months of field use, live paid-agent workloads, installer/updater approval, or user acceptance. Notes remain on separate last-write-wins semantics. DevDeck 1.37.8 still has an unreleased PR; do not call it publicly shipped. + +The WritingDeveloper site embeds this **incident case study** inside the existing DevDeck project detail, adds bilingual source/CI links, and navigates directly from Home and Hire. Separate FOLIO-45/36 security/release gates prevent publishing the broader portfolio update to Vercel production; green local site tests are not release authorization. + +## Site QA contract + +`content/failure-cases.json` holds the dated incident, exact source commit SHA, bounded result counts and limitations, plus six immutable GitHub source links. `src/lib/__tests__/devdeck-failure-case.test.ts` enforces dates, links, fixture image paths and that private paths aren't linked. `npm run qa:portfolio` additionally checks actual EN/KO DevDeck pages, the two loaded QA crops, source links, test counts and visible scope caveats. diff --git a/public/images/projects/devdeck-sync-qa-after.webp b/public/images/projects/devdeck-sync-qa-after.webp new file mode 100644 index 0000000000000000000000000000000000000000..f082ec7b45fcbec50594b3ce467543da59d7d633 GIT binary patch literal 12938 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%0A24j(}Zqmr(wQZ z)s`LOP4jW0(^+{9Y_4oslruJ8)E8mot(Mr$S!2Ic4)R9` zlgbg51h46u4WmvY7^daua-&i@9V@HBK1BTSHF#}4%-LU_X8p?Cm2XvBd1AsA=fL-pd7_8;@HdkENCer%9t^x+rUj+>>*XoH;Gh>r~Dye z`P$Sp&ZVAW5JBI5+pEf3zKwjbsjgzfPJuEdi!CLoi~M-1ttj(;W*`FGMqi4^sfgdrm$UhkMS{vLOa3ysC< zz8H$!JT@9$ke{WGn}N5Y+KBSFk~r7$#MyztBV@tSeHH!8ux{v%xDZCPA<-o_TBoqk zp?a5Lmv_-((k9$muh-ho!@I)8gmY9;eQ8*nr85Ss<~Mh4Tm}^uCi$?9Vhz5k6uh66 zBx@h)P<)yJgXE-#ZfRn|m@P*QX zn|SK(oJW>}u+EG$dLWCpVdZhDu9)s3R`T6rbr)5vn}5v zXfH*trJ&Y?<@}vm-Ek(T z&yInWzP+BNmjnLx;&All!yM}S>eghLsA}!7iuX0x&N$0~zWRJVV?NH{FR7b-md?|H z8e>nJ-HD0Nl`$%vb|}h)yIC>#p5PMv3Nd{ zw1mr-jYN?NY08)aQeMYk+{r>ZF6^LEcZ<~ z4mB$QJ8k;t#fWh_Z el instanceof HTMLImageElement && el.complete && el.naturalWidth > 0) + assert(loaded, 'QA fixture screenshot failed to load') + } + results.push({ route, status: response?.status(), imagesLoaded: 2, pinnedLinks: 6, incident: true }) + console.log('PASS INCIDENT', route, 'before/after images, 6 source links, scope') + await incidentCtx.close() + } for (const file of resumes.files) { const r = await ctx.request.get(base + '/resume/' + file.file) assert(r.ok() && r.headers()['content-type']?.includes('application/pdf'), 'PDF response invalid') diff --git a/src/app/[locale]/hire/page.tsx b/src/app/[locale]/hire/page.tsx index 73ed3bc..f2da9e3 100644 --- a/src/app/[locale]/hire/page.tsx +++ b/src/app/[locale]/hire/page.tsx @@ -74,7 +74,7 @@ function OfferRow({ label, children }: { label: string; children: ReactNode }) { } const DELIVERY_STAGES = [ - { key: 'decision', href: '/projects/devdeck' }, + { key: 'decision', href: '/projects/devdeck#failure-investigation' }, { key: 'verification', href: '/projects/citefirst' }, { key: 'release', href: '/projects/creator-os' }, ] as const diff --git a/src/app/[locale]/projects/[slug]/page.tsx b/src/app/[locale]/projects/[slug]/page.tsx index d41f42e..3ddcb9b 100644 --- a/src/app/[locale]/projects/[slug]/page.tsx +++ b/src/app/[locale]/projects/[slug]/page.tsx @@ -12,6 +12,7 @@ import { predecessorOf } from '@/lib/lineage' import { getAllPosts } from '@/lib/mdx' import { buildProjectPostMap } from '@/lib/post-project-links' import { PageTransition } from '@/components/ui/PageTransition' +import { FailureInvestigation } from '@/components/projects/FailureInvestigation' import { generateBreadcrumbJsonLd, generateProjectJsonLd, safeJsonLd, toAbsoluteUrl } from '@/lib/seo' const PROJECTS = projectsData.projects as Project[] @@ -223,6 +224,8 @@ export default async function ProjectDetailPage({ params }: { params: Promise<{
)} + +
{/* Sits first: for a private project with no website this is the only place on the page that goes anywhere at all. */} diff --git a/src/components/projects/EvidenceSnapshotStrip.tsx b/src/components/projects/EvidenceSnapshotStrip.tsx index 5c7bab0..0ac5dbf 100644 --- a/src/components/projects/EvidenceSnapshotStrip.tsx +++ b/src/components/projects/EvidenceSnapshotStrip.tsx @@ -68,7 +68,7 @@ export function EvidenceSnapshotStrip({ locale }: { locale: string }) {

diff --git a/src/components/projects/FailureInvestigation.tsx b/src/components/projects/FailureInvestigation.tsx new file mode 100644 index 0000000..fbd2c22 --- /dev/null +++ b/src/components/projects/FailureInvestigation.tsx @@ -0,0 +1,195 @@ +import Image from 'next/image' +import reports from '../../../content/failure-cases.json' + +/** Reviewed incident evidence, rendered only on the matching project. */ +export function FailureInvestigation({ projectSlug, locale }: { projectSlug: string; locale: string }) { + const item = reports.incidents.find((entry) => entry.project === projectSlug) + if (!item) return null + const ko = locale === 'ko' + + return ( +
+
+

+ {ko ? '실패 → 원인 → 수정 → 검증' : 'Engineering incident / failure to verification'} +

+

+ {ko ? item.titleKo : item.titleEn} +

+

{ko ? item.introKo : item.introEn}

+
+ + {ko ? item.statusKo : item.statusEn} + + + {ko ? '최초 실패 기록' : 'Baseline recorded'}: + +
+
+ +
+ {[item.before, item.after].map((frame, index) => ( +
+
+ + {index === 0 ? (ko ? '실패' : 'Before') : ko ? '수정 후' : 'After'} + +

{ko ? frame.titleKo : frame.titleEn}

+
+ {ko +
+ {ko ? frame.noteKo : frame.noteEn} +
+
+ ))} +
+ +
+
+

+ {ko ? item.reproduction.titleKo : item.reproduction.titleEn} +

+
    + {(ko ? item.reproduction.stepsKo : item.reproduction.stepsEn).map((step, i) => ( +
  1. + + {String(i + 1).padStart(2, '0')} + + {step} +
  2. + ))} +
+
+
+

{ko ? item.rootCause.titleKo : item.rootCause.titleEn}

+

+ {ko ? item.rootCause.textKo : item.rootCause.textEn} +

+

+ {ko + ? '전송 성공은 실제 화면과 영속 상태가 올바르다는 증거가 아닙니다.' + : 'A successful transport response is not proof that the UI or persistent record is correct.'} +

+
+
+ +
+

+ {ko ? '수정: 상태 소유권·쓰기 순서·초안 보호' : 'Fix: ownership, write ordering, and draft protection'} +

+
+ {item.changes.map((change, i) => ( +
+ {String(i + 1).padStart(2, '0')} +

{ko ? change.titleKo : change.titleEn}

+

+ {ko ? change.bodyKo : change.bodyEn} +

+
+ ))} +
+
+ +
+

+ {ko ? item.verification.titleKo : item.verification.titleEn} +

+
+
+

+ {item.verification.focusedTests}/{item.verification.focusedTests} +

+

+ {ko ? '관련 단위 테스트 통과' : 'Focused unit tests passed'} +

+
+
+

+ {item.verification.electronJourneys}/{item.verification.electronJourneys} +

+

+ {ko ? 'Electron 3개 앱 검증 통과' : 'Three-app Electron journeys passed'} +

+
+
+

+ {ko ? '재실행' : 'Rerun'}: .{' '} + {ko ? item.verification.environmentKo : item.verification.environmentEn} +

+
    + {item.verification.journeys.map((journey) => ( +
  • + + {ko ? journey.ko : journey.en} +
  • + ))} +
+

{ko ? '재검증 명령' : 'Reproduce the checks'}

+
+ {item.verification.commands.map((command) => ( + + {command} + + ))} +
+
+ + + +
+
+ ) +} diff --git a/src/lib/__tests__/devdeck-failure-case.test.ts b/src/lib/__tests__/devdeck-failure-case.test.ts new file mode 100644 index 0000000..932ddfe --- /dev/null +++ b/src/lib/__tests__/devdeck-failure-case.test.ts @@ -0,0 +1,75 @@ +import { statSync } from 'node:fs' +import { join } from 'node:path' +import { describe, expect, it } from 'vitest' +import cases from '../../../content/failure-cases.json' +import projects from '../../../content/projects.json' + +const incident = cases.incidents[0] +const baseline = 'b7817547dd2100751ce46229a83810319affe82b' +const candidate = 'fa8864833b98e7d81f140e598b1f56d4d2b60c39' + +describe('DevDeck source-backed failure reconstruction', () => { + it('describes exactly one case anchored to a real, existing project', () => { + expect(cases.schemaVersion).toBe(1) + expect(cases.incidents).toHaveLength(1) + expect(incident.project).toBe('devdeck') + expect(projects.projects.some((project) => project.slug === incident.project)).toBe(true) + expect(incident.baselineCommit).toBe(baseline) + expect(incident.candidateCommit).toBe(candidate) + }) + + it('distinguishes the historical failure from the Oct 12 rerun and public release', () => { + expect(incident.recordedAt).toBe('2026-09-08') + expect(incident.verifiedAt).toBe('2026-10-12') + expect(incident.statusEn).toContain('not a public release') + expect(incident.statusKo).toContain('정식 출시 아님') + expect(incident.verification.limitationsEn).toContain('Not two physical machines') + expect(incident.verification.limitationsKo).toContain('물리적으로 분리된') + }) + + it('has the reproduced user-visible failure and a specific root cause in both locales', () => { + for (const [steps, cause, before, after] of [ + [incident.reproduction.stepsEn, incident.rootCause.textEn, incident.before.noteEn, incident.after.noteEn], + [incident.reproduction.stepsKo, incident.rootCause.textKo, incident.before.noteKo, incident.after.noteKo], + ] as const) { + expect(steps).toHaveLength(4) + expect(cause).toContain('LOCAL_MACHINE_ID') + expect(before.length).toBeGreaterThan(25) + expect(after.length).toBeGreaterThan(25) + } + expect(incident.changes).toHaveLength(3) + expect(incident.verification.commands).toEqual([ + 'npm test -- src/main/sessionLabels.test.ts src/shared/sessionConsistency.test.ts', + 'npm run qa:session-sync', + ]) + }) + + it('shows the actually executed 20 focused tests and eight independent Electron journeys', () => { + expect(incident.verification.focusedTests).toBe(20) + expect(incident.verification.electronJourneys).toBe(8) + expect(incident.verification.journeys).toHaveLength(8) + expect(new Set(incident.verification.journeys.map((journey) => journey.en)).size).toBe(8) + for (const journey of incident.verification.journeys) expect(journey.ko.length).toBeGreaterThan(10) + }) + + it('only publishes small, locally redacted fixture crops; never private paths', () => { + for (const photo of [incident.before, incident.after]) { + expect(photo.image).toMatch(/^\/images\/projects\/devdeck-sync-qa-(before|after)\.webp$/) + const size = statSync(join(process.cwd(), 'public', photo.image.slice(1))).size + expect(size).toBeGreaterThan(2000) + expect(size).toBeLessThan(90000) + expect(photo.noteEn.toLowerCase()).toContain('crop') + } + }) + + it('links only to immutable GitHub sources and a same-commit successful CI run', () => { + const kinds = incident.sources.map((source) => source.kind) + expect(kinds).toEqual(['baseline', 'fix', 'review', 'unit', 'harness', 'ci']) + for (const source of incident.sources) { + expect(source.href).toMatch(/^https:\/\/github\.com\/writingdeveloper\/devdeck\//) + if (source.kind === 'baseline') expect(source.href).toContain(baseline) + else if (source.kind === 'ci') expect(source.href).toContain('34319241204') + else expect(source.href).toContain(candidate) + } + }) +}) From 5fe338e1e156ec53cf8eb024376124e10dc05be2 Mon Sep 17 00:00:00 2001 From: Si Hyeong Lee Date: Mon, 12 Oct 2026 16:58:58 -0700 Subject: [PATCH 09/10] fix(portfolio): keep all evidence links routed to their own projects --- src/components/projects/EvidenceSnapshotStrip.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/projects/EvidenceSnapshotStrip.tsx b/src/components/projects/EvidenceSnapshotStrip.tsx index 0ac5dbf..229c964 100644 --- a/src/components/projects/EvidenceSnapshotStrip.tsx +++ b/src/components/projects/EvidenceSnapshotStrip.tsx @@ -68,7 +68,11 @@ export function EvidenceSnapshotStrip({ locale }: { locale: string }) {

From dc7cf1b5cb01e97bc194094e24da13b281a17195 Mon Sep 17 00:00:00 2001 From: Si Hyeong Lee Date: Tue, 13 Oct 2026 16:29:39 -0700 Subject: [PATCH 10/10] feat(portfolio): verify October production projects and audit public links --- content/projects.json | 55 ++++---- content/verified-demos.json | 23 ++++ .../2026-10-13-portfolio-refresh-audit.md | 81 ++++++++++++ package.json | 3 +- .../projects/brain-vat-npc-production.webp | Bin 0 -> 58598 bytes scripts/audit-public-links.mts | 122 ++++++++++++++++++ scripts/qa-portfolio.mts | 38 ++++++ src/app/[locale]/projects/[slug]/page.tsx | 3 + .../projects/VerifiedProjectDemo.tsx | 68 ++++++++++ .../portfolio-freshness-20261013.test.ts | 64 +++++++++ src/lib/__tests__/projects.test.ts | 7 +- 11 files changed, 433 insertions(+), 31 deletions(-) create mode 100644 content/verified-demos.json create mode 100644 docs/reviews/2026-10-13-portfolio-refresh-audit.md create mode 100644 public/images/projects/brain-vat-npc-production.webp create mode 100644 scripts/audit-public-links.mts create mode 100644 src/components/projects/VerifiedProjectDemo.tsx create mode 100644 src/lib/__tests__/portfolio-freshness-20261013.test.ts diff --git a/content/projects.json b/content/projects.json index 623f52e..a80fdcb 100644 --- a/content/projects.json +++ b/content/projects.json @@ -1,10 +1,10 @@ { "projects": [ { - "name": "Soursea", + "name": "Soursea — Personal Sourcing Workspace", "slug": "soursea", - "descriptionKo": "한국→미국 셀러용 Electron 소싱 데스크톱 도구. 내장 브라우저에서 공급처 페이지를 구조화된 로컬 상품 데이터로 추출하고, 운영 보드와 MCP를 통해 Claude Code 분석까지 연결합니다.", - "descriptionEn": "Electron desktop sourcing workspace for a Korea→US seller. An embedded browser turns supplier pages into structured local product records, then connects that data to an operations board and Claude Code through MCP.", + "descriptionKo": "Soursea LLC의 고객용 서비스 목록과 별개인 개인용 Electron 상품 소싱 도구입니다. 내장 브라우저에서 공급처 정보를 정규화해 로컬 SQLite에 저장하고 MCP로 분석 워크플로에 연결하지만, 공개 SaaS로 제공하지 않습니다.", + "descriptionEn": "A personal-use Electron sourcing workspace (not the Soursea LLC customer product catalog). An embedded browser normalizes supplier pages into local SQLite records and connects operations data to a local MCP client; it is not offered as a public SaaS.", "techStack": [ "Electron", "TypeScript", @@ -34,10 +34,10 @@ } }, { - "name": "Creator OS", + "name": "Creator OS — Release Engineering", "slug": "creator-os", - "descriptionKo": "크리에이터·YouTube 리포팅 SaaS를 실제 고객 환경에 내보내기 전에 실패 폐쇄형 릴리스 게이트로 단단하게 만든 production-hardening 프로젝트. PostgreSQL 워커, Docker 런타임, 백업·복구, Playwright QA와 운영 프리플라이트를 한 릴리스 계약으로 묶었습니다.", - "descriptionEn": "A production-hardening project for a creator and YouTube reporting SaaS. Before exposing customer traffic, I tied PostgreSQL workers, Docker runtime, backup/recovery, Playwright QA, and fail-closed operator preflight into one release contract.", + "descriptionKo": "별도 SaaS가 아니라 같은 Creator OS 제품의 출시 엔지니어링 사례입니다. PostgreSQL 워커·Docker 배포 정체성, 암호화 백업·복구 리허설, 운영자 사전 점검과 읽기 전용 파일럿 검증을 통해 빌드 성공과 실제 고객용 출시를 구분합니다.", + "descriptionEn": "An engineering case study of the same Creator OS product, not another standalone SaaS. It separates a working build from customer-safe deployment using PostgreSQL worker checks, Docker deployment identity, encrypted backups, restore rehearsals, explicit operator preflights, and read-only pilot verification.", "techStack": [ "Next.js", "TypeScript", @@ -51,7 +51,7 @@ "status": "active", "private": true, "featured": false, - "updatedAt": "2026-09-23", + "updatedAt": "2026-10-08", "screenshot": "/images/projects/creator-os.png", "screenshotAltKo": "Creator OS 비공개 스테이징의 실제 Today 리포트 화면. 배포 전 QA에서 캡처한 제품 UI.", "screenshotAltEn": "The real Creator OS Today report UI captured during private-staging QA before public launch.", @@ -62,8 +62,8 @@ "decisionEn": "I separated source completion from launch approval. The release uses immutable manifests, a dedicated PostgreSQL worker, Docker/Compose verification, backup-and-restore plus an independent deletion ledger, fail-closed operator/preflight checks, and a separate FINAL-QA gate. Missing external evidence stays blocked instead of being treated as success.", "evidenceKo": "최근 COS-32/33 최종 QA에서 focused 22/22, 전체 회귀 669건 통과(27건은 DB 미구성으로 skip이며 pass로 세지 않음), typecheck·production build·release verifier가 통과했습니다. 올바른 4080 private-staging host에 대한 29/29 read-only live checks도 통과했습니다.", "evidenceEn": "The latest COS-32/33 final QA passed 22/22 focused checks and 669 regression tests; 27 database-dependent tests were skipped and explicitly not counted as passes. Typecheck, production build, release verifiers, and 29/29 read-only checks against the intended 4080 private-staging host also passed.", - "resultKo": "반복 가능한 private-staging 릴리스 증거와 운영 경계를 만들었지만, public launch는 DNS 쓰기 인증·공개 TLS/proxy·실제 Google 동의·정책/지원 정보·이메일 sender·암호화 백업 키 보관 등 외부 게이트가 남아 있어 의도적으로 차단 상태로 유지했습니다.", - "resultEn": "The result is a reproducible private-staging release with explicit operational evidence. Public launch remains intentionally blocked on external gates such as authoritative DNS access, public TLS/proxy verification, real Google consent, policy/support approval, email sender identity, and encrypted recovery-key custody." + "resultKo": "10월 6일부터 승인된 Google 테스트 사용자와 읽기 전용 YouTube 동의를 사용하는 제한된 외부 파일럿을 운영했습니다. 누구나 가입하는 공개 출시·결제는 별도이며, 이 항목은 두 번째 제품이 아닌 출시 안전성 엔지니어링 기록입니다.", + "resultEn": "A bounded external pilot was activated on October 6 for approved Google test users, with real read-only YouTube consent. Broad public registration and billing are not available; this entry tracks engineering and release safety, not a second product." } }, { @@ -536,10 +536,10 @@ "featured": true }, { - "name": "Creator Learning OS", + "name": "Creator OS — Product & External Pilot", "slug": "creator-learning-os", - "descriptionKo": "YouTube 채널 데이터를 '그래서 지금 무엇을 만들거나 고쳐야 하는가?'라는 하나의 실행 항목으로 바꾸는 evidence-first Creator SaaS. 내부 Load Path 데이터와 고객 CSV 흐름을 같은 모델로 다루고 Today·Video diagnostics·Briefs·Experiments·Playbook을 연결했습니다. SQLite/PostgreSQL 어댑터, tenant 경계, desktop/mobile Playwright QA, fail-closed release readiness와 PostgreSQL backup/recovery tooling까지 구현했으며, 고객 OAuth·billing 등 미완료 요소는 출시로 포장하지 않고 명시적으로 차단합니다. 아직 public/paid SaaS는 출시하지 않았습니다.", - "descriptionEn": "An evidence-first creator SaaS built around one question: what should I create or improve now? It turns YouTube/channel evidence into one concrete next task while keeping the supporting detail on demand. The product connects Today, video diagnostics, saved Briefs, Experiments and a channel Playbook across internal reference data and customer CSV flows, with SQLite/PostgreSQL adapters, tenant boundaries, desktop/mobile Playwright QA, fail-closed release readiness, and PostgreSQL backup/recovery tooling. Customer OAuth, billing and other unfinished production requirements stay explicitly blocked rather than being relabeled as shipped. Public/paid SaaS is not released yet.", + "descriptionKo": "“지금 무엇을 개선해야 하나?”에 답하도록 설계한 크리에이터·YouTube 의사결정 SaaS입니다. 10월 6일부터 공개 호스트의 외부 파일럿이 운영되지만 Google 로그인은 승인된 테스트 사용자에게만 제공됩니다. 별도 읽기 전용 YouTube 동의, 근거 기반 결정론적 리포트, 비로그인 데모, 백업·복구 및 운영 게이트가 검증됐습니다. 일반 회원가입·유료 출시·실시간 LLM 추론 서비스는 아닙니다.", + "descriptionEn": "A creator and YouTube decision-support SaaS for answering “what should I improve now?” October 6 brought an external pilot on a public host, but Google sign-in remains Testing-only for approved users. Separate read-only YouTube consent, evidence-bound deterministic reports, a public no-login demo, backup/restore drills, and operator release gates are verified. This is not unrestricted signup, paid availability, or live LLM inference.", "techStack": [ "TypeScript", "Next.js", @@ -552,17 +552,18 @@ "status": "building", "private": true, "featured": false, - "updatedAt": "2026-09-22", + "updatedAt": "2026-10-08", "caseStudy": { "problemKo": "크리에이터 분석 도구는 지표를 많이 보여줘도 사용자가 다음에 무엇을 해야 하는지 다시 해석해야 하는 경우가 많습니다.", "problemEn": "Creator analytics often expose more metrics while still making the user decide what to do next.", "decisionKo": "대시보드의 중심을 점수나 차트가 아니라 '지금 할 한 가지'로 두고, 근거와 진단은 필요할 때만 펼치도록 설계했습니다. 릴리스 준비도는 미완료 의존성이 있으면 fail-closed 처리합니다.", "decisionEn": "I centered the product on one concrete next action rather than an opaque score, with evidence and diagnostics available on demand. Release readiness fails closed when production dependencies remain incomplete.", - "evidenceKo": "SQLite/PostgreSQL 어댑터, tenant 경계, desktop/Pixel 7 Playwright QA, provider readiness gate, 4080 배포 검증, PostgreSQL backup/recovery bundle이 저장소에 구현되어 있습니다.", - "evidenceEn": "The repository includes SQLite/PostgreSQL adapters, tenant boundaries, desktop/Pixel 7 Playwright QA, provider-readiness gates, 4080 deployment verification, and PostgreSQL backup/recovery tooling.", - "resultKo": "분석을 읽는 제품에서, 근거를 보존하면서 바로 실행할 작업을 주는 운영 도구로 방향을 좁혔습니다. 아직 미출시 요소는 명시적으로 미출시로 남깁니다.", - "resultEn": "The product is converging from a reporting surface into an operating tool that gives one evidence-backed action. Unfinished release requirements remain explicitly unshipped." - } + "evidenceKo": "10월 6일 공개 호스트 전환 기록에서 Cloudflare TLS·AOP 신뢰 경계와 승인된 테스트 사용자 Google 로그인, 별도 읽기 전용 YouTube 동의를 확인했습니다. 10월 8일에는 한영 약관·지원 화면, 모델 API 호출 없는 근거 중심 결정론적 리포트, 외부 저장소 PostgreSQL 복구 리허설을 검증했습니다. /demo는 비로그인 접근 가능하지만 불특정 사용자 가입이나 실사용자 규모는 확인하지 않았습니다.", + "evidenceEn": "An October 6 public-host activation verified Cloudflare TLS, AOP trust boundary and allowed-test-user Google login with separate YouTube read-only consent. The October 8 release record verified bilingual policy/support pages, deterministic grounded reports without a provider model call, and an off-device PostgreSQL backup restore drill. Public /demo is accessible without login; production external-user volume and unrestricted signup were not verified.", + "resultKo": "비로그인 데모와 승인된 Google 테스트 사용자 로그인을 갖춘 외부 파일럿 단계입니다. 일반 고객 확대, 결제, 모델 API 추론 및 무제한 셀프서비스는 별도 출시 과제입니다.", + "resultEn": "An external pilot with a public read-only demo and a restricted Google test-user login is running. Customer-scale rollout, billing, provider-model inference and unrestricted self-service remain separate unapproved releases." + }, + "website": "https://creator.writingdeveloper.blog/demo" }, { "name": "RailForge", @@ -1068,8 +1069,8 @@ { "name": "BRAIN//VAT", "slug": "brain-vat-siege", - "descriptionKo": "Three.js 보스전과 신경 컨트롤러 연구를 하나의 공개 인터랙티브 케이스 스터디로 만든 프로젝트입니다. 미학습·사전학습·온라인 적응 예측기를 같은 입력에서 비교하고, 플레이로 달라진 102개 가중치 기억을 호환 보스 몸체로 옮길 수 있습니다. 별도 연구 경로에서는 166,700-뉴런 MaleCNS 고정 connectome의 시간 상태에 작은 외부 readout을 붙여 held-out 움직임 이력 분류를 검증했습니다.", - "descriptionEn": "A public interactive case study combining a Three.js boss fight with neural-controller research. It compares untrained, pretrained-frozen and online-adaptive predictors on the same committed inputs, and lets a player move a 102-weight learned memory cartridge into a compatible boss chassis. A separate research path keeps the 166,700-neuron MaleCNS connectome fixed and tests small external readouts over its temporal state on a held-out motion-history task.", + "descriptionKo": "Three.js 보스전과 신경 컨트롤러 연구를 하나의 공개 인터랙티브 케이스 스터디로 만든 프로젝트입니다. 미학습·사전학습·온라인 적응 예측기를 같은 입력에서 비교하고, 플레이로 달라진 102개 가중치 기억을 호환 보스 몸체로 옮길 수 있습니다. 별도 연구 경로에서는 166,700-뉴런 MaleCNS 고정 connectome의 시간 상태에 작은 외부 readout을 붙여 held-out 움직임 이력 분류를 검증했습니다. 10월 13일 공개된 별도 /npc 데모에서는 제한된 관측과 목격 이벤트 기억, 세계 상태에 따른 행동 검증을 갖춘 규칙 기반 경비 NPC를 구현했습니다. 학습 모델이나 LLM NPC는 아닙니다.", + "descriptionEn": "A public interactive case study combining a Three.js boss fight with neural-controller research. It compares untrained, pretrained-frozen and online-adaptive predictors on the same committed inputs, and lets a player move a 102-weight learned memory cartridge into a compatible boss chassis. A separate research path keeps the 166,700-neuron MaleCNS connectome fixed and tests small external readouts over its temporal state on a held-out motion-history task. On October 13, a separate public /npc demo added a deterministic rule-driven guard with filtered observations, witnessed-event memory, and world-validated actions. It is not an LLM or trained NPC.", "techStack": [ "JavaScript", "Three.js", @@ -1084,19 +1085,19 @@ "website": "https://brain-vat-siege.vercel.app", "private": true, "featured": true, - "updatedAt": "2026-09-23", + "updatedAt": "2026-10-13", "screenshot": "/images/projects/brain-vat-siege.webp", "screenshotAltKo": "BRAIN//VAT SENTINEL 보스전의 실제 Three.js 화면. 중앙의 발광 기계형 보스가 세 개의 네온 레인을 향해 공격을 준비하고 있다.", "screenshotAltEn": "A real Three.js capture of the BRAIN//VAT SENTINEL boss fight, with a glowing mechanical boss preparing an attack over three neon lanes.", "caseStudy": { "problemKo": "신경망이 동작한다는 그래프만으로는 사용자가 무엇을 할 수 있는지, 그리고 AI의 기억·예측이 실제 플레이를 어떻게 바꾸는지 체감하기 어려웠습니다.", "problemEn": "Neural telemetry alone did not make it obvious what a player could do with the system or how prediction and memory changed an actual interaction.", - "decisionKo": "예측을 사용자 입력 전에 잠그는 3레인 보스전을 만들고 미학습·고정 사전학습·온라인 적응 모델을 같은 회피 기록으로 비교했습니다. 이어 플레이로 변한 102개 예측 가중치만 호환 보스 chassis로 옮기는 기억 카트리지와 게임 소유 action budget을 분리했습니다.", - "decisionEn": "I built a three-lane boss fight that commits predictions before player input, compares fresh, frozen-pretrained and online-adaptive models on the same dodge trace, and separates game-owned action budgets from a 102-weight predictor memory cartridge that can move only between compatible boss chassis.", - "evidenceKo": "공개 production은 `/boss`, `/demo`, `/evaluation`을 외부 AI API 없이 실행합니다. SENTINEL의 실제 Chrome QA는 합법적인 키 입력으로 10회 반격 승리·무조작 패배를 모두 재현했고, 기억 카트리지는 SENTINEL에서 WRAITH로 이동 후 HP·라운드는 초기화되면서 예측 가중치만 유지됐습니다. MaleCNS 별도 평가에서는 최종 프레임만 30/90(33.3%), 36개 calibrated optic cell의 시간 상태+111개 외부 readout 파라미터가 66/90(73.3%)였으며 connectome weight SHA는 전후 동일했습니다.", - "evidenceEn": "The public production runs `/boss`, `/demo` and `/evaluation` without an external AI API. Real Chrome QA records a legitimate 10-counter SENTINEL victory and an unattended defeat; a saved memory cartridge moves from SENTINEL to WRAITH while HP and round state reset and only predictor weights persist. In a separate MaleCNS test, final-frame-only scoring is 30/90 (33.3%) while temporal state from 36 calibrated optic cells plus a 111-parameter external readout reaches 66/90 (73.3%); the connectome-weight SHA is unchanged before and after.", - "resultKo": "결과는 단순 AI 데모가 아니라 플레이 가능한 3D 시스템, 재현 가능한 평가, 명시적 권한 경계, 기억 이식 실험과 고정 connectome readout 연구를 한 공개 케이스 스터디로 묶은 것입니다.", - "resultEn": "The result is a public case study that joins a playable 3D system with reproducible evaluation, explicit action boundaries, compatible memory transfer, and fixed-connectome readout experiments instead of presenting a neural model as a black-box demo." + "decisionKo": "예측을 사용자 입력 전에 잠그는 3레인 보스전을 만들고 미학습·고정 사전학습·온라인 적응 모델을 같은 회피 기록으로 비교했습니다. 이어 플레이로 변한 102개 예측 가중치만 호환 보스 chassis로 옮기는 기억 카트리지와 게임 소유 action budget을 분리했습니다. 후속 NPC 실험에서는 이동·시야·세계 이벤트·허용된 의도·NPC 위치를 브라우저의 게임 엔진이 결정하게 하고, 규칙 컨트롤러는 제한된 상위 행동만 제안하도록 분리했습니다.", + "decisionEn": "I built a three-lane boss fight that commits predictions before player input, compares fresh, frozen-pretrained and online-adaptive models on the same dodge trace, and separates game-owned action budgets from a 102-weight predictor memory cartridge that can move only between compatible boss chassis. A later NPC experiment keeps player movement, sight, world events, permitted intent, and NPC motion inside the authoritative local-browser simulation; the controller only proposes bounded high-level actions.", + "evidenceKo": "공개 production은 `/boss`, `/demo`, `/evaluation`을 외부 AI API 없이 실행합니다. SENTINEL의 실제 Chrome QA는 합법적인 키 입력으로 10회 반격 승리·무조작 패배를 모두 재현했고, 기억 카트리지는 SENTINEL에서 WRAITH로 이동 후 HP·라운드는 초기화되면서 예측 가중치만 유지됐습니다. MaleCNS 별도 평가에서는 최종 프레임만 30/90(33.3%), 36개 calibrated optic cell의 시간 상태+111개 외부 readout 파라미터가 66/90(73.3%)였으며 connectome weight SHA는 전후 동일했습니다. 2026-10-13 BVAT-37의 공개 /npc 데모는 소스 테스트 200/200과 로컬·운영 Chromium 데스크톱/모바일 QA를 통과했습니다. 목격된 첫 절도는 경고, 두 번째는 추격으로 이어지는 규칙 동작을 검증했고, 배포 커밋 일치와 브라우저 오류 0건을 기록했습니다.", + "evidenceEn": "The public production runs `/boss`, `/demo` and `/evaluation` without an external AI API. Real Chrome QA records a legitimate 10-counter SENTINEL victory and an unattended defeat; a saved memory cartridge moves from SENTINEL to WRAITH while HP and round state reset and only predictor weights persist. In a separate MaleCNS test, final-frame-only scoring is 30/90 (33.3%) while temporal state from 36 calibrated optic cells plus a 111-parameter external readout reaches 66/90 (73.3%); the connectome-weight SHA is unchanged before and after. BVAT-37 on 2026-10-13 adds a verified playable /npc public demo: 200/200 source tests, local and deployed Chromium desktop/mobile checks, and deterministic first-warning / second-pursuit witnessed-theft behavior. Production /npc and its source commit identity were verified; zero JavaScript errors were reported in the dated run.", + "resultKo": "결과는 단순 AI 데모가 아니라 플레이 가능한 3D 시스템, 재현 가능한 평가, 명시적 권한 경계, 기억 이식 실험과 고정 connectome readout 연구를 한 공개 케이스 스터디로 묶은 것입니다. NPC 실험은 단일 규칙 기반 브라우저 시뮬레이션으로, 학습된 사회적 기억·LLM 대화·실제 멀티플레이 권한이나 사람의 재미 검증을 뜻하지 않습니다.", + "resultEn": "The result is a public case study that joins a playable 3D system with reproducible evaluation, explicit action boundaries, compatible memory transfer, and fixed-connectome readout experiments instead of presenting a neural model as a black-box demo. The NPC experiment is a single rule-based, session-local browser toy—not learned social memory, LLM dialogue, real multiplayer authority, or human-validated game quality." } } ] diff --git a/content/verified-demos.json b/content/verified-demos.json new file mode 100644 index 0000000..6a7ff8f --- /dev/null +++ b/content/verified-demos.json @@ -0,0 +1,23 @@ +{ + "schemaVersion": 1, + "demos": [ + { + "project": "brain-vat-siege", + "verifiedAt": "2026-10-13", + "sourceCommit": "854213620980fe9c62ea72c12c8d58ec93c9c2e9", + "deploymentStatus": "public", + "demoUrl": "https://brain-vat-siege.vercel.app/npc", + "image": "/images/projects/brain-vat-npc-production.webp", + "titleEn": "NPC Living World — witnessed actions change the guard", + "titleKo": "NPC Living World — 목격한 행동에 따라 달라지는 경비", + "descriptionEn": "Playable Three.js example: a deterministic, rule-based guard receives filtered observations, warns after the first witnessed theft, and pursues after the second. The local-browser game engine remains authoritative for movement, events, collision, and allowed NPC intents.", + "descriptionKo": "직접 조작할 수 있는 Three.js 데모입니다. 규칙 기반 경비 NPC는 제한된 관측만 사용하며 첫 목격 절도에는 경고, 두 번째에는 추격합니다. 이동·이벤트·충돌·NPC 행동 허용 여부는 브라우저의 게임 엔진이 결정합니다.", + "testLineEn": "200/200 source tests; October 13 desktop/mobile production Chrome QA passed with no recorded JS errors.", + "testLineKo": "소스 테스트 200/200, 10월 13일 실제 운영 데스크톱·모바일 Chrome QA 통과 및 JS 오류 기록 없음.", + "caveatEn": "This is one deterministic NPC in a browser sandbox. It has no trained policy, LLM, generative dialogue, persistent social memory, real multiplayer authority, or human-validated play quality.", + "caveatKo": "브라우저 샌드박스의 규칙 기반 NPC 1명입니다. 학습된 정책·LLM·생성형 대화·영구 사회적 기억·실제 멀티플레이 권한·사람의 게임 재미 검증을 갖춘 것은 아닙니다.", + "captureNoteEn": "Cropped and resized from the actual 2026-10-13 public-production Chrome screenshot; source retained in the MAIN PC's BVAT-37 QA record. No private test data was used.", + "captureNoteKo": "2026-10-13 실제 공개 운영 Chrome 캡처를 위쪽 화면 중심으로 잘라 최적화했습니다. 원본은 MAIN PC BVAT-37 QA 기록에 보존되어 있으며 비공개 테스트 데이터는 사용하지 않았습니다." + } + ] +} diff --git a/docs/reviews/2026-10-13-portfolio-refresh-audit.md b/docs/reviews/2026-10-13-portfolio-refresh-audit.md new file mode 100644 index 0000000..3c8973f --- /dev/null +++ b/docs/reviews/2026-10-13-portfolio-refresh-audit.md @@ -0,0 +1,81 @@ +# WritingDeveloper — production-to-source refresh audit (2026-10-13 PT) + +**Scope:** public `https://writingdeveloper.blog`, 4080 MAIN portfolio source and companion projects, Notebook project evidence, GitHub PRs/CI, Soursea FOLIO Plane board. + +**Important status:** This document records observations and candidate code changes. **It does not approve or assert a Vercel production deployment**. Current live site serves the earlier release, while the updates live in draft PR #34 stacked on draft security PR #33. + +## Priority answer + +**Release verified work before adding more projects.** The most expensive present defect is the broken résumé. Second is the unapproved dependency-security update. Third is stale/ambiguous project claims. Shipping ten more experimental projects would not fix the basic ability of a recruiter or customer to verify the work and contact its author. + +## 1. Public availability, links and navigation + +- Public `/`, `/en`, `/hire`, `/en/hire`, `/projects`, `/en/projects`, Studio, Blog, robots, sitemap and machine-readable pages returned HTTP 200 at review. +- All **three public résumé PDFs returned HTTP 404**: + - `/resume/Sihyeong-Lee-Resume.pdf` + - `/resume/Sihyeong-Lee-Resume-DevEx.pdf` + - `/resume/Sihyeong-Lee-Resume-FDE.pdf` +- The full discovery sweep evaluated **64 raw targets**: 57 HTTP 200, six 404 and one timeout. Three 404s belonged to private GitHub repositories whose source URLs are deliberately not shown as public links. Do **not** call those three customer-visible broken links. +- Permanent `npm run audit:public-links` now filters the public surface: **56 targets, 52 reachable, 3 internal PDF 404, 0 external HTTP errors, 1 inconclusive**. The inconclusive domain is `https://kindling.writingdeveloper.blog`, which timed out on both a Python 11-second read and independent 22-second GET/15-second HEAD. This does **not** establish a permanent shutdown. Recheck origin/DNS/health and stop advertising availability if it remains unreachable. +- Audit report is stored in ignored `.qa/portfolio/public-link-audit-latest.json`. Run `npm run audit:public-links -- --all-projects` for both-locale detail routes as well. It is read-only; internal HTTP 400+ produces a failing exit so it cannot be casually described as green. Externally blocked requests are separately reported as warnings. +- The live sitemap's XML contains 220 `loc` values, **including image URLs and alternate links**. Do not interpret that as 220 unique indexable pages or SEO reach. + +## 2. GitHub/release state + +- GitHub public `main` continues to serve the older production source. A direct HTTP `Server: Vercel` response establishes Vercel as the public serving layer, not Notebook as the website origin. +- [PR #33](https://github.com/writingdeveloper/portfolio/pull/33) upgrades Next.js and repairs a lockfile; [PR #34](https://github.com/writingdeveloper/portfolio/pull/34) stacks 4080 evidence, localized UX, DevDeck failure case and now the October project corrections on it. Both are **draft, unmerged**. +- Latest observed `npm audit --omit=dev --audit-level=high` remains nonzero, **three High entries**, due to unpatched `braces` inherited via `@keystatic/next → chokidar`. The latest compatible `braces@3.0.3` was **not** an upstream fix. `npm audit fix --force` would downgrade Keystatic incompatibly. Do not globally disable the audit or call those risks accepted without explicit scope, owner and expiry. +- An independent Dependabot [PR #35](https://github.com/writingdeveloper/portfolio/pull/35) was created for `brace-expansion@1.1.21`; its GitHub CI failed in `npm ci`. That is **not** the same `braces` problem and cannot silently unblock #33. +- On the source preview in prior sessions, TypeScript, lint, format, unit tests, images, actual Playwright EN/KO mobile/desktop/light/dark and all three local résumé file hashes have passed. Each new source commit needs its own final CI read-back before release. +- **FOLIO-45** owns security decisions; **FOLIO-36** owns editorial PDF acceptance, merge, Vercel production, rollback and real public link/hash/CTA smoke QA. Neither is Done. + +## 3. Content accuracy — what was updated in draft PR #34 + +| Item | Prior issue | Verified evidence as of this audit | Candidate action | +|---|---|---|---| +| **BRAIN//VAT** | `updatedAt=2026-09-23` and no NPC experiment | Local git `8542136` / `d28291e`, BVAT-37 2026-10-13 public production Chrome desktop/mobile PASS, Node 200/200, deterministic rule guard. Live `/npc` 200 | Date set to Oct 13; descriptions/evidence updated to distinguish a rule-based single NPC from any learned model, LLM or multiplayer engine. Added optimized public-production Chrome screenshot and demo panel | +| **Creator OS product** | Ledger said OAuth unfinished, obscuring restricted public pilot | Notebook `creator-learning-os/docs/qa/2026-10-06-public-activation.md` records real allowed-test-user Google identity + separate YouTube consent, AOP/TLS trust boundary; Oct 8 bounded deterministic report, email and recovery check. `https://creator.writingdeveloper.blog/demo` returns 200 anonymously | Clarified Testing-only external pilot, free public no-login demo, not general paid sign-up nor model-powered generation; date Oct 8 | +| **Creator OS engineering** | Two separate entries looked like two products | Same product, different engineering/release case, with operator gated public pilot | Named `Creator OS — Release Engineering`, explains shared product lineage; not two SaaS companies | +| **Soursea** | Local personal sourcing tool could be mistaken for company product | `soursea-site/docs/FACTS.md` explicitly excludes the personal Electron sourcing tool from Soursea LLC customer catalog | Renamed `Soursea — Personal Sourcing Workspace` and labeled private/noncommercial product | +| **Studio** | Highly technical listing has no updatedAt and no four-field case study; strong model-count wording relies on older tests | Notebook `studios` monorepo README, latest `studios-wt-orbit` worktree and QA backlog document ongoing changes, including test isolation lessons; not yet canonical merged proof | **Do not claim new experimental branch models or results are released.** Stage a dated architecture/QA case study only after checking canonical main, ComfyUI runtime, current 5 modalities and redacted screenshots | +| **MingleStage** | Entirely absent from 48-entry catalogue despite Soursea LLC early access | Live home and `/app/` HTTP 200; company fact ledger calls it Early Access. Prior FOLIO-33 decision expressly deferred a launched case study pending stable anonymous/guest room and media/cross-client proof | Keep **FOLIO-33 gate**; if passes, add `building / early access` with synthetic screenshots, not `launched` or user/revenue metrics | +| **STRATA / RailForge / Music-MV Studio** | Many current uncommitted or research-only efforts | MAIN git `project-strata` 2026-10-06, `railforge` 2026-09-29; Notebook music-mv README. Runtime/vertical slice and H3 binding remain acceptance gates | Keep `building/private`. Update after real accepted gameplay/workflow demonstration, not based on file counts | +| **Other recent code** | Personal OpenMontage/Wan meme, Roblox avatar and private media experiments | MAIN local commits and experiments exist | Do not indiscriminately promote. Publish only with permission, licensing/privacy review and a reproducible technical claim | + +## 4. Editorial and information architecture + +- There are **48 entries**, of which **36 have no verified `updatedAt`**. This is an evidence gap, not license to fabricate dates. Date only when a dated immutable source or production acceptance exists. +- Retain **five curated selected-work items** to communicate different skills, rather than placing 48 equally above the fold. Strongest evidence-led hooks: DevDeck user-visible state repair; citefirst retrieval denominator and caveat; BRAIN//VAT interactive public verification; Creator OS release gate; Studio after fresh artifact QA. +- If introducing a new post, choose one carefully documented real failure or release decision rather than another AI-framework roundup. Current candidate includes September 22's bilingual agent-ownership blog post; public last highlighted post had been August 27. +- Audit the first-screen Hire conversion path after the final deployment. The public site currently breaks the résumé, which overwhelms improvements to aesthetics and metadata. +- Cross-link `soursea.io` and the individual portfolio with explicit **personal vs LLC** distinction. Do not describe the personal sourcing desktop as a live Soursea product. +- Do not claim model-generated work is a customer outcome. Label deterministic rules and simulated NPCs correctly; distinguish skipped tests, historical QA, local preview and production. +- Public text remains bilingual; invalid localized page links, dead images, 404 PDF CTAs and accessibility regressions should be caught by Playwright. + +## 5. Proposed follow-up order and Plane mapping + +1. **P0 · FOLIO-45**: resolve/upstream-patch the actual `braces` transitive vulnerability, prove clean Linux/Windows CI. A time-limited explicit security-risk decision is a separate authorization, not assumed. +2. **P0 · FOLIO-36**: owner reviews résumé snapshots and claims; merge #33/#34 through their required gates, deploy to Vercel, verify public HTTP 200/application/pdf/SHA for all three PDF versions plus contact CTA/mobile/EN-KO/rollback. +3. **P1 · FOLIO-51 (new)**: retain repeatable public-link health checks, investigate Kindling origin timeouts and after-release public résumé health. Do not conflate private GitHub 404s with public broken links. +4. **P1 · FOLIO-46**: source-backed project curation, including Oct 13 BRAIN//VAT NPC and Creator OS restricted pilot; next Studio current canonical verification and proof-led case study. +5. **P1 · FOLIO-33**: evaluate MingleStage as a *labelled early-access* case only once real anonymous/guest, media and mobile/cross-client gates pass. Historical pilot notes are not unconditional launch proof. +6. **P2 · FOLIO-48**: capture same-host Lighthouse and performance budgets after preview/production alignment; make projects catalogue lighter and assess proof-card scroll depth. Prior 509 KB public-vs-485 KB local decoded HTML is a noncontrolled comparison, not a field LCP win. +7. **P2 · FOLIO-35/49**: revisit specific target job/contract descriptions and portfolio's real conversion evidence in December. Do not publish vague AI productivity percentages. + +No unrelated projects were restarted, the 4080 original WIP checkout remains preserved, and Notebook worktrees were inspected read-only. A source preview build is not live production, and production was not modified by this audit. +## 2026-10-13 same-day verification addendum + +### Automated candidate QA + +- Next.js 16.4.0 candidate: TypeScript, ESLint, Prettier, 244/244 unit tests across 26 files, evidence checks, all versioned résumé PDF bytes, and 11/11 bilingual posts PASS. Production build PASS with 148/148 static-generation tasks. +- Production-mode preview on localhost: Chromium EN/KO x 1440/390px x dark/light 8/8 PASS, DevDeck historical failure case both locales, BRAIN//VAT NPC screenshot/live link plus its explicit no-trained-policy disclaimer, Creator OS Testing-only restriction and its anonymous public demo in both locales, all 3 local PDFs with correct SHA-256 and MIME. +- The new per-locale NPC/Creator browser probe initially shared a page between locales and produced a stale-language assertion. A fresh Chromium context per locale resolved that QA harness issue without weakening the assertions. Both separately loaded pages contained the correct training limitation. +- Public-link audit against local preview: 56 reachable / 0 broken / 0 uncertain. This is not a claim that public production résumé PDFs are fixed. Production and preview JSON reports are retained separately under ignored .qa/portfolio/. + +### Intermittent Kindling response + +- Early audit attempts timed out (11-second Python/Node, 22-second GET and 15-second HEAD), but a later independent check of the same external domain returned HTTP 200 in 5.7 seconds. This is intermittent accessibility from the review host, not proof of permanent shutdown. Recheck from a second network before altering the published link. + +### Release guard + +- The unresolved production braces advisory remains unapproved. Changes are confined to the candidate draft PR, not public production. The current external pilot is Testing-only and the BRAIN//VAT NPC is deterministic, not trained or LLM-driven. diff --git a/package.json b/package.json index 8d6a179..53b26da 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "evidence:check": "tsx scripts/evidence.mts", "evidence:collect": "tsx scripts/evidence.mts --collect", "evidence:verify": "tsx scripts/evidence.mts --verify-local", - "qa:portfolio": "tsx scripts/qa-portfolio.mts" + "qa:portfolio": "tsx scripts/qa-portfolio.mts", + "audit:public-links": "tsx scripts/audit-public-links.mts" }, "dependencies": { "@keystatic/core": "^0.5.48", diff --git a/public/images/projects/brain-vat-npc-production.webp b/public/images/projects/brain-vat-npc-production.webp new file mode 100644 index 0000000000000000000000000000000000000000..af52769175a6b2add46dff2c4a857c3a4e5bf0f3 GIT binary patch literal 58598 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%0AR$XC0%g3vF(QIxC?p+VrmLAlWhZb;D-o-f)T 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νwrCt7b`_?rK8)DQ)9ctRCA-n57fvNml}DX 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 Tr<+eaBhhVWSLt(a`cMD>l}jnT literal 0 HcmV?d00001 diff --git a/scripts/audit-public-links.mts b/scripts/audit-public-links.mts new file mode 100644 index 0000000..fe7b58d --- /dev/null +++ b/scripts/audit-public-links.mts @@ -0,0 +1,122 @@ +import fs from 'node:fs' +import path from 'node:path' +import projects from '../content/projects.json' + +interface Target { + kind: 'route' | 'demo' | 'public-source' + id: string + url: string +} +interface Result extends Target { + status: number | null + resolvedUrl?: string + error?: string + elapsedMs: number +} + +const origin = (process.env.PORTFOLIO_AUDIT_ORIGIN || 'https://writingdeveloper.blog').replace(/\/$/, '') +const includeAllProjects = process.argv.includes('--all-projects') +const internalRoutes = [ + '/', + '/en', + '/hire', + '/en/hire', + '/projects', + '/en/projects', + '/blog', + '/en/blog', + '/studio', + '/en/studio', + '/robots.txt', + '/sitemap.xml', + '/llms.txt', + '/resume/Sihyeong-Lee-Resume.pdf', + '/resume/Sihyeong-Lee-Resume-DevEx.pdf', + '/resume/Sihyeong-Lee-Resume-FDE.pdf', + '/projects/devdeck', + '/en/projects/devdeck', + '/projects/brain-vat-siege', + '/en/projects/brain-vat-siege', + '/projects/creator-learning-os', + '/en/projects/creator-learning-os', +] +const urls: Target[] = internalRoutes.map((id) => ({ kind: 'route', id, url: origin + id })) +if (includeAllProjects) { + for (const project of projects.projects) { + for (const lang of ['', '/en']) { + urls.push({ + kind: 'route', + id: lang + '/projects/' + project.slug, + url: origin + lang + '/projects/' + project.slug, + }) + } + } +} +for (const project of projects.projects) { + if (project.website) urls.push({ kind: 'demo', id: project.slug, url: project.website }) + // Private source URLs are never linked to the user. An unauthenticated 404 + // from a private GitHub repository is NOT evidence of a broken public CTA. + if (project.github && !project.private) urls.push({ kind: 'public-source', id: project.slug, url: project.github }) +} +const seen = new Set() +const targets = urls.filter((item) => { + if (seen.has(item.url)) return false + seen.add(item.url) + return true +}) + +async function check(item: Target): Promise { + const start = performance.now() + const result: Result = { ...item, status: null, elapsedMs: 0 } + try { + const response = await fetch(item.url, { + redirect: 'follow', + headers: { 'user-agent': 'Mozilla/5.0 (PortfolioLinkQA; review-only)' }, + signal: AbortSignal.timeout(11000), + }) + result.status = response.status + result.resolvedUrl = response.url + await response.body?.cancel() + } catch (error) { + result.error = error instanceof Error ? error.message : String(error) + } + result.elapsedMs = Math.round(performance.now() - start) + return result +} + +const results: Result[] = [] +let index = 0 +await Promise.all( + Array.from({ length: 8 }, async () => { + while (index < targets.length) { + const item = targets[index++] + results.push(await check(item)) + } + }) +) +const brokenInternal = results.filter((r) => r.kind === 'route' && r.status !== null && r.status >= 400) +const externalProblems = results.filter((r) => r.kind !== 'route' && r.status !== null && r.status >= 400) +const uncertain = results.filter((r) => r.status === null) +const summary = { + checkedAt: new Date().toISOString(), + origin, + source: 'candidate project ledger; read-only HTTP headers, not functional browser QA', + checked: results.length, + ok: results.filter((r) => r.status !== null && r.status < 400).length, + brokenInternal: brokenInternal.length, + externalProblems: externalProblems.length, + uncertain: uncertain.length, + results: results.sort((a, b) => a.kind.localeCompare(b.kind) || a.id.localeCompare(b.id)), +} +const directory = path.resolve('.qa/portfolio') +fs.mkdirSync(directory, { recursive: true }) +const file = path.join(directory, 'public-link-audit-latest.json') +fs.writeFileSync(file, JSON.stringify(summary, null, 2) + '\n') +console.log( + `Checked ${summary.checked} URLs: ${summary.ok} reachable, ${summary.brokenInternal} broken internal, ${summary.externalProblems} external HTTP errors, ${summary.uncertain} inconclusive` +) +for (const row of [...brokenInternal, ...externalProblems, ...uncertain]) { + console.log(`[${row.status ?? 'unknown'}] ${row.kind} ${row.id} ${row.url} ${row.error || ''}`) +} +console.log('Evidence:', file) +if (brokenInternal.length) process.exitCode = 1 diff --git a/scripts/qa-portfolio.mts b/scripts/qa-portfolio.mts index 5d94583..4d5f976 100644 --- a/scripts/qa-portfolio.mts +++ b/scripts/qa-portfolio.mts @@ -174,6 +174,44 @@ try { console.log('PASS INCIDENT', route, 'before/after images, 6 source links, scope') await incidentCtx.close() } + for (const prefix of ['', '/en']) { + const freshContext = await browser.newContext() + const freshPage = await freshContext.newPage() + const npcRoute = prefix + '/projects/brain-vat-siege' + const npcResponse = await freshPage.goto(base + npcRoute, { waitUntil: 'networkidle', timeout: 30000 }) + assert(npcResponse?.ok(), 'BRAIN//VAT project route unavailable') + const npcEvidence = freshPage.locator('#verified-demo') + assert(await npcEvidence.isVisible(), 'Verified NPC demo missing') + const liveNpc = npcEvidence.locator('a[href="https://brain-vat-siege.vercel.app/npc"]') + assert((await liveNpc.count()) === 1, 'NPC live demonstration link missing') + const npcImage = npcEvidence.locator('img') + await npcImage.scrollIntoViewIfNeeded() + assert( + await npcImage.evaluate((node) => node instanceof HTMLImageElement && node.complete && node.naturalWidth > 0), + 'Real NPC production screenshot did not load' + ) + const npcText = await npcEvidence.innerText() + assert(npcText.includes('200/200'), 'NPC test-count evidence missing') + assert(npcText.includes(prefix ? 'no trained policy' : '학습된 정책'), 'Missing NPC limitation at ' + npcRoute) + results.push({ route: npcRoute, verifiedDemo: true, screenshotLoaded: true }) + console.log('PASS VERIFIED DEMO', npcRoute) + + const creatorRoute = prefix + '/projects/creator-learning-os' + const creatorResponse = await freshPage.goto(base + creatorRoute, { waitUntil: 'networkidle' }) + assert(creatorResponse?.ok(), 'Creator OS pilot product detail unavailable') + assert( + (await freshPage.locator('a[href="https://creator.writingdeveloper.blog/demo"]').count()) >= 1, + 'Creator OS no-login public demo missing' + ) + const creatorDescription = await freshPage.locator('header').last().innerText() + assert( + creatorDescription.includes(prefix ? 'Testing-only' : '승인된 테스트 사용자'), + 'Creator OS pilot access restrictions missing' + ) + results.push({ route: creatorRoute, pilotStatus: 'testing-only', demoLinked: true }) + console.log('PASS CREATOR PILOT', creatorRoute) + await freshContext.close() + } for (const file of resumes.files) { const r = await ctx.request.get(base + '/resume/' + file.file) assert(r.ok() && r.headers()['content-type']?.includes('application/pdf'), 'PDF response invalid') diff --git a/src/app/[locale]/projects/[slug]/page.tsx b/src/app/[locale]/projects/[slug]/page.tsx index 3ddcb9b..438c6fb 100644 --- a/src/app/[locale]/projects/[slug]/page.tsx +++ b/src/app/[locale]/projects/[slug]/page.tsx @@ -13,6 +13,7 @@ import { getAllPosts } from '@/lib/mdx' import { buildProjectPostMap } from '@/lib/post-project-links' import { PageTransition } from '@/components/ui/PageTransition' import { FailureInvestigation } from '@/components/projects/FailureInvestigation' +import { VerifiedProjectDemo } from '@/components/projects/VerifiedProjectDemo' import { generateBreadcrumbJsonLd, generateProjectJsonLd, safeJsonLd, toAbsoluteUrl } from '@/lib/seo' const PROJECTS = projectsData.projects as Project[] @@ -224,6 +225,8 @@ export default async function ProjectDetailPage({ params }: { params: Promise<{
)} + +
diff --git a/src/components/projects/VerifiedProjectDemo.tsx b/src/components/projects/VerifiedProjectDemo.tsx new file mode 100644 index 0000000..822444a --- /dev/null +++ b/src/components/projects/VerifiedProjectDemo.tsx @@ -0,0 +1,68 @@ +import Image from 'next/image' +import demos from '../../../content/verified-demos.json' + +/** A dated, externally usable demonstration, with its measurement limits attached. */ +export function VerifiedProjectDemo({ projectSlug, locale }: { projectSlug: string; locale: string }) { + const item = demos.demos.find((demo) => demo.project === projectSlug) + if (!item) return null + const ko = locale === 'ko' + return ( +
+
+
+ + {ko ? '실제 운영 검증 데모' : 'Verified public demonstration'} + + + + +
+

+ {ko ? item.titleKo : item.titleEn} +

+

+ {ko ? item.descriptionKo : item.descriptionEn} +

+ + {ko ? '공개 NPC 데모 직접 실행' : 'Try the live NPC demonstration'} ↗ + +
+
+ {ko +
+ {ko ? item.captureNoteKo : item.captureNoteEn} +
+
+
+
+

{ko ? '검증된 범위' : 'What passed'}

+

+ {ko ? item.testLineKo : item.testLineEn} +

+
+
+

{ko ? '아직 증명하지 않은 범위' : 'What was not validated'}

+

+ {ko ? item.caveatKo : item.caveatEn} +

+
+
+
+ ) +} diff --git a/src/lib/__tests__/portfolio-freshness-20261013.test.ts b/src/lib/__tests__/portfolio-freshness-20261013.test.ts new file mode 100644 index 0000000..82209fc --- /dev/null +++ b/src/lib/__tests__/portfolio-freshness-20261013.test.ts @@ -0,0 +1,64 @@ +import { statSync } from 'node:fs' +import { join } from 'node:path' +import { describe, expect, it } from 'vitest' +import projects from '../../../content/projects.json' +import type { Project } from '@/types/content' +import demos from '../../../content/verified-demos.json' + +const project = (slug: string) => (projects.projects as Project[]).find((value) => value.slug === slug) + +describe('verified portfolio refresh: 2026-10-13', () => { + it('references the actual October 13 public BRAIN//VAT NPC proof, not an LLM claim', () => { + const brain = project('brain-vat-siege') + const item = demos.demos.find((entry) => entry.project === 'brain-vat-siege') + expect(brain?.updatedAt).toBe('2026-10-13') + expect(brain?.status).toBe('active') + expect(brain?.descriptionEn).toContain('deterministic rule-driven') + expect(brain?.caseStudy?.evidenceEn).toContain('200/200') + expect(item).toBeDefined() + expect(item?.sourceCommit).toBe('854213620980fe9c62ea72c12c8d58ec93c9c2e9') + expect(item?.verifiedAt).toBe('2026-10-13') + expect(item?.demoUrl).toBe('https://brain-vat-siege.vercel.app/npc') + expect(item?.descriptionEn).toContain('rule-based') + expect(item?.caveatEn).toContain('no trained policy') + expect(item?.caveatKo).toContain('학습된 정책') + expect(statSync(join(process.cwd(), 'public', item!.image.slice(1))).size).toBeGreaterThan(10000) + }) + + it('describes Creator OS as a testing-only external pilot rather than an unreleased OAuth prototype', () => { + const pilot = project('creator-learning-os') + expect(pilot?.updatedAt).toBe('2026-10-08') + expect(pilot?.private).toBe(true) + expect(pilot?.status).toBe('building') + expect(pilot?.website).toBe('https://creator.writingdeveloper.blog/demo') + expect(pilot?.descriptionEn).toContain('Testing-only') + expect(pilot?.descriptionEn).toContain('not unrestricted signup') + expect(pilot?.descriptionKo).toContain('승인된 테스트 사용자') + expect(pilot?.caseStudy?.evidenceEn).toContain('without a provider model call') + }) + + it('marks Creator OS product and release-hardening entry as two views of one product', () => { + const product = project('creator-learning-os') + const engineering = project('creator-os') + expect(product?.name).toContain('Product & External Pilot') + expect(engineering?.name).toContain('Release Engineering') + expect(engineering?.descriptionEn).toContain('same Creator OS product') + expect(engineering?.caseStudy?.resultKo).toContain('두 번째 제품이 아닌') + }) + + it('does not present the personal Soursea sourcing tool as an offered LLC product', () => { + const tool = project('soursea') + expect(tool?.private).toBe(true) + expect(tool?.website).toBeUndefined() + expect(tool?.name).toContain('Personal Sourcing Workspace') + expect(tool?.descriptionKo).toContain('고객용 서비스 목록과 별개') + }) + + it('leaves unverified updatedAt fields unknown rather than inventing dates', () => { + for (const p of projects.projects as Project[]) { + if (p.updatedAt) expect(p.updatedAt).toMatch(/^20\d{2}-\d{2}-\d{2}$/) + } + expect(project('studios')?.updatedAt).toBeUndefined() + expect(project('kindling')?.updatedAt).toBeUndefined() + }) +}) diff --git a/src/lib/__tests__/projects.test.ts b/src/lib/__tests__/projects.test.ts index 525d880..a494f92 100644 --- a/src/lib/__tests__/projects.test.ts +++ b/src/lib/__tests__/projects.test.ts @@ -262,14 +262,15 @@ describe('2026-10 verified source-backed research entries', () => { describe('2026-09 ledger refresh', () => { const ledger = projectsData.projects as Project[] - it('adds Creator Learning OS to the ledger without pretending it has shipped', () => { + it('shows Creator OS as a restricted external pilot with a public read-only demo, not a paid launch', () => { expect(ledger).toHaveLength(48) const creator = ledger.find((project) => project.slug === 'creator-learning-os') expect(creator).toBeDefined() expect(creator?.status).toBe('building') expect(creator?.private).toBe(true) - expect(creator?.website).toBeUndefined() - expect(creator?.caseStudy?.evidenceEn).toBeTruthy() + expect(creator?.website).toBe('https://creator.writingdeveloper.blog/demo') + expect(creator?.descriptionEn).toContain('Testing-only') + expect(creator?.caseStudy?.evidenceEn).toContain('without a provider model call') }) it('adds BRAIN//VAT as a public demo without exposing a private repo', () => {
+ + {locale === 'ko' ? '사례와 검증 보기' : 'Case study & evidence'} → + {project.website && ( - AI-NATIVE PRODUCT ENGINEER + AI-NATIVE PRODUCT · AGENT SYSTEMS ENGINEER LEDGER NO. 001 @@ -294,11 +301,28 @@ export function LedgerHome({

{locale === 'ko' - ? `AI 네이티브 제품과 개발 인프라를 설계·배포·운영합니다. 에이전트 도구, RAG 평가, 로컬 GPU 생성 파이프라인, 프로덕션 풀스택 시스템까지 직접 책임집니다.` - : `I design, ship, and operate AI-native products and developer infrastructure — from agent tooling and RAG evaluation to local GPU generation pipelines and production full-stack systems.`} + ? `에이전트가 실제 시스템에서 일하도록 만드는 AI 네이티브 제품을 설계·배포·운영합니다. MCP·툴 사용, eval, RAG, 로컬 GPU 파이프라인, 프로덕션 풀스택 인프라까지 직접 책임집니다.` + : `I build the systems that let AI agents do real work: MCP and tool use, evals, RAG, developer tooling, local GPU pipelines, and production full-stack infrastructure.`}

+
+ + {locale === 'ko' ? '경력 · 이력서 보기' : 'Experience & résumé'} → + + + {locale === 'ko' ? 'AI 파이프라인 사례' : 'Inside the AI pipeline'} → + +
+ {/* Stats ribbon */}
{stats.map((s) => ( @@ -355,7 +379,9 @@ export function LedgerHome({