Install any skill in seconds. Free to start, no credit card required.
Get Started Free →화면 전체나 신규 surface를 처음부터 디자인할 때의 진입점 — Discovery→Wireframe→Components→Microcopy→Validation 파이프라인을 omd-master 오케스트레이터로 실행. 트리거: '랜딩페이지', '랜딩 페이지', '랜딩 만들어줘', '홈 화면', '첫 화면', '프로토타입', '그럴싸한', '구색 갖춰', 'first screen', 'first impression', 'landing page', 'landing', 'prototype', 'MVP UI', 'home', 'production-ready', 'wireframe to production', '랜딩 처음부터', 'production-ready', '一からデザイン', '從頭設計'. 자연어 발화('그럴싸한 랜딩 만들어줘', 'MVP UI 잡아줘', '프로토타입이라도 구색 갖춰서')에도 자동 트리거. 단일 컴포넌트 수정은 omd:apply.
.claude/skills/kwakseongjae-omd-harness/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-09 | ✗→✓ | ▲ Improved | 481% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 326% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 285% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 575% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 326% | 0% |
<!-- omd:installed-skill — managed by omd install-skills. Do not edit; rerun the command to refresh. -->
이 스킬은 omd-master 오케스트레이터를 호출하는 단일 진입점이다. 본 스킬은 launcher + 사전체크 + run 디렉토리 부트스트랩 책임만 가지고, phase 로직은 agents/omd-master.md에 있다.
Run 디렉토리 부트스트랩에는 CLI 의존이 없다. Core v2 review/compile/adoption은 설치된 provider-free design-md 명령 또는 byte-equivalent helper만 사용한다.
/omd-harness <task> 명시 호출슬래시에 task 같이 적었으면 (/omd-harness 물 음용 유도 메인 화면) 그 자연어 부분이 task. 빈 슬래시면 한 번 묻기:
어떤 디자인 작업을 진행할까요?
shape: "[도메인] + [톤/스타일] + [핵심 화면]" — 예: "토스 스타일 가족용 식단 앱 메인 화면"task에서 delivery intent도 함께 고정한다.
디자인/와이어프레임/기획/시안만 요청 → delivery_intent: design-only구현/만들어/적용/build/implement/production-ready 포함 → delivery_intent: implementimplement여도 mandatory checkpoint를 건너뛰지 않는다. 차이는 승인된 handoff 뒤 실제 제품 코드 통합까지 이어지는지다.
먼저 Agent 도구의 사용 가능 role 목록에서 omd-master를 확인한다. 있으면 Step 2로 간다. 없을 때는 Markdown을 임의 폴더에 복사하지 않는다. Claude와 Codex의 role schema가 다르고, .agents/는 Codex에서 skill 경로이지 role 경로가 아니다.
.agents/skills/omd-harness/에서 로드됐거나 .codex/agents/omd-master.toml이 있으면 Codex다. role 파일은 .codex/agents/omd-master.toml이어야 하며 top-level name, description, developer_instructions가 모두 있어야 한다..claude/skills/omd-harness/에서 로드됐거나 .claude/agents/omd-master.md가 있으면 Claude Code다. role 파일은 첫 줄이 ---인 .claude/agents/omd-master.md여야 한다..opencode/skills/omd-harness/에서 로드됐거나 .opencode/agents/omd-master.md가 있으면 OpenCode다. project role은 .opencode/agents/omd-master.md, global role은 ~/.config/opencode/agents/omd-master.md이며 mode: subagent여야 한다.role 파일이 없거나 schema가 틀렸으면 해당 채널만 최신 설치기로 복구한다:
bash# <channel> = claude-code, codex 또는 opencode npx oh-my-design-cli@latest install-skills --agent <channel> --all npx oh-my-design-cli@latest doctor
Codex의 legacy .codex/skills OmD entrypoint는 최신 설치기가 안전하게 제거하고 공식 .agents/skills 경로로 옮긴다. 사용자 소유 파일은 삭제하지 않는다.
설치 파일이 유효해도 이미 실행 중인 세션의 Agent 목록은 즉시 갱신되지 않을 수 있다. 이 경우 작업을 중단하거나 잘못된 형식으로 복사하지 말고:
developer_instructions, Claude Code는 frontmatter 뒤 body를 읽는다.역할 파일은 복구됐고, 이번 작업은 inline으로 계속해요. 다음 세션부터 전용 role이 자동 로드됩니다.Step 4에서 전용 role spawn이 여전히 불가능하면 inline persona가 같은 phase/state/checkpoint 계약을 직접 실행한다. 산출물이나 사용자 checkpoint를 생략하지 않는다.
이전엔 omd harness "<task>" --internal CLI를 호출했지만 1.0.0부터는 스킬이 직접 한다. 결정론적 hard verify gate:
bashls -t .omd/runs 2>/dev/null | head -1
출력 있으면 그 디렉토리의 task.md를 Read해서 사용자 task와 의미적으로 일치하는지 확인. 일치하면 그 run 재사용 — Step 3으로 점프.
다음을 반드시 정확히 이 순서로 Bash 툴로 실행:
bash# 2.2.1 — timestamp + slug 결정 (한국어 보존) TS=$(node -e "console.log(new Date().toISOString().replace(/[:.]/g,'-'))") SLUG=$(node -e " const s = process.argv[1].toLowerCase().trim() .replace(/[^a-z0-9가-힣\s-]+/g,'') .replace(/\s+/g,'-') .replace(/-+/g,'-') .replace(/^-|-$/g,''); console.log(s.slice(0,40) || 'untitled'); " "<EXTRACTED_TASK>") RUN_ID="run-${TS}-${SLUG}" RUN_DIR=".omd/runs/${RUN_ID}" # 2.2.2 — 표준 서브폴더 생성 mkdir -p "${RUN_DIR}"/{wireframes,components,assets/briefs,assets/fallback,assets/pinterest-refs,eval/screenshots,persona-feedback,handoff,checkpoints} # 2.2.3 — task.md cat > "${RUN_DIR}/task.md" <<EOF # Harness Task <EXTRACTED_TASK> --- - run_id: \`${RUN_ID}\` - started_at: $(date -u +%Y-%m-%dT%H:%M:%SZ) - cwd: \`$(pwd)\` EOF # 2.2.4 — run.log echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] run initialized" > "${RUN_DIR}/run.log" # 2.2.5 — .omd/.gitignore (idempotent) mkdir -p .omd [ -f .omd/.gitignore ] || printf "runs/\ncache/\n" > .omd/.gitignore # 2.2.6 — INDEX.md (idempotent header + append) INDEX=".omd/runs/INDEX.md" [ -f "${INDEX}" ] || cat > "${INDEX}" <<EOF # Harness Runs Index One line per run. Append-only. EOF TASK_ONELINE=$(echo "<EXTRACTED_TASK>" | tr '\n' ' ' | cut -c1-120) echo "- $(date -u +%Y-%m-%dT%H:%M:%SZ) \`${RUN_ID}\` — ${TASK_ONELINE}" >> "${INDEX}" # 2.2.7 — 결과 출력 (이 스킬이 파싱) echo "RUN_DIR=${RUN_DIR}" echo "RUN_ID=${RUN_ID}"
부트스트랩 다음, master spawn 전에 반드시:
bashtest -d "${RUN_DIR}" && test -f "${RUN_DIR}/task.md" && echo "OK" || echo "FAIL"
OK가 출력되지 않으면 master는 절대 spawn하지 않는다. 사용자에게:
하네스 부트스트랩이 실패했어요 (run dir or task.md 누락). 디스크 권한·경로 문제일 수 있어요. 다시 시도하거나 .omd/ 디렉토리를 정리해주세요.이 gate를 통과해야만 Step 2.5로.
reference를 고르라고 사용자에게 묻기 전에 먼저 레포를 본다. 사용자가 듣고 싶은 첫 문장은 "이 레포 분석했어요 — Next.js 14 + 토스 블루 + 4개 surface" 같은 진단이지 "어느 레퍼런스 골라드릴까요?"가 아니다.
bash# HELPER resolution (먼저 존재하는 것 사용): # 1. .codex/data/scripts/ctx-prime.cjs ← Codex installer copy # 2. .claude/data/scripts/ctx-prime.cjs ← Claude Code / Cursor installer copy # 3. .opencode/data/scripts/ctx-prime.cjs ← OpenCode installer copy # 4. node_modules/oh-my-design-cli/scripts/ctx-prime.cjs (로컬 npm 설치) # 5. $(npm root -g)/oh-my-design-cli/scripts/ctx-prime.cjs (global) HELPER="" for CANDIDATE in \ ".codex/data/scripts/ctx-prime.cjs" \ ".claude/data/scripts/ctx-prime.cjs" \ ".opencode/data/scripts/ctx-prime.cjs"; do if [ -f "$CANDIDATE" ]; then HELPER="$CANDIDATE"; break; fi done if [ -z "$HELPER" ]; then OMD_DIR=$(npm root)/oh-my-design-cli [ -d "$OMD_DIR" ] || OMD_DIR=$(npm root -g)/oh-my-design-cli HELPER="$OMD_DIR/scripts/ctx-prime.cjs" fi [ -f "$HELPER" ] || { echo "CTX_PRIME_MISSING"; exit 0; } node "$HELPER" "$(pwd)" "${RUN_DIR}"
성공 시 ${RUN_DIR}/ctx-prime.json 생성. ~12-50ms (typical repo). ctx-prime.cjs는 활성 host의 .codex/data/scripts/, .claude/data/scripts/, 또는 .opencode/data/scripts/에 installer가 복사하므로 패키지 dir 없이도 동작한다 (companion context.cjs도 같은 폴더에 함께 복사됨).
CTX_PRIME_MISSING (모든 local/global 경로 miss) → Step 3로 직진 (legacy path).
고정된 audience + 4문항을 바로 묻지 않는다. 먼저 design-council-prime.cjs를 ctx-prime.cjs와 같은 resolution order로 찾아 실행한다:
bashCOUNCIL_HELPER="$(dirname "$HELPER")/design-council-prime.cjs" [ -f "$COUNCIL_HELPER" ] && node "$COUNCIL_HELPER" "$(pwd)" "${RUN_DIR}"
council/decision-ledger.json이 생성되면 이것이 intake의 단일 source of truth다. 아래 2.5.2–2.5.3 고정 picker는 실행하지 않는다.
auto이면서 proposed_value가 있는 항목만 prefilled_slots[slot]에 적재.interview 항목만 한 번의 최대 4-question batch로 질문. ledger의options와 reason을 사용하고 근거 없는 추천 표시는 만들지 않는다.
defer는 묻거나 채우지 않고 deferred_slots에 id/slot/reason을 보존.blocked가 하나라도 있으면 진행하지 않고 필요한 evidence/authority만 알림.dispatch-plan.json의 dispatch_suppressed_by_blocked: true는 이미 결정론적으로 blocker가 확인됐다는 뜻이다. blocker가 풀리기 전에는 자문 agent를 호출하지 않는다.
decision_ledger_ref: "council/decision-ledger.json"와 함께 기록.
이 분류를 host가 prose로 다시 구현하지 않는다. council helper와 같은 폴더의 design-council-handoff.cjs를 사용해 checkpoint를 materialize한다:
bashHANDOFF_HELPER="$(dirname "$COUNCIL_HELPER")/design-council-handoff.cjs" [ -f "$HANDOFF_HELPER" ] && node "$HANDOFF_HELPER" "$(pwd)" "${RUN_DIR}" prepare
status: blocked → 질문을 만들지 않고 blocking_items만 사용자에게 알린 뒤 중단.status: ask_user → questions_file의 product-authority 질문만 한 batch로 제시.state: PROPOSE_PLAN → 질문 없이 Step 3으로 진행.checkpoint materialize 직후 같은 helper dir의 context planner를 실행한다:
bashCONTEXT_HELPER="$(dirname "$COUNCIL_HELPER")/design-harness-context-plan.cjs" [ -f "$CONTEXT_HELPER" ] && node "$CONTEXT_HELPER" "$(pwd)" "${RUN_DIR}" relay
${RUN_DIR}/handoff/context-plan.json을 읽고 그대로 따른다. relay_blocked와 relay_questions는 master를 spawn하지 않고 launcher가 기존 artifact를 exact relay한다. resume_master/run_master만 master를 호출하며, sidecars에 적힌 파일만 active channel skill tree에서 추가로 읽는다. planner가 없는 legacy install에서만 master의 내장 conditional pointer를 사용한다. sidecar를 관성적으로 전부 로드하지 않는다.
질문 답은 ${RUN_DIR}/checkpoints/council-intake.answers.json에 저장한다. 답변 객체에는 handoff의 checkpoint_id, ledger_sha256, questions_sha256를 그대로 복사하고 answers 아래 decision id별 응답을 넣는다. 이 receipt가 없거나 현재 ledger/questions hash와 다르면 재질문 없이 fail-close한다. 이후 다음처럼 병합한다. helper는 모든 required interview가 답변됐을 때만 PROPOSE_PLAN을 쓴다.
bashnode "$HANDOFF_HELPER" "$(pwd)" "${RUN_DIR}" apply \ "${RUN_DIR}/checkpoints/council-intake.answers.json"
interview가 0개면 질문 없이 Step 3으로 간다. 이 단계는 deterministic intake 분류이며 multi-agent council이 실행됐다고 표현하지 않는다. helper 누락·실패 때만 아래 legacy path를 사용한다.
기존/current surface의 개선 작업에서 ctx-prime이 confidence 0.75 이상의 audience evidence와 단일 surface를 함께 보유하면 audience와 scope는 값을 새로 확정하지 않고 defer한다. 사용자가 action 변경을 요청하지 않았다면 primary CTA도 같은 surface evidence에 묶어 defer한다. 이 decision들은 council에도 보내지 않는다. 이는 기존 제품 방향과 행동 계약을 보존하는 것이며 unknown을 채우거나 새 사실을 auto하는 규칙이 아니다. root index.html도 하나의 실제 surface로 센다.
council/dispatch-plan.json을 읽는다. dispatch_required: false면 agent를 호출하지 않고 2.5.1b의 ledger를 그대로 사용한다. true면 아래 계약으로 선택된 lane만, 한 번, 최대 2개 병렬 실행한다.
selected_lanes의 role과 decision_ids를 그대로 사용한다. 전체 역할을관성적으로 호출하거나 선택되지 않은 쟁점을 추가하지 않는다.
ownership은 council/lanes/<lane_id>.json이다.
{ "lane_id": "...", "claims": [...] }이고, 각 claim은decision_id, decision_mode, authority_mode, recommendation, reason, evidence를 포함한다.
decision_mode: preserve-existing | choose-new | unknownauthority_mode: preserve-existing | user-answerable | external-unverifiable | unknownpreserve-existing/defer다. 새 제품 결정을 한 것이 아니다.
결정은 choose-new/user-answerable/interview다.
external-unverifiable/blocked다. evidence는 실제 존재하는 repo/run-relative 경로여야 한다. 인용할 근거가 없으면 claim을 만들지 않는다.
의견을 꾸며내지 않는다. 해당 lane에 { "lane_id": "...", "status": "unavailable", "claims": [] }를 쓰고 원래 disposition을 보존한다.
bashRECONCILE_HELPER="$(dirname "$COUNCIL_HELPER")/design-council-reconcile.cjs" [ -f "$RECONCILE_HELPER" ] && node "$RECONCILE_HELPER" "$(pwd)" "${RUN_DIR}"
이후 council/reconciled-ledger.json을 intake authority로 사용한다. council은 interview ↔ defer/blocked 범위의 자문만 할 수 있고, 이미 확정된 auto 값은 snapshot hash로 동결된다. 어떤 자문도 auto로 승격할 수 없다. blocked가 남으면 정확히 필요한 evidence/authority만 알리고 중단한다. 각 항목은 effective_disposition을 우선 사용하며 없으면 원래 disposition을 쓴다. interview만 한 번의 최대 4-question batch로 묻는다. blocked는 interview와 같은 것으로 세지 않는다. blocked는 필요한 외부 근거를 알리고 멈추며, user-answerable 결정은 blocked로 바꾸지 않고 interview에 남긴다. 실제 council/debate.json이 생성되지 않았으면 council이 실행됐다고 표현하지 않는다.
Read 툴로 ${RUN_DIR}/ctx-prime.json 로드. 다음 필드만 사용자에게 한 줄로 brief:
stack.framework, stack.kind, brand_signal.dominant_color_hexsurface_inventory.length (몇 개 surface 발견)brand_signal.language (ko / en / ja)AskUserQuestion 1개를 다음 shape로:
question: "이 레포 분석했어요 — {framework} + {dominant_color_hex} 베이스 + {N}개 surface ({language} 카피). 이번 작업의 1차 타깃 페르소나는?"
header: "Audience"
options: ctx-prime.audience_hypothesis 상위 3개 → label/description 매핑
- audience_hypothesis[0]: label + "(추천)", description = evidence
- audience_hypothesis[1]: label, description = evidence
- audience_hypothesis[2]: label, description = evidence (없으면 생략)(AskUserQuestion이 자동 "Other" 추가하므로 자유 입력 페르소나도 가능. Codex / OpenCode 등 AskUserQuestion이 없는 채널은 같은 question + option을 prose로 묻고 자유 텍스트 답을 받는다 — #21.)
사용자 답을 ctx-prime.json에 confirmed_audience 필드로 merge (Edit 또는 Write):
jsonc{ // ... 기존 필드 ... "confirmed_audience": "외부 트래픽 — SEO/conversion 우선, 톤 일탈 허용" }
페르소나 확정 직후 AskUserQuestion 1번 더, 최대 4개 question 묶음. ctx-prime 결과를 활용해 picker option을 동적 구성:
> 채널 분기 (#21): Claude Code 채널에서는 반드시 AskUserQuestion 툴로 제시 — 복수 답이 자연스러운 question(예: wow moment 여러 개 허용 시)은 multiSelect: true. Codex / OpenCode 등 툴이 없는 채널은 같은 question 묶음을 prose 1회 배치로 묻고 자유 텍스트 답을 받는다. 어느 채널이든 question 수 budget은 동일(아래 최대 4개) — 추가 게이트 금지.
Question 1 — exit_scope:
Question 2 — wow moment:
Question 3 — primary CTA:
Question 4 — visual grounding:
답을 ${RUN_DIR}/handoff/.handoff.json에 prefilled_slots로 적재:
bashmkdir -p "${RUN_DIR}/handoff" cat > "${RUN_DIR}/handoff/.handoff.json" <<EOF { "state": "PROPOSE_PLAN", "prefilled_slots": { "audience": "<confirmed_audience>", "exit_scope": "<answer 1>", "wow_moment": "<answer 2>", "cta_primary": "<answer 3>", "visual_grounding": "<answer 4>" }, "ctx_prime_ref": "ctx-prime.json", "created_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)" } EOF
이 시점부터 master는 SLOT_GATE를 건너뛰고 PROPOSE_PLAN으로 직행한다 (master INTAKE 분기 참고).
ctx-prime.json 누락 또는 사용자가 picker에서 "Other → 알아서 골라줘" 답하면 Step 3 (reference picker) 그대로 진행. prefilled_slots 없으면 master는 legacy SLOT_GATE 흐름.
먼저 council/decision-ledger.json의 design-system-disposition을 읽는다.
reuse → 기존 root DESIGN.md를 사용하고 reference picker를 건너뛴다.surface-local-only → root DESIGN.md를 만들지 않고 현재 run의 localsurface contract만 사용한다. reference picker를 건너뛴다.
establish 또는 refresh → 아래 reference 의미 매칭을 보조 evidence로사용할 수 있다. reference는 제품 사실이나 시스템 전체를 소유하지 않는다.
interview → checkpoint 답변 전에는 reference를 고르지 않는다.blocked → 중단한다.기존 root DESIGN.md를 사용하는 경우 이 시점에 read-only format inspection을 남긴다: core-v2-bound | core-v2-portable | legacy-13 | legacy-15 | legacy-16 | unmarked | absent. 채택된 profile: portable-core manifest가 exact graph/projection hash를 검증할 때만 core-v2-bound다. migration-candidate는 named source DESIGN.md authority를 유지한다. 이 단계에서 문서를 개명·재정렬·덮어쓰지 않는다. Core v2가 아닌 입력은 Phase 5의 provider-free staged migration으로만 전환하고, dropped=0 수용 게이트를 건너뛰지 않는다.
Harness Phase 5 agents author only graph/provenance/coverage drafts. After the frozen ledger explicitly authorizes establish or refresh, the master uses omd design-md prepare-review <graph> --provenance <provenance> --coverage <coverage> --out-dir <review> (plus the migration report when applicable) to produce the exact non-authoritative checkpoint preview. After mandatory checkpoint #2 approval, it invokes omd design-md approve-review and the fully receipt-bound omd design-md compile ... --review-receipt <approval> --out-dir <fresh> --adopt. The only installed fallback is the exact prepare-design-md-core-review.cjs, compile-design-md-core.cjs, and adopt-design-md-core.cjs helper chain with the same inputs; the master never reconstructs it. DESIGN.md, section anchors, all seven design-md:claim openers, every design-md:claim-end, manifest, and binding hashes are compiler-owned; never hand-write or patch them. A migration candidate remains non-authoritative. The graph draft omits projection/projection.sha256; a compiler that demands a placeholder, precomputed, or zero SHA fails closed before staging.
Compiler conformance is not factual, provenance, license, locale, accessibility, or visual-quality proof. The fresh package must also contain exact provenance/coverage bindings and pass the installed final project-system validator. If those bindings, the deterministic checkpoint packager, or the atomic package adopter are unavailable, fail closed at staging without manual hashes or partial project copies. Project mutation is only through omd design-md prepare-checkpoint <fresh> --reviewer <project-owner-id> --out <checkpoint> --authority-transition-approved then omd design-md adopt <fresh> --project-root <project-root> --checkpoint-receipt <checkpoint>; mandatory checkpoint #2 remains the separate authorization to adopt exact frozen bytes.
ledger가 없는 legacy install에서만 기존 동작처럼 프로젝트 루트에 DESIGN.md가 없으면 reference를 직접 추천한다. 외부 API 호출 없음.
다음 data dir을 순서대로 확인해, 세 파일이 함께 있는 첫 dir에서 전부 Read한다:
.codex/data/.claude/data/.opencode/data/node_modules/oh-my-design-cli/data/data/reference-fingerprints.json — reference fingerprint (tone keywords, visual theme, antipatterns, signature motion, has_personas, category)reference-tags.md — 사람-읽기용 keyword 매트릭스vocabulary.json — controlled vocab채널을 알 수 있으면 그 채널 dir을 우선하되, 서로 다른 dir의 세 파일을 섞지 않는다.
선택된 reference DESIGN.md는 다음 순서로 resolve한다:
<!-- omd:catalog-resolution-order — omd-init/omd-reference-capture SKILL.md + agents/omd-master.md 와 동일 순서 강제. drift guard: test/unit/core/catalog-resolution-order.test.ts -->
.codex/data/references/<id>/DESIGN.md.claude/data/references/<id>/DESIGN.md.opencode/data/references/<id>/DESIGN.mdnode_modules/oh-my-design-cli/web/references/<id>/DESIGN.mdweb/references/<id>/DESIGN.mdhttps://oh-my-design.kr/<id>/design.md[calm, minimal, approachable, warm])["toss"])tone_keywords ∩ task keywords → 1점/매칭추천하는 모든 id는 reference-fingerprints.json의 items[].id에 반드시 존재해야 한다. 없는 id는 만들어내지 않는다.
라벨 없이, 추천을 statement로:
DESIGN.md가 없어서 reference 한 개를 골라 부트스트랩할게요. <task 핵심 한 줄>을 보니 <top1.id>가 가장 잘 맞을 것 같아요 — <visual_theme 핵심 + 매칭 키워드 1-2개를 한 줄로>.
이대로 가시려면 go (또는 <top1.id>).
다른 후보: <top2.id> (한 줄 이유) · <top3.id> (...) · <top4.id> (...) · <top5.id> (...)
본인이 아는 다른 reference면 한 줄로 id만 (예: vercel) — reference 카탈로그에 없으면 알려드립니다.go 또는 reference id (top-5 안) → 그 id로 master spawn중단 → 종료선택된 reference의 라이브 사이트에서 디자인 토큰 + 시각 reference + 폰트를 가져오면 master phase 정확도가 크게 올라간다. 단일 mode (이전의 clone/inspired 갈래는 v1.3.3에서 폐기 — 시각 동일성은 brand creative work을 가져와야 가능하고, 그건 IP 영역).
사용자에게 한 줄로 묻기:
<id> 라이브 자료를 가져올까요? (토큰·구조 cue·폰트·hero screenshot)
가져옴: 컬러·radius·간격·폰트(open-source CDN)·구조 cue(carousel/CTA 모양/nav)·voice register
가져오지 않음: brand mascot 일러스트·마케팅 사진·로고(사용자 자체 자산으로 시작)
답: yes / skipyes → omd:reference-capture skill 호출 (Skill 툴) → 끝나면 Step 4로 skip → 바로 Step 4
omd:reference-capture는 LICENSE-NOTE.md / attribution.md / fonts.json / structure.json 작성. 모든 brand-identifying 자산은 assets/_reference/<id>/에 reference 용도로 보존되며 사용자 product DOM에는 들어가지 않는다.
사용자 task에서 surface idiom 신호 추출. 이 신호는 master가 reference-capture 자료 중 어떤 부분을 더 무겁게 볼지 결정한다.
| 키워드 (KR/EN/JP/TW) | surface_signal | |---|---| | 랜딩, 홈, 메인, landing, home, main, marketing, 홍보, 프로모션, 「ランディング」, 首頁 | marketing | | 대시보드, 앱, 화면, 설정, 관리, dashboard, app, settings, console, admin, 「ダッシュボード」, 儀表板 | product | | 문서, 가이드, docs, documentation, help, 「ドキュメント」, 文件 | docs | | 온보딩, 시작하기, 가입, onboarding, signup, 「オンボーディング」, 註冊 | onboarding | | (위에 매치 없음) | null (master 자유 판단) |
기존 <RUN_DIR + task + chosen_ref_id> 에 surface_signal과 reference-capture 자료 경로를 명시:
RUN_DIR: <path>
task: <user task>
chosen_ref_id: <id>
surface_signal: marketing | product | docs | onboarding | null
reference_capture_dir: assets/_reference/<id>/ | null
delivery_intent: implement | design-only
design_md_format: core-v2-bound | core-v2-portable | legacy-13 | legacy-15 | legacy-16 | unmarked | absentreference_capture_dir이 존재하면 master는 그 디렉토리의 tokens.json, structure.json, screenshots/*.png 를 모두 활용한다 (canonical DESIGN.md만 보지 말 것).
Subagent (master)는 AskUserQuestion 직접 호출 불가 (main-thread 전용). file-based handoff 패턴으로 돌린다.
시각 디자인·component·prototype phase로 master를 spawn하기 직전에만 references/master-visual-grounding.md를 전부 읽는다. intake 분류, 질문 relay, blocked handoff에는 이 sidecar를 읽지 않는다. 읽은 뒤에는 전체 문서를 prompt에 복사하지 말고 reference, surface signal, verified font, archetype, asset mode, protected behavior, unresolved group만 한 단락으로 요약해 전달한다.
이 sidecar의 unknown-means-absent, verified-asset, shared-container, reveal safety, responsive 규칙은 regression gate다. omd-asset-fetch가 URL·license·fallback의 단일 source of truth이며 harness가 CDN catalog를 복제하지 않는다.
spawn_count = 0
prompt = "<grounding sidecar에서 추린 evidence summary> + <RUN_DIR + task + chosen_ref_id + surface_signal + reference_capture_dir>. Phase 1부터 시작."
while spawn_count < 12 (safety cap):
result = Agent({
subagent_type: "omd-master",
description: "Run design harness round N",
prompt: prompt
})
spawn_count += 1
handoff_path = "<RUN_DIR>/.handoff.json"
if not exists(handoff_path):
relay result text to user; halt
handoff = JSON.parse(Read(handoff_path))
if handoff.user_prose:
print handoff.user_prose to user
if handoff.status == "done": break to Step 5
if handoff.status == "error": halt + show
if handoff.status == "blocked": relay handoff.user_prose + blocking_items; halt
if handoff.status == "ask_user":
questions = JSON.parse(Read(handoff.questions_file))
answers = AskUserQuestion({ questions: questions.questions })
answers_file = "<RUN_DIR>/checkpoints/<handoff.checkpoint_id>.answers.json"
Write(answers_file, JSON.stringify({checkpoint_id, answers}))
prompt = "continue checkpoint:" + handoff.checkpoint_id + " — answers at " + answers_filemaster가 ARCHIVE_RUN에서 <RUN_DIR>/handoff/delivery.json을 작성해야 한다. launcher는 status: done을 받으면 이 파일을 읽는다.
delivery_intent: design-only → artifact와 unresolved를 사용자에게 전달하고 종료.delivery_intent: implement → 현재 main agent가 implementation_owner를 이어받아 omd:apply의 implement/change 경로로 제품 파일을 편집한다.delivery packet 최소 shape:
json{ "intent": "implement", "task": "<user outcome>", "consumer_route": "<real route or null>", "acceptance": [], "protected_behaviors": [], "evidence": [], "unknowns": [], "implementation_owner": "main-agent-after-checkpoint-3", "artifacts": [], "verification": { "routes": [], "viewports": [], "states": [], "commands": [] } }
main agent는 다음 순서를 지킨다.
consumer_route가 null이면 코드에서 실제 사용자 진입 경로를 찾는다. 추정 route로 대체하지 않는다.<RUN_DIR>/handoff/delivery-verification.json에 changed product files, 실행한 checks, unresolved를 기록한다.제품 파일 변경과 실제 route 검증 전에는 status: done을 최종 delivery 완료로 해석하지 않는다. 그것은 design archive 완료일 뿐이다.
한 번의 /omd-harness 호출에 최대 12 spawn. 초과 시 사용자에게 escalate ("master가 12 spawn 초과, 멈춥니다 — run dir 보존").
사용자가 자연어로 "go" / "fix X" 답하면 동일 loop 재시작. master는 .handoff.json 보고 어디까지 갔는지 파악.
Master가 체크포인트에서 turn을 종료한 후 다음 사용자 메시지가:
paused.flag 생성. 나중에 /omd-harness resume 하면 재개.omd/runs/run-<ts>-<slug>/
├── task.md
├── brief.md
├── references-cited.md
├── journey.mmd
├── wireframes/
├── DESIGN.md.patch
├── system/
│ ├── graph.draft.json
│ ├── provenance.draft.json
│ ├── coverage.draft.json
│ ├── adopted-candidate/
│ ├── graph.patch.json
│ ├── manifest.patch.json
│ ├── provenance.patch.json
│ ├── coverage.patch.json
│ └── checkpoint-manifest.json
├── components/
│ ├── manifest.json
│ └── microcopy.json
├── assets/
│ ├── brief.md
│ ├── manifest.json
│ ├── briefs/
│ ├── fallback/
│ └── pinterest-refs/
├── eval/
│ ├── deterministic.json
│ ├── jury.json
│ └── screenshots/
├── persona-feedback/
│ └── <persona>.json
├── critique.md
├── handoff/
│ ├── v0.zip
│ ├── cursor.zip
│ └── subframe.zip
├── run.log
└── postmortem.md작성하고 compiler/checkpoint packager가 만든 승인된 exact bytes만 atomic adopter로 적용)
projection binding을 쓰지 않는다. compiler가projection SHA를 요구하면 placeholder를 넣지 말고 fail-close한다.
만들거나 수정하지 말 것
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 13,103 | 13,835 | +6% | 1 | 1 | 0% | 2,191 | 11,030 | +403% | 0 | 0 | — |
case-02 | fail→fail | 13,367 | 13,131 | -2% | 1 | 1 | 0% | 2,389 | 10,950 | +358% | 0 | 0 | — |
case-03 | fail→fail | 27,974 | 11,246 | -60% | 1 | 1 | 0% | 5,457 | 10,138 | +86% | 0 | 0 | — |
case-04 | pass→pass | 18,945 | 20,553 | +8% | 1 | 1 | 0% | 4,157 | 14,155 | +241% | 0 | 0 | — |
case-05 | pass→fail | 14,681 | 36,510 | +149% | 1 | 1 | 0% | 2,862 | 11,031 | +285% | 0 | 0 | — |
case-06 | pass→fail | 13,826 | 7,649 | -45% | 1 | 1 | 0% | 2,520 | 11,061 | +339% | 0 | 0 | — |
case-07 | fail→fail | 17,560 | 12,780 | -27% | 1 | 1 | 0% | 3,149 | 10,760 | +242% | 0 | 0 | — |
case-08 | fail→fail | 19,274 | 14,246 | -26% | 1 | 1 | 0% | 3,886 | 10,159 | +161% | 0 | 0 | — |
case-09 | fail→pass | 10,290 | 3,680 | -64% | 1 | 1 | 0% | 1,796 | 10,439 | +481% | 0 | 0 | — |
case-10 | fail→pass | 14,801 | 9,388 | -37% | 1 | 1 | 0% | 2,700 | 11,502 | +326% | 0 | 0 | — |
case-11 | fail→pass | 15,178 | 8,845 | -42% | 1 | 1 | 0% | 2,947 | 11,344 | +285% | 0 | 0 | — |
case-12 | fail→pass | 9,165 | 8,797 | -4% | 1 | 1 | 0% | 1,727 | 11,660 | +575% | 0 | 0 | — |
case-13 | fail→pass | 17,246 | 14,088 | -18% | 1 | 1 | 0% | 2,879 | 12,272 | +326% | 0 | 0 | — |
case-14 | fail→pass | 10,105 | 3,660 | -64% | 1 | 1 | 0% | 1,755 | 10,377 | +491% | 0 | 0 | — |
case-15 | fail→pass | 11,080 | 3,703 | -67% | 1 | 1 | 0% | 1,918 | 10,381 | +441% | 0 | 0 | — |
case-16 | pass→pass | 17,315 | 14,871 | -14% | 1 | 1 | 0% | 2,576 | 10,635 | +313% | 0 | 0 | — |
case-17 | pass→pass | 12,030 | 3,491 | -71% | 1 | 1 | 0% | 2,166 | 10,402 | +380% | 0 | 0 | — |
case-18 | fail→pass | 11,700 | 3,205 | -73% | 1 | 1 | 0% | 2,131 | 10,393 | +388% | 0 | 0 | — |
case-19 | fail→pass | 12,198 | 4,026 | -67% | 1 | 1 | 0% | 2,310 | 10,529 | +356% | 0 | 0 | — |
case-20 | pass→pass | 15,550 | 9,185 | -41% | 1 | 1 | 0% | 2,813 | 11,408 | +306% | 0 | 0 | — |
case-21 | fail→pass | 16,418 | 7,513 | -54% | 1 | 1 | 0% | 2,865 | 11,099 | +287% | 0 | 0 | — |
case-22 | fail→pass | 17,024 | 5,342 | -69% | 1 | 1 | 0% | 3,112 | 10,727 | +245% | 0 | 0 | — |
case-23 | fail→fail | 11,883 | 4,159 | -65% | 1 | 1 | 0% | 2,045 | 10,487 | +413% | 0 | 0 | — |
case-24 | fail→pass | 13,726 | 4,935 | -64% | 1 | 1 | 0% | 2,606 | 10,778 | +314% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 24 cases were attempted, and 18 counted toward the lift figure. The other 6 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +42 percentage points is the difference between those two pass rates over the 18 comparable cases. 2 cases got worse with the skill loaded, and they are included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 8/21/2026 | +36% |
Other measured skills in the registry, with their headline benchmark lift.