diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 260b7782..65eeb9b6 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -5,7 +5,7 @@ }, "metadata": { "description": "Personal Claude Code plugin collection with 24 specialized plugins. Codex 0.135 + Hermes Agent native — generated `.agents/plugins/marketplace.json` + per-plugin `.codex-plugin/plugin.json` (`scripts/sync-codex-manifests.mjs`) and Hermes `plugin.yaml` + `__init__.py` adapters (`scripts/sync-hermes-manifests.mjs`).", - "version": "2.2.0" + "version": "2.3.0" }, "plugins": [ { @@ -54,7 +54,7 @@ "name": "notebook", "source": "./plugins/notebook", "description": "Safe Jupyter notebook editing", - "version": "1.0.1", + "version": "1.0.2", "category": "development" }, { @@ -89,14 +89,14 @@ "name": "docs-forge", "source": "./plugins/docs-forge", "description": "README/CHANGELOG generation with CRO best practices, plus deployment-doc templates and MOC index generation", - "version": "0.3.0", + "version": "0.3.1", "category": "documentation" }, { "name": "slidev", "source": "./plugins/slidev", "description": "Slidev markdown presentation generator with interview workflow and KubeCon-level visual enhancement", - "version": "1.2.1", + "version": "1.2.2", "category": "content" }, { @@ -131,7 +131,7 @@ "name": "project-init", "source": "./plugins/project-init", "description": "Agent-harness project lifecycle. `new` — one-shot first-day bootstrap (interview, .claude/ scaffold, minimal CLAUDE.md, AGENTS.md with Codex GitHub cloud reviewer guidelines in general/ml/web variants, README/CHANGELOG seed, gh repo create + initial push) behind a hardened preflight guard that refuses a non-empty cwd. `wiring` — its inverse for existing repos: a read-only 14-axis setup diagnostic (FAIL / WARN / ASK / INFO / SKIP / OK) covering guidance files, .claude/rules paths: scoping defeated by @import, llm-wiki layout + staging backlog, Serena onboarding, memory posture, MCP duplicate registration, Codex CLI posture + AGENTS.md byte budget, spec homes, gws-sync, .tmp, core.hooksPath, .gitignore coverage. ASK answers persist to .claude/state/wiring.json. Shared read-only detector: scripts/project_state.sh.", - "version": "0.4.3", + "version": "0.4.4", "category": "planning" }, { @@ -145,14 +145,14 @@ "name": "anti-slop-design", "source": "./plugins/anti-slop-design", "description": "Anti-AI-slop design guard for web/SaaS landing, decks (PPT), dashboards, and copy. Runs a clarify->context->plan->run->audit->revise flow with a two-phase audit gate (pre-emit self-critique + binary slop checklist) and hands Korean copy rewriting to humanize-korean. Source-grounded in 6 OSS anti-slop repos.", - "version": "0.3.2", + "version": "0.3.3", "category": "design" }, { "name": "tally-form", "source": "./plugins/tally-form", "description": "Build Tally questionnaire/survey forms from checklist markdown — deterministic stdlib urllib builder with theme presets (neutral/hermes), section dividers, paragraph-split intros, per-question choices with required + checkbox (multi-select), short-answer inputs (text/number/email/phone/link), native scheduling (matrix grid / date / time), form images (logo/cover/inline IMAGE via hosted URLs incl. GitHub raw shorthand), redirect-on-completion, idempotent publish, and humanize-korean copy routing. Includes dev-survey and lecture-consultation presets plus bundled example fixtures.", - "version": "1.2.1", + "version": "1.2.2", "category": "content" }, { @@ -166,14 +166,14 @@ "name": "gws-sync", "source": "./plugins/gws-sync", "description": "로컬 폴더 → Google Drive 단방향 제안형 동기화 (gws CLI 기반, MCP 아님). 매핑 설정 파일(.gws-sync.json)로 로컬↔Drive 폴더 대응을 기억하고, 실행 시 Drive 트리 탐색 → 신규·변경 diff 리포트 → 업로드 위치 AskUserQuestion 승인 → 업로드(기존 파일은 content update로 ID·공유링크 보존). 삭제는 제안만(자동 삭제 금지), Drive→로컬 다운로드 범위 밖. gws 미설치 시 공식 docs 기반 설치 안내 출력 후 중단(자동 설치 안 함). googleworkspace/cli 공식 스킬/레시피 95종 카탈로그(llms.txt)를 references에 동봉 — 상황에 유용한 미설치 스킬을 npx skills add로 제안.", - "version": "0.1.1", + "version": "0.1.2", "category": "productivity" }, { "name": "mem0-ops", "source": "./plugins/mem0-ops", "description": "Fleet-level mem0 diagnostics and cleanup — complements the upstream mem0 plugin (which owns per-project quality). fleet-scan reports per-app noise ratio, junk app_id candidates, and app/user_id fragmentation across all apps; doctor checks config posture (MEM0_RERANK env, ~/.mem0/settings.json auto_save precedence trap, project decay flag, hook timeout budget, identity fragmentation); cleanup does backup-then-delete by metadata.type or whole junk app behind a dry-run default plus a skill-layer per-app confirmation gate (the script alone gates on --execute only). stdlib-only REST scripts, zero LLM cost for the deterministic parts.", - "version": "0.1.1", + "version": "0.1.2", "category": "productivity" } ] diff --git a/.claude/rules/dual-integration.md b/.claude/rules/dual-integration.md index 88f1ff93..80ace6c3 100644 --- a/.claude/rules/dual-integration.md +++ b/.claude/rules/dual-integration.md @@ -32,6 +32,7 @@ Top-level guidance no longer needs mirroring at all: root `CLAUDE.md` is a one-l - **Keep subagent delegation Claude-only acceleration.** A Claude-side subagent dispatch may only wrap a skill phase whose inline cross-runtime path stays primary and complete — never move skill logic into an agent definition (Codex 0.135 and Hermes have no agents surface, so relocated logic silently vanishes for them). - **Keep skill `description` frontmatter under 1024 chars.** Codex 0.135 silently skips any skill whose `description` exceeds 1024 characters; Claude Code has no such limit, so the violation is invisible on the Claude side. `--check` validates description length (not just drift), and the shared `.githooks/pre-commit` runs it on every commit — activate once per clone with `git config core.hooksPath .githooks`. Put the full trigger list / per-tool rationale in the skill body, not the description. - **Quote a skill `description` that contains a colon-space (`: `).** YAML frontmatter parses `description: ...: ...` as a nested mapping and fails with `mapping values are not allowed here`, so the skill silently fails to load on both runtimes. Wrap the value in double quotes (or a `>-` block scalar). `plugin.json` / `marketplace.json` are JSON and unaffected; the lenient manifest generator and `--check` do NOT catch this. +- **Write instruction and skill documentation prose in English.** Skill bodies, bundled reference docs, and plugin `CLAUDE.md` prose are English so all three runtimes — and the Codex GitHub cloud reviewer — read one language. Domain content is exempt and stays in its source language: marketing/UI copy, form presets, humanize samples, illustrative Korean example outputs, and the i18n / trigger phrases inside a skill `description:` frontmatter field (translating those breaks skill matching). A skill whose output is functional content in the user's language (a seeded stub, a runtime message shown to the user) keeps that content as-is — translating it changes what the plugin emits, not just its documentation. - **Keep shared lore in the neutral root.** Cross-agent insight and wiki content live under `.llmwiki/` (never `.claude/`-only), so both runtimes read one copy. - **State when a change is intentionally single-surface.** If guidance applies to only one agent (e.g. a Claude-only Plan Mode rule), say so in the change so the asymmetry reads as deliberate, not forgotten. diff --git a/.githooks/pre-commit b/.githooks/pre-commit index 4480e36f..b8e1ff81 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -11,6 +11,9 @@ node "$repo_root/scripts/sync-codex-manifests.mjs" --check node "$repo_root/scripts/sync-hermes-manifests.mjs" --check node "$repo_root/scripts/check-doc-consistency.mjs" node "$repo_root/scripts/check-skill-tool-portability.mjs" --check +# Skill-prose progressive-disclosure smell detector — INFORMATIONAL ONLY. It exits 0 +# regardless, but the `|| true` keeps it non-blocking even if node itself errors. +node "$repo_root/scripts/check-skill-prose.mjs" || true # Hermes adapter mock-load — same guard CI runs, so import/registration regressions # in generated __init__.py fail at commit time, not only in CI. Skip (not fail) when # python3 is absent locally; CI still enforces it. diff --git a/.github/workflows/validate-codex.yml b/.github/workflows/validate-codex.yml index f9964a53..717228bc 100644 --- a/.github/workflows/validate-codex.yml +++ b/.github/workflows/validate-codex.yml @@ -29,6 +29,9 @@ jobs: # interactive-input tool: each AskUserQuestion skill is a mapped pilot or reviewed # baseline debt. See scripts/check-skill-tool-portability.mjs. - run: node scripts/check-skill-tool-portability.mjs --check + # Progressive-disclosure smell detector (skill docs > ~500 lines, deep bundled + # references). INFORMATIONAL ONLY — always exits 0, never blocks the run. + - run: node scripts/check-skill-prose.mjs || true # Import each generated Hermes adapter with a stub ctx and assert register_skill # fires — catches a generated-but-never-executed adapter regression (PyYAML is # preinstalled on ubuntu-latest). See scripts/mock-load-hermes.py. diff --git a/AGENTS.md b/AGENTS.md index ca251732..2d248146 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -169,6 +169,7 @@ - subagent 위임은 Claude 전용 가속일 뿐이다 — skill 단계의 인라인 크로스런타임 경로가 primary 로 남아야 하고, skill 로직을 agent 정의로 옮기지 않는다 (Codex 0.135 / Hermes 는 agents surface 가 없어 옮긴 로직이 조용히 사라진다). - wiki lore 는 `.claude/rules/` 로 승격하지 않는다 — Codex/Hermes 가 못 읽는다. cross-agent insight 는 `.llmwiki/insight/` 로 graduate 후 공유 주입 hook 으로 노출한다. - `.llmwiki/` 를 per-agent 로 fork 하지 않는다. +- Instruction and skill documentation prose is written in English (skill bodies, reference docs, plugin `CLAUDE.md`) so all three runtimes and the Codex cloud reviewer read one language. Domain content is exempt and stays in its source language — copy, form presets, humanize samples, illustrative example outputs, and the i18n / trigger phrases inside a skill `description:` frontmatter field (translating those breaks skill matching). - **`AGENTS.md` 를 `CLAUDE.md` 로의 포인터로 축약하지 않는다.** Codex/Hermes 는 `@` 를 확장하지 않아 `@CLAUDE.md` 는 죽은 텍스트이고, "CLAUDE.md 를 먼저 읽어라" 식 산문 redirect 는 Codex GitHub cloud reviewer 에 닿지 않는다 (이 리뷰어는 `## Review guidelines` 섹션을 시스템 프롬프트에 직접 로드한다 — 임의 산문 redirect 는 따라가지 않고, `AGENTS.md` 가 명시적으로 참조하는 `code_review.md` 만 예외적으로 따라갈 수 있다[소프트 개런티, best-practices 문서]). 실패는 조용하다 — 에러 없이 지침만 사라진다. 이 저장소는 반대 방향을 택했다: `AGENTS.md` 가 SSOT 이고 `CLAUDE.md` 는 `@AGENTS.md` 한 줄을 import 한다 (`@import` 는 Claude 전용이라 `CLAUDE.md` 쪽에만 두면 되고, Codex/Hermes 는 `AGENTS.md` 를 직접 읽는다). 심볼릭 링크도 같은 효과를 내지만 Windows 체크아웃에서 `core.symlinks` 가 꺼져 있으면 `CLAUDE.md` 가 링크 대상 문자열 그대로 풀려 깨지므로, 포터블한 `@import` 를 택했다. ## Cross-runtime interactive input policy diff --git a/plugins/anti-slop-design/.claude-plugin/plugin.json b/plugins/anti-slop-design/.claude-plugin/plugin.json index 0f3b3129..5c8a5671 100644 --- a/plugins/anti-slop-design/.claude-plugin/plugin.json +++ b/plugins/anti-slop-design/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "anti-slop-design", - "version": "0.3.2", + "version": "0.3.3", "description": "Anti-AI-slop design guard for web/SaaS landing, decks (PPT), dashboards, and copy. Runs a clarify->context->plan->run->audit->revise flow with a two-phase audit gate (pre-emit self-critique + binary slop checklist) and hands Korean copy rewriting to humanize-korean. Source-grounded in 6 OSS anti-slop repos.", "skills": ["./skills/anti-slop-design"] } diff --git a/plugins/anti-slop-design/.codex-plugin/plugin.json b/plugins/anti-slop-design/.codex-plugin/plugin.json index e8165fd9..0d677d22 100644 --- a/plugins/anti-slop-design/.codex-plugin/plugin.json +++ b/plugins/anti-slop-design/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "anti-slop-design", - "version": "0.3.2", + "version": "0.3.3", "description": "Anti-AI-slop design guard for web/SaaS landing, decks (PPT), dashboards, and copy. Runs a clarify->context->plan->run->audit->revise flow with a two-phase audit gate (pre-emit self-critique + binary slop checklist) and hands Korean copy rewriting to humanize-korean. Source-grounded in 6 OSS anti-slop repos.", "author": { "name": "YoungjaeDev" diff --git a/plugins/anti-slop-design/plugin.yaml b/plugins/anti-slop-design/plugin.yaml index c928015b..32fa21c0 100644 --- a/plugins/anti-slop-design/plugin.yaml +++ b/plugins/anti-slop-design/plugin.yaml @@ -1,5 +1,5 @@ name: anti-slop-design -version: "0.3.2" +version: "0.3.3" description: "Anti-AI-slop design guard for web/SaaS landing, decks (PPT), dashboards, and copy. Runs a clarify->context->plan->run->audit->revise flow with a two-phase audit gate (pre-emit self-critique + binary slop checklist) and hands Korean copy rewriting to humanize-korean. Source-grounded in 6 OSS anti-slop repos." author: "YoungjaeDev" kind: standalone diff --git a/plugins/anti-slop-design/skills/anti-slop-design/SKILL.md b/plugins/anti-slop-design/skills/anti-slop-design/SKILL.md index dce73a07..87f54d0b 100644 --- a/plugins/anti-slop-design/skills/anti-slop-design/SKILL.md +++ b/plugins/anti-slop-design/skills/anti-slop-design/SKILL.md @@ -17,115 +17,115 @@ When this skill is loaded through Hermes as `anti-slop-design:anti-slop-design`, Treat `$ARGUMENTS` as the natural-language arguments supplied when the user asks Hermes to load the skill. Plugin-provided skills are explicit opt-in loads in Hermes; use `skill_view("anti-slop-design:anti-slop-design")` (or ask Hermes to load that qualified skill) rather than relying on bare text. -웹/SaaS 랜딩, 발표 덱(PPT), 대시보드/admin UI, 마케팅·UI 카피를 만들거나 감사·개선할 때 "AI가 만든 티(slop)"를 **생성 전에 차단**하고 **생성 후에 감사**하는 enterprise anti-slop guard. +An enterprise anti-slop guard for building, auditing, or improving web/SaaS landings, presentation decks (PPT), dashboards/admin UI, and marketing/UI copy — it **blocks the AI-generated look (slop) before generation** and **audits it after**. -**핵심 명제:** slop = 브리프와 무관하게 나오는 기본값(**default-not-choice**). 모든 판정은 "이건 *이* 브리프를 위한 선택인가, *아무* 브리프에나 나올 선택인가"로 환원된다. 색·폰트·레이아웃이 "예쁜가"가 아니라 "선택인가"를 본다. +**Core proposition:** slop = the default that shows up regardless of the brief (**default-not-choice**). Every verdict reduces to "is this a choice for *this* brief, or a choice that would show up for *any* brief?" It asks not whether the color/font/layout is "pretty" but whether it is "a choice". -## 언제 쓰나 +## When to use -- 위 4개 artifact를 **새로 만들 때**(생성 전 Phase A + 생성 후 Phase B 게이트). -- 기존 산출물을 **감사/개선**할 때("이 랜딩 AI 티 나는지 봐줘", "덱 slop 잡아줘"). -- 카피의 AI 티를 다룰 때 — 영문은 자체 탐지·스코어링, **한국어 재작성은 humanize-korean에 위임**. +- When **newly creating** the four artifacts above (a pre-generation Phase A gate + a post-generation Phase B gate). +- When **auditing/improving** an existing artifact ("check whether this landing looks AI-generated", "catch the slop in this deck"). +- When dealing with AI-tells in copy — English is detected/scored here, but **Korean rewriting is delegated to humanize-korean**. -## 안 하는 것 (scope) +## What it does not do (scope) -- 디자인 "생성기"가 아니다. 방향·구조·게이트를 제공하고, 실제 구현은 호출자(또는 frontend-design, ppt-master, taste-skill 등)가 한다. -- 실행형 detection 엔진/편집 차단 hook 없음 — 리포트·권고만 한다. -- 덱 빌드 실행(md->SVG->pptx)은 기존 도구(ppt-master/codex-image)가 한다. 단 **생성 일관성·납품 전 검증 방법론**(per-slide 병렬 + BUILDKIT, 렌더 검증 함정)은 anti-slop 소관으로 포함 — `references/slop-taxonomy.md` §3 PPT lane. -- 브랜드 색·폰트를 **기억으로 추측하지 않는다**. 자료 있으면 읽고, 없으면 `references/house-style.md` 기본값, 그래도 없으면 placeholder로 두고 사용자에게 묻는다. +- It is not a design "generator". It provides direction, structure, and gates; the actual implementation is done by the caller (or frontend-design, ppt-master, a taste-skill, etc.). +- No executable detection engine / edit-blocking hook — it only reports and recommends. +- Deck build execution (md->SVG->pptx) is done by the existing tools (ppt-master/codex-image). But the **generation-consistency and pre-delivery verification methodology** (per-slide parallelism + BUILDKIT, render-verification pitfalls) is anti-slop's domain — see `references/slop-taxonomy.md` §3 PPT lane. +- It does **not guess brand colors/fonts from memory**. If materials exist, read them; if not, use the `references/house-style.md` defaults; if still none, leave a placeholder and ask the user. -## 흐름 (clarify -> context -> plan -> audit(A) -> run -> audit(B) -> revise) +## Flow (clarify -> context -> plan -> audit(A) -> run -> audit(B) -> revise) ### 1. Clarify -artifact 종류(web / ppt / dashboard / copy), 청중, 브랜드, 결정맥락을 식별. 모호하면 `AskUserQuestion` 및 'interview skill'을 통해 좁힌다. 자동 가정 금지. +Identify the artifact type (web / ppt / dashboard / copy), audience, brand, and decision context. If ambiguous, narrow it via `AskUserQuestion` and the 'interview skill'. No automatic assumptions. ### 2. Context -- 해당 lane 규칙(`references/slop-taxonomy.md`의 lane 섹션) + `references/house-style.md` + `references/slop-taxonomy.md`의 VISUAL/STRUCTURAL을 로드. -- 카피가 범위면 `references/copy-rules.md`도 로드. -- 브랜드 자료(logo/palette/스크린샷) 있으면 읽어 brand-spec을 잡고, 없으면 house-style 기본값. **색을 지어내지 않는다.** +- Load the relevant lane rules (the lane sections of `references/slop-taxonomy.md`) + `references/house-style.md` + the VISUAL/STRUCTURAL sections of `references/slop-taxonomy.md`. +- If copy is in scope, load `references/copy-rules.md` too. +- If brand materials exist (logo/palette/screenshots), read them to fix the brand-spec; otherwise use the house-style defaults. **Do not invent colors.** ### 3. Plan -- "clean / modern / professional" 같은 **모호한 방향 금지**. 구체적 방향 1개를 고른다(예: enterprise editorial / technical minimal / research-lab calm / operator dashboard). -- 정보 위계(primary/secondary/tertiary)를 먼저 정의. -- **시각 산출물은 방향을 2~3개 제안하고 사용자가 택1**(show-don't-tell). 한 안만 밀지 않는다. +- No **vague direction** like "clean / modern / professional". Pick one concrete direction (e.g. enterprise editorial / technical minimal / research-lab calm / operator dashboard). +- Define the information hierarchy (primary/secondary/tertiary) first. +- **For visual artifacts, propose 2-3 directions and let the user pick one** (show-don't-tell). Do not push a single option. -### 4. Audit gate — Phase A (생성 전) -Plan을 6축으로 채점해 emit 전에 통과시킨다(상세 → 아래 "Audit gate (2단계)"의 Phase A). +### 4. Audit gate — Phase A (pre-generation) +Score the plan on 6 axes and pass it before emit (details → Phase A under "Audit gate (2 phases)" below). ### 5. Run -택1 방향 + lane 규칙 + house-style 기본값으로 산출(또는 호출자에게 전달할 spec 작성). 모든 ban에는 **escape hatch**: 브리프의 명시 요구가 항상 이긴다(브랜드가 보라색이면 보라 허용, 청중이 어린이면 emoji 허용 등). 예외를 쓰면 그 줄에 이유를 명시. +Produce the artifact (or write the spec to hand to the caller) using the chosen direction + lane rules + house-style defaults. Every ban has an **escape hatch**: an explicit requirement in the brief always wins (if the brand is purple, purple is allowed; if the audience is children, emoji are allowed, etc.). When you use an exception, state the reason on that line. -### 6. Audit gate — Phase B (납품 전) -아래 12항목 binary 체크리스트(필수, 상세 → 아래 "Audit gate (2단계)"의 Phase B). 카피 포함 시 영문은 `references/copy-rules.md`로 탐지·스코어링하고, **한국어 산문 재작성은 `humanize-korean:humanize-korean`(fast 모드)로 핸드오프** 후 `final.md` 본문만 회수한다. +### 6. Audit gate — Phase B (pre-delivery) +The 12-item binary checklist below (required, details → Phase B under "Audit gate (2 phases)"). When copy is included, English is detected/scored via `references/copy-rules.md`, and **Korean prose rewriting is handed off to `humanize-korean:humanize-korean` (fast mode)**, recovering only the body of `final.md`. ### 7. Revise -게이트에 걸린 항목을 고친 뒤 최종화. 출력은 항상 다음을 포함: -1. 사용한 design direction (구체 명칭) -2. 정보 위계 -3. 적용한 anti-slop 결정 (무엇을 왜 피했나) -4. 산출물(또는 구현 spec) -5. 남은 리스크 / trade-off -6. 게이트 결과 — Phase A 6축 점수(최저 축 포함)와 Phase B 12항목 중 걸렸던 항목·수정 내용(모두 no였으면 그대로 명시) +Fix the items that failed the gate, then finalize. The output always includes: +1. the design direction used (concrete name) +2. the information hierarchy +3. the anti-slop decisions applied (what was avoided and why) +4. the artifact (or implementation spec) +5. remaining risks / trade-offs +6. gate results — the Phase A 6-axis scores (including the lowest axis) and, of the Phase B 12 items, which failed and how they were fixed (if all were "no", state so) -## Audit gate (2단계) +## Audit gate (2 phases) -Phase A = 흐름 4번(Plan 직후, Run 이전) · Phase B = 흐름 6번(Run 이후, 납품 전). +Phase A = flow step 4 (right after Plan, before Run) · Phase B = flow step 6 (after Run, before delivery). -### Phase A — 생성 전 self-critique (도구 불필요, 최고 레버리지) +### Phase A — pre-generation self-critique (no tools needed, highest leverage) -**self-similarity probe:** "비슷한 브리프를 머릿속으로 처리했을 때 나올 선택과 같은가? 같다면 그건 *이* 브리프를 위한 선택이 아니다 — 교체하고 무엇을 왜 바꿨는지 적는다." +**self-similarity probe:** "Is this the same choice I would make processing a similar brief in my head? If so, it is not a choice for *this* brief — replace it and note what changed and why." -이어서 plan을 6축 1~5점으로 채점. **한 축이라도 3 미만이면 emit 전에 1회 수정:** -1. **Philosophy** — "왜"/관점이 있나, 아니면 그냥 레이아웃인가? -2. **Hierarchy** — 2초 안에 primary/secondary/tertiary가 읽히나? -3. **Specificity** — 이 브리프처럼 보이나, 아무-페이지처럼 보이나? -4. **Restraint** — 모든 요소가 제 값을 하나? (Chanel "악세서리 하나 빼기") -5. **Variety** — 직전 산출물과 구조적으로 다른가? (색만 바꾼 건 불인정) -6. **Honesty** — 지어낸 metric/testimonial/logo가 0인가? +Then score the plan on 6 axes, 1-5 points each. **If any axis is below 3, revise once before emit:** +1. **Philosophy** — is there a "why"/point of view, or is it just a layout? +2. **Hierarchy** — is primary/secondary/tertiary readable within 2 seconds? +3. **Specificity** — does it look like this brief, or like any-page? +4. **Restraint** — does every element earn its place? (Chanel's "take one accessory off") +5. **Variety** — is it structurally different from the last artifact? (changing only the color does not count) +6. **Honesty** — are invented metrics/testimonials/logos at 0? -루프 종료 휴리스틱: **"2회 수정은 정상, 3회면 디자인이 아니라 브리프가 틀린 것."** 3회째면 멈추고 브리프를 다시 묻는다. +Loop-termination heuristic: **"2 revisions is normal; at 3, it is the brief that is wrong, not the design."** On the third, stop and re-ask the brief. -### Phase B — 납품 전 binary 체크리스트 +### Phase B — pre-delivery binary checklist -12항목, **모든 답이 "no"여야 통과**. 하나라도 "yes" = 고친다(납품 금지). 각 항목은 detector + fix 쌍. +12 items; **all answers must be "no" to pass**. Any "yes" = fix it (delivery blocked). Each item is a detector + fix pair. -| # | tell (답이 "no"여야 함) | fix | +| # | tell (answer must be "no") | fix | |---|---|---| -| 1 | purple/rainbow/mesh gradient, 또는 gradient text? | flat committed accent, `bg-clip:text` 금지 | -| 2 | 단일 과용 font(Inter/Roboto/Geist/Space Grotesk)/one-font 페이지, 또는 italic serif/display 헤더(h1-h6/hero/stat — hallmark "top AI tell")? | display+body 의도적 pairing, 헤더는 roman weight | -| 3 | side-stripe card / card-in-card / icon-tile-above-heading 3-col grid / glassmorphism-as-default·목적없는 shadow? | bg·weight 대비, stripe 제거, 카드 변주, shadow는 elevation 의미 있을 때만 | -| 4 | cream-default / `#0D1117`-neon / 순수 `#000`·`#fff` base? | anchor hue로 tint한 committed palette | -| 5 | full-viewport centered hero / 전부 centered? | centered 요소 <=2, 비대칭 도입 | -| 6 | 장식용 `01/02/03` 번호 / 모든 섹션에 eyebrow chip? | 실제 sequence일 때만, 내용을 encode | -| 7 | generic Hero->3 features->testimonials->CTA->footer 골격? | 브리프 특정 macrostructure | -| 8 | 지어낸 metric / 가짜 testimonial / placeholder명(Acme/Jane Doe), 또는 hero가 big-number+small-label+보조stat 템플릿(실수치라도)? | 실제 수치+실제 narrative, 라벨된 placeholder, 또는 질문 | -| 9 | emoji as icon / icon library 혼용? | 하나의 real icon set | -| 10 | 손그림 figurative SVG / 재그린 browser·phone·terminal chrome? | 실제 screenshot 또는 회색 placeholder | -| 11 | over-animation / `transition-all` / 균일 `hover:scale` / `prefers-reduced-motion` 없음? | 하나의 orchestrated moment + reduced-motion | -| 12 | copy: buzzword / "Not X, it's Y" 대비 / throat-clearing / 지어낸 specifics? | 직접 진술 후 한국어는 humanize-korean로 | - -**numeric floor sweep** (자동검증 가능) — 세부 8항목(contrast·본문 폰트·type-scale·line-length·line-height·색 수·touch target·accent footprint)과 정확한 수치는 `references/slop-taxonomy.md` §4 Numeric floor sweep 표에서 확인한다(아래 "reference 로딩 가이드"의 중복 금지 정책과 동일하게 본문엔 요약만 둔다). +| 1 | purple/rainbow/mesh gradient, or gradient text? | flat committed accent, no `bg-clip:text` | +| 2 | a single overused font (Inter/Roboto/Geist/Space Grotesk) / one-font page, or an italic serif/display header (h1-h6/hero/stat — the hallmark "top AI tell")? | deliberate display+body pairing, headers in roman weight | +| 3 | side-stripe card / card-in-card / icon-tile-above-heading 3-col grid / glassmorphism-as-default·purposeless shadow? | bg·weight contrast, remove the stripe, vary the cards, shadow only when elevation has meaning | +| 4 | cream-default / `#0D1117`-neon / pure `#000`·`#fff` base? | a committed palette tinted with an anchor hue | +| 5 | full-viewport centered hero / everything centered? | centered elements <=2, introduce asymmetry | +| 6 | decorative `01/02/03` numbers / an eyebrow chip on every section? | only when it is a real sequence, encoding content | +| 7 | generic Hero->3 features->testimonials->CTA->footer skeleton? | a brief-specific macrostructure | +| 8 | invented metrics / fake testimonials / placeholder names (Acme/Jane Doe), or a hero that is a big-number+small-label+supporting-stat template (even with real numbers)? | real numbers + real narrative, labeled placeholders, or a question | +| 9 | emoji as icons / mixed icon libraries? | one real icon set | +| 10 | hand-drawn figurative SVG / redrawn browser·phone·terminal chrome? | a real screenshot or a gray placeholder | +| 11 | over-animation / `transition-all` / uniform `hover:scale` / no `prefers-reduced-motion`? | one orchestrated moment + reduced-motion | +| 12 | copy: buzzwords / "Not X, it's Y" contrast / throat-clearing / invented specifics? | direct statements, then hand Korean to humanize-korean | + +**numeric floor sweep** (auto-verifiable) — the 8 detail items (contrast·body font·type-scale·line-length·line-height·color count·touch target·accent footprint) with exact numbers are in the `references/slop-taxonomy.md` §4 Numeric floor sweep table (keeping only a summary in the body, per the no-duplication policy in "reference loading guide" below). ### gate mechanics -- Phase A 주관 판단을 Phase B 체크리스트보다 **먼저** 형성한다(체크리스트가 비판을 anchoring하지 않도록). -- 산출물에 self-describing 스탬프(``)를 **반드시 남긴다** — Phase A/B가 실제로 실행됐다는 유일한 사후 증거이므로 생략 금지. -- 모든 ban은 escape hatch 보유 — "브리프의 명시 요구가 항상 이긴다". 예외는 인라인으로 사유 표기. +- Form the Phase A subjective judgment **before** the Phase B checklist (so the checklist does not anchor the critique). +- **Always** leave a self-describing stamp on the artifact (``) — it is the only after-the-fact evidence that Phase A/B actually ran, so never omit it. +- Every ban has an escape hatch — "an explicit requirement in the brief always wins". Note exceptions inline with a reason. -## reference 로딩 가이드 +## reference loading guide -| 상황 | 로드 | +| Situation | Load | |---|---| -| 모든 시각 작업 | `references/slop-taxonomy.md` (VISUAL + STRUCTURAL) | -| lane별 규칙 | `references/slop-taxonomy.md`의 web / ppt / dashboard 섹션 | -| 카피 포함 | `references/copy-rules.md` (+ 한국어는 humanize-korean 핸드오프) | -| 기본 제안값 | `references/house-style.md` | +| all visual work | `references/slop-taxonomy.md` (VISUAL + STRUCTURAL) | +| per-lane rules | the web / ppt / dashboard sections of `references/slop-taxonomy.md` | +| copy included | `references/copy-rules.md` (+ hand Korean to humanize-korean) | +| default suggestions | `references/house-style.md` | -자세한 detector 목록·수치·예시는 본문에 중복하지 말고 reference에서 progressive disclosure로 가져온다. +Do not duplicate the detailed detector lists·numbers·examples in the body; pull them from the references via progressive disclosure. -## humanize-korean 핸드오프 (카피) +## humanize-korean handoff (copy) -- 경계: anti-slop-design = 시각/구조 + **영문 카피 탐지·스코어링** 소유. humanize-korean = **한국어 산문 재작성** 소유. -- 호출: 한국어 카피 재작성이 필요하면 `humanize-korean:humanize-korean`을 호출(기본 fast 모드, >=8000자 또는 정밀 필요 시 strict). 출력 `final.md`의 본문만 회수(HTML 주석 메타 제외). -- register: 산출물(특히 덱)의 발표 맥락(강연/학술/피치)에 톤앤매너를 맞춰 humanize한다 — 학술/전문가 청중이면 정착 기술용어를 유지(첫 등장 1회 한글 병기)하고 구어체로 평탄화하지 않는다(`copy-rules.md` §1). -- fallback (필수): `humanize-korean`은 이 marketplace에 번들되지 않은 **외부 의존**이다. 미설치 환경(또는 Codex)에서는 호출이 없어도 lane이 중단되지 않게 graceful degrade — `copy-rules.md`의 한국어 카피 원칙으로 **직접 수동 재작성**하고, humanize-korean이 있으면 그쪽을 우선한다. 의존을 hard-require 하지 않는다. -- 금지: stop-slop류 무딘 절대금지(부사 전면금지, em-dash 전면금지, 3항목 리스트 금지)를 한국어로 복제하지 않는다 — 전역 가이드·humanize-korean의 한국어 친화 완화 스탠스를 따른다. +- Boundary: anti-slop-design owns visual/structural + **English copy detection·scoring**. humanize-korean owns **Korean prose rewriting**. +- Call: when Korean copy rewriting is needed, call `humanize-korean:humanize-korean` (fast mode by default, strict when >=8000 chars or precision is needed). Recover only the body of the output `final.md` (exclude the HTML-comment metadata). +- register: humanize matched to the artifact's presentation context (lecture/academic/pitch) in tone and manner — for an academic/expert audience, keep established technical terms (Korean gloss once on first appearance) and do not flatten to colloquial style (`copy-rules.md` §1). +- fallback (required): `humanize-korean` is an **external dependency** not bundled in this marketplace. In an environment where it is not installed (or under Codex), graceful-degrade so the lane does not stop without the call — **rewrite manually and directly** using the Korean-copy principles in `copy-rules.md`, preferring humanize-korean when present. Do not hard-require the dependency. +- prohibited: do not replicate stop-slop-style blunt absolute bans (a blanket ban on adverbs, a blanket ban on em-dashes, a ban on 3-item lists) in Korean — follow the global guide and humanize-korean's Korean-friendly relaxation stance. diff --git a/plugins/anti-slop-design/skills/anti-slop-design/references/house-style.md b/plugins/anti-slop-design/skills/anti-slop-design/references/house-style.md index eef401f3..83907c63 100644 --- a/plugins/anti-slop-design/skills/anti-slop-design/references/house-style.md +++ b/plugins/anti-slop-design/skills/anti-slop-design/references/house-style.md @@ -1,48 +1,48 @@ # house-style -기본 제안값(default suggestion)과 OSS 교차점검. 출처 substance: `docs/references/anti-slop-design-oss-synthesis.md` §5. +Default suggestions and OSS cross-check. Source substance: `docs/references/anti-slop-design-oss-synthesis.md` §5. -**원칙: 기본은 범용, house-style은 worked example / 기본 제안값.** 브리프나 브랜드 자료가 있으면 그것이 이긴다. house-style은 "자료가 없을 때의 합리적 출발점"이지 강제 규범이 아니다. +**Principle: the default is generic; house-style is a worked example / default suggestion.** A brief or brand material, if present, wins. house-style is "a reasonable starting point when there is no material", not a mandatory norm. --- -## 1. 기본 제안값 (enterprise 톤) +## 1. Default suggestions (enterprise tone) -- **enterprise / calm but sharp** — 과장 없는 기술회사 신뢰감, 정보 전달 우선, low-noise/high-signal. -- **monochrome + 단일 accent** — grayscale base + accent 1색. -- **Pretendard** (한글 본문/제목). -- **no emoji** (코드·문서·UI 공통). -- **inline SVG diagram** — 아키텍처/플로우/data-viz. -- **dependency-free static** — HTML + CSS + vanilla JS, 외부 의존 없음. -- **print-CSS** (본문 >=10pt). +- **enterprise / calm but sharp** — the trust of a tech company without hype, information-transfer first, low-noise/high-signal. +- **monochrome + a single accent** — grayscale base + 1 accent color. +- **Pretendard** (Korean body/headings). +- **no emoji** (in code, docs, and UI alike). +- **inline SVG diagram** — architecture/flow/data-viz. +- **dependency-free static** — HTML + CSS + vanilla JS, no external dependency. +- **print-CSS** (body >=10pt). - **callout** — Note / Tip / Important / Caution / Warning. -OSS 보강(합의): 단일 restrained accent는 hallmark(accent <=~5% viewport)·huashu(<=3-4색)·frontend-slides("dominant color + sharp accent가 timid 균등 팔레트를 이긴다")·frontend-design("boldness는 한 곳에 spend")가 모두 지지. no emoji·dependency-free도 직접 합의. +OSS reinforcement (consensus): a single restrained accent is supported by hallmark (accent <=~5% viewport), huashu (<=3-4 colors), frontend-slides ("a dominant color + a sharp accent beats a timid even palette"), and frontend-design ("spend boldness in one place"). no-emoji and dependency-free are directly agreed too. --- -## 2. 충돌 해소 (house-style이 banned 패턴에 근접하는 지점) +## 2. Conflict resolution (where house-style approaches a banned pattern) -### blue/indigo accent <-> AI 팔레트 -사용자 기본 accent(blue/indigo)는 repo들이 지목하는 바로 그 hue 대역이다(frontend-slides는 generic indigo `#6366f1`를 명시 ban, impeccable은 hue 260-310 flag, purple->blue gradient는 1순위 universal tell). +### blue/indigo accent <-> AI palette +The user's default accent (blue/indigo) is exactly the hue band the repos point at (frontend-slides explicitly bans generic indigo `#6366f1`, impeccable flags hue 260-310, and a purple->blue gradient is the #1 universal tell). -**해소:** slop은 **gradient**와 **무고민 기본값 indigo**이지, *평면 단일 committed* indigo가 아니다. -- house-style은 특정 committed indigo 토큰을 `oklch()`로 핀하고 **절대 gradient화하지 않는다**. -- 이 한 지점이 house-style이 banned 패턴에 가장 근접한 유일 지점 — 사용 시 "flat 단색 committed accent"임을 인라인으로 명시. +**Resolution:** slop is the **gradient** and the **thoughtless default indigo**, not a *flat single committed* indigo. +- house-style pins a specific committed indigo token in `oklch()` and **never turns it into a gradient**. +- This one spot is the only place house-style comes closest to a banned pattern — when using it, state inline that it is a "flat, single, committed accent". -### inline SVG diagram <-> 손그림 SVG ban -huashu 최우선 ban은 **figurative/representational SVG**(사람·장면·제품)다. **diagram·icon·data-viz는 명시적 허용 집합.** +### inline SVG diagram <-> hand-drawn SVG ban +huashu's top ban is **figurative/representational SVG** (people·scenes·products). **Diagrams·icons·data-viz are an explicitly allowed set.** -**해소:** SVG ban을 **figurative에만 스코프**한다. 아키텍처/플로우 다이어그램은 house-style 핵심 자산이므로 false-positive 내면 안 된다. 즉 "손그림 인물/제품 SVG" != "구조 다이어그램". +**Resolution:** scope the SVG ban **to figurative only**. Architecture/flow diagrams are a core house-style asset, so they must not produce false positives. That is, "hand-drawn person/product SVG" != "structural diagram". ### Pretendard / callout -banned font 목록(Inter/Roboto/Geist/Space Grotesk 등 Latin face 대상)에 Pretendard 없음 — 한국어-우선 의도적 선택, 충돌 없음(어떤 repo도 Pretendard를 과용 폰트로 지목하지 않음, clean 처리). callout은 어떤 repo도 안 다룸 — slop corpus와 직교, 충돌 없음. +The banned-font list (targeting Latin faces like Inter/Roboto/Geist/Space Grotesk) has no Pretendard — a Korean-first deliberate choice, no conflict (no repo names Pretendard as an overused font; treat it as clean). callout is covered by no repo — orthogonal to the slop corpus, no conflict. --- -## 3. 적용 규칙 +## 3. Application rules -- 브랜드 자료 없을 때만 위 기본값을 출발점으로. 자료 있으면 brand-spec이 이긴다. -- accent는 `oklch()` 단일 committed 토큰, gradient 금지. -- SVG는 diagram/icon/data-viz만 — figurative 손그림 금지. -- 범용 산출이 목표면 house-style을 강제하지 말고 "기본 제안"으로만 제시한다. +- Use the defaults above as a starting point only when there is no brand material. When material exists, the brand-spec wins. +- Accent is a single committed `oklch()` token; no gradient. +- SVG only for diagram/icon/data-viz — no figurative hand-drawing. +- When generic output is the goal, do not force house-style — present it only as a "default suggestion". diff --git a/plugins/anti-slop-design/skills/anti-slop-design/references/slop-taxonomy.md b/plugins/anti-slop-design/skills/anti-slop-design/references/slop-taxonomy.md index 285a44ff..c8d4585b 100644 --- a/plugins/anti-slop-design/skills/anti-slop-design/references/slop-taxonomy.md +++ b/plugins/anti-slop-design/skills/anti-slop-design/references/slop-taxonomy.md @@ -1,115 +1,115 @@ # slop-taxonomy -AI-slop 시각/구조 지문 카탈로그. 6개 OSS repo(impeccable 44-rule / hallmark 58-gate / frontend-design / huashu / stop-slop / frontend-slides) source-grounded 합성에서 distill. 출처 substance: repo 분석 `docs/references/anti-slop-design-oss-synthesis.md`. +A catalog of AI-slop visual/structural fingerprints. Distilled from a source-grounded synthesis of 6 OSS repos (impeccable 44-rule / hallmark 58-gate / frontend-design / huashu / stop-slop / frontend-slides). Source substance: the repo analysis in `docs/references/anti-slop-design-oss-synthesis.md`. -각 항목은 **detector(무엇이 tell인가) + Instead(어떻게 고치나)** 쌍. **[CORE]** = 3개 이상 repo가 독립적으로 지목한 고신뢰 universal fingerprint. 모든 ban은 escape hatch 보유 — **브리프의 명시 요구가 이긴다**(브랜드가 보라색이면 보라 허용 등). +Each item is a **detector (what is the tell) + Instead (how to fix)** pair. **[CORE]** = a high-confidence universal fingerprint pointed at independently by 3 or more repos. Every ban has an escape hatch — **an explicit requirement in the brief wins** (if the brand is purple, purple is allowed, etc.). --- ## 1. VISUAL fingerprints ### Color & Contrast -- **[CORE] purple/violet gradient (purple->pink->blue, "AI 팔레트")** — 모든 visual repo가 1순위로 지목. CSS hue 260-310을 heading/큰 글자에. Instead: 평면 committed accent 1색, gradient 금지. -- **[CORE] gradient text (`background-clip:text` on gradient, Tailwind `bg-clip-text` 포함)** — "장식적, 의미 전달 0". Instead: 단색 텍스트. -- **cream/beige "tasteful default" surface** — OKLCH L 0.84-0.97 / C<0.06 / hue 40-100. 토큰명 `--paper/--cream/--sand/--bone/--linen/--ivory` 자체가 tell. (모델 자신의 house-style 기본값). Instead: 브리프에서 도출한 committed surface. -- **GitHub-dark lazy preset** — 균일 `#0D1117` + generic cyan/purple neon glow. (이것만 banned — authored cinematic/warm-cyber dark은 허용). Instead: 의도된 dark 팔레트. -- **순수 `#000` / `#fff` base** — flat하게 읽힘(modern-minimal 장르는 `#fff` 예외). Instead: anchor hue로 살짝 tint. -- **zero-chroma neutral** — 순수 grey는 죽어 보임. Instead: 모든 neutral을 anchor hue 쪽으로 >=0.005 chroma tint. -- **too many colors** — Instead: <=3-4 (1 primary + 1 secondary + 1 accent + grays), 또는 **monochrome(단일 hue + grays)으로 최대 절제**. 색 가짓수 자체가 많은 것도 slop(특히 슬라이드 덱은 색 절제가 신뢰도). accent footprint가 viewport의 ~5% 초과면 tell(atmospheric 장르는 ~20% radial bloom 허용). -- gray text on colored bg, cyan-on-dark glow — washed out. Instead: 충분한 대비. +- **[CORE] purple/violet gradient (purple->pink->blue, the "AI palette")** — pointed at first by every visual repo. CSS hue 260-310 on headings/large text. Instead: a single flat committed accent color, no gradient. +- **[CORE] gradient text (`background-clip:text` on a gradient, including Tailwind `bg-clip-text`)** — "decorative, zero meaning conveyed". Instead: solid-color text. +- **cream/beige "tasteful default" surface** — OKLCH L 0.84-0.97 / C<0.06 / hue 40-100. The token name `--paper/--cream/--sand/--bone/--linen/--ivory` is itself the tell (the model's own house-style default). Instead: a committed surface derived from the brief. +- **GitHub-dark lazy preset** — uniform `#0D1117` + a generic cyan/purple neon glow. (Only this is banned — an authored cinematic/warm-cyber dark is allowed.) Instead: an intentional dark palette. +- **pure `#000` / `#fff` base** — reads as flat (the modern-minimal genre is a `#fff` exception). Instead: a slight tint toward an anchor hue. +- **zero-chroma neutral** — pure grey looks dead. Instead: tint every neutral toward the anchor hue by >=0.005 chroma. +- **too many colors** — Instead: <=3-4 (1 primary + 1 secondary + 1 accent + grays), or **maximum restraint with monochrome (a single hue + grays)**. A high color count is itself slop (color restraint is credibility, especially for slide decks). An accent footprint over ~5% of the viewport is a tell (the atmospheric genre allows ~20% radial bloom). +- gray text on a colored bg, cyan-on-dark glow — washed out. Instead: sufficient contrast. ### Typography -- **[CORE] 과용 폰트를 display/body로** — Inter, Roboto, Open Sans, Lato, Montserrat, Arial, Helvetica, Poppins, system stack + AI 선호 display(Geist, Space Grotesk, Plus Jakarta Sans, Fraunces, Instrument, Mona Sans, Recoleta). brand-domain allowlist 존재(vercel.com의 Geist, github.com의 Mona Sans는 정상). Instead: characterful display + 별도 body 의도적 pairing. -- **[CORE] one-font 페이지** — 단일 family = template 페이지. Instead: display+body pairing. -- **모델 수렴 폰트 Space Grotesk** — 도구 자신이 습관적으로 집는 선택. generic뿐 아니라 "내가 디폴트로 고른 것"을 의심. -- **italic serif/display 헤더** — h1-h6/hero title/wordmark/stat에 `font-style:italic`("top AI tell"). 오버사이즈 italic serif hero(Fraunces/Playfair/Cormorant/Garamond/Canela/Ogg, generic `serif` fallback 포함). Instead: roman weight. -- **flat type hierarchy** — size step 간 ratio <1.25. Instead: >=1.25 (slide는 title >=2.5x body, 이상 3x). -- **oversized H1** — display 크기의 풀문장 headline. clamp() max <=6rem(~96px). 짧은 1-2단어 headline은 그 크기 OK. -- **>3 font families** — "2+1 rule": `--font-display` + `--font-body` + outlier 최대 1(비코드 맥락에선 mono도 family로 카운트). -- **extreme negative tracking** — body letter-spacing <=-0.05em(글자 붙음), display floor >=-0.04em. body wide-tracking >0.05em도 tell. -- **all-caps display, line-height <1.0** — wrap 시 cap-top 충돌. floor 1.0(권장 1.02-1.08). all-caps body는 word-shape 인식 상실로 ban. -- tiny text(body <12px = 확실한 tell; 권장 floor는 14px — §4 numeric floor 참조), tight leading(line-height <1.3x). +- **[CORE] an overused font as display/body** — Inter, Roboto, Open Sans, Lato, Montserrat, Arial, Helvetica, Poppins, the system stack + AI-favored display faces (Geist, Space Grotesk, Plus Jakarta Sans, Fraunces, Instrument, Mona Sans, Recoleta). A brand-domain allowlist exists (Geist on vercel.com, Mona Sans on github.com are fine). Instead: a characterful display + a separate body in a deliberate pairing. +- **[CORE] one-font page** — a single family = a template page. Instead: a display+body pairing. +- **the model-convergent font Space Grotesk** — the choice the tool habitually reaches for. Suspect not only the generic but "the one I picked as a default". +- **italic serif/display headers** — `font-style:italic` on h1-h6/hero title/wordmark/stat (the "top AI tell"). An oversized italic serif hero (Fraunces/Playfair/Cormorant/Garamond/Canela/Ogg, including the generic `serif` fallback). Instead: roman weight. +- **flat type hierarchy** — ratio <1.25 between size steps. Instead: >=1.25 (slides: title >=2.5x body, ideally 3x). +- **oversized H1** — a full-sentence headline at display size. clamp() max <=6rem (~96px). A short 1-2 word headline is OK at that size. +- **>3 font families** — the "2+1 rule": `--font-display` + `--font-body` + at most 1 outlier (in non-code contexts, mono counts as a family too). +- **extreme negative tracking** — body letter-spacing <=-0.05em (letters touching), display floor >=-0.04em. body wide-tracking >0.05em is also a tell. +- **all-caps display, line-height <1.0** — cap-top collision on wrap. floor 1.0 (recommended 1.02-1.08). all-caps body is banned for loss of word-shape recognition. +- tiny text (body <12px = a sure tell; recommended floor is 14px — see §4 numeric floor), tight leading (line-height <1.3x). ### Visual Details (component cliches) -- **[CORE] side-stripe / left-border-accent card** — 가장 많이 지목된 컴포넌트 tell("AI UI의 가장 식별 가능한 지문"). 시그니처: `border-radius:12px; border-left:4px solid #3b82f6`(border >=3px 또는 rounded 요소의 모든 border-width). Instead: bg/weight 대비로 구분, stripe 제거. -- **[CORE] icon-tile-above-heading feature card** — 작은 rounded-square icon 컨테이너를 heading 위에 쌓는 "universal AI feature-card template". Instead: 카드별 크기·내용 변주. -- **[CORE] nested card (card-in-card)** — semantic 이유 없음. Instead: 평면화. -- **[CORE] emoji as icon** — sparkle/rocket/lightning/fire/target/check를 feature/step/pricing 아이콘으로. (브랜드가 쓰거나 청중이 어린이면 예외). Instead: 하나의 real icon set. -- icon library 혼용(Material+Heroicons+Lucide). Instead: 1개 set. -- **glassmorphism as default / 목적 없는 drop shadow** — absolute ban. Instead: shadow는 elevation 의미가 있을 때만. -- **hero-metric template** — "큰 숫자 + 작은 라벨 + 보조 stat + gradient accent"는 the template answer. 거대한 맨숫자를 hero headline으로. Instead: 실제 narrative. -- bounce/elastic/overshoot easing(`cubic-bezier(0.34,1.56,...)`). Instead: ease-out-quart/quint/expo. +- **[CORE] side-stripe / left-border-accent card** — the most-pointed-at component tell ("the most identifiable fingerprint of AI UI"). Signature: `border-radius:12px; border-left:4px solid #3b82f6` (a border >=3px, or any border-width on a rounded element). Instead: distinguish by bg/weight contrast, remove the stripe. +- **[CORE] icon-tile-above-heading feature card** — stacking a small rounded-square icon container above the heading, the "universal AI feature-card template". Instead: vary size·content per card. +- **[CORE] nested card (card-in-card)** — no semantic reason. Instead: flatten. +- **[CORE] emoji as icons** — sparkle/rocket/lightning/fire/target/check as feature/step/pricing icons. (Exception if the brand uses them or the audience is children.) Instead: one real icon set. +- mixed icon libraries (Material+Heroicons+Lucide). Instead: 1 set. +- **glassmorphism as default / purposeless drop shadow** — an absolute ban. Instead: shadow only when elevation has meaning. +- **hero-metric template** — "a big number + a small label + a supporting stat + a gradient accent" is the template answer. A huge bare number as a hero headline. Instead: a real narrative. +- bounce/elastic/overshoot easing (`cubic-bezier(0.34,1.56,...)`). Instead: ease-out-quart/quint/expo. ### Imagery & Decoration -- **[CORE] 손그림 figurative SVG (사람/장면/제품)** — huashu 최우선 ban. AI가 그린 SVG 인물은 이목구비 어긋남, CSS 실루엣 제품은 "generic tech animation"(모든 제품이 똑같아 brand 인식 0). **허용 SVG: true icon(16-32px), geometric decoration, data-viz/diagram만.** Instead: "회색 사각형 + '1200x800 illustration slot' 라벨이 나쁜 SVG hero보다 100배 낫다." -- **decorative imagery on text content** — honesty test: 이미지를 빼도 정보가 안 줄면 slop(에세이 목록의 배너, 프로필의 풍경 헤더). purple gradient와 동급. -- **재그린 UI chrome** — 가짜 browser bar(traffic-light dots), phone notch, terminal/IDE chrome, self-drawn iOS Dynamic Island. "self-writing은 99% position bug." Instead: 실제 screenshot을 `
`에. -- aurora-blob / floating-orb / mesh background(>1 accent, >~5% footprint, 또는 페이지 전체 animating mesh). 덱에선 "abstract shape만, illustration 금지". -- decorative SVG/canvas에 `aria-label`/`aria-hidden` 없음("the new accessibility tell"). +- **[CORE] hand-drawn figurative SVG (people/scenes/products)** — huashu's top ban. AI-drawn SVG people have misaligned features; a CSS-silhouette product is a "generic tech animation" (every product looks the same, zero brand recognition). **Allowed SVG: true icons (16-32px), geometric decoration, data-viz/diagram only.** Instead: "a gray rectangle + a '1200x800 illustration slot' label is 100x better than a bad SVG hero." +- **decorative imagery on text content** — the honesty test: if removing the image loses no information, it is slop (a banner on an essay list, a landscape header on a profile). On par with a purple gradient. +- **redrawn UI chrome** — a fake browser bar (traffic-light dots), a phone notch, terminal/IDE chrome, a self-drawn iOS Dynamic Island. "Self-writing is 99% a position bug." Instead: a real screenshot in a `
`. +- aurora-blob / floating-orb / mesh background (>1 accent, >~5% footprint, or a full-page animating mesh). In decks, "abstract shapes only, no illustration". +- decorative SVG/canvas with no `aria-label`/`aria-hidden` ("the new accessibility tell"). ### Motion -- **[CORE] over-animation / 흩뿌린 micro-interaction** — "추가 애니메이션은 AI 생성 느낌을 키운다". Instead: 하나의 orchestrated moment(예: 1회 staggered page-load), 1-2개 persisting hero 요소로 연속 narrative. -- `transition-all` / 균일 `hover:scale-105` / 한 요소에 동시 hover 효과 >1. -- layout prop(width/height/top/left/margin/padding) 애니메이션. Instead: transform/opacity만. -- `prefers-reduced-motion` fallback 없음(필수). -- auto-rotating carousel에 pause-on-hover/focus 없음(WCAG 2.2.2). +- **[CORE] over-animation / scattered micro-interactions** — "extra animation amplifies the AI-generated feel". Instead: one orchestrated moment (e.g. a single staggered page-load), a continuous narrative with 1-2 persisting hero elements. +- `transition-all` / uniform `hover:scale-105` / more than 1 simultaneous hover effect on an element. +- animating layout props (width/height/top/left/margin/padding). Instead: transform/opacity only. +- no `prefers-reduced-motion` fallback (required). +- an auto-rotating carousel with no pause-on-hover/focus (WCAG 2.2.2). --- ## 2. STRUCTURAL patterns -위계·밀도·장식·"선택 아닌 기본값" 구조. - -- **[CORE] generic AI macrostructure: Hero -> 3 features -> testimonials -> CTA -> footer** — 주제와 무관하게 나오는 골격. Instead: 브리프 특정 구조(섹션마다 존재 이유). -- **[CORE] 3-equal-column card grid (icon-above-heading, ~24px gap)** — Instead: 비대칭/크기 변주, 일부 image·일부 text, 일부 column-span. -- **[CORE] everything-centered / full-viewport centered hero** — `min-height:100vh` 전부 centered = auto-fail. Instead: centered 요소 <=2, 비대칭 도입. -- **[CORE] 장식용 numbered marker (01/02/03)** — 실제 sequence(순서 정보)일 때만 허용. 장식 numbering은 slop. -- **[CORE] 모든 섹션 위 tiny uppercase tracked eyebrow chip** — "AI editorial scaffolding". eyebrow를 heading과 같은 줄에 두면 auto-fail(단일 column 수직 stack이어야). 구조 장치는 내용의 진실을 encode해야지 장식이면 안 됨. -- **[CORE] 지어낸 metric / quote-slop / data-slop** — invented "10x faster", "trusted by 50,000+ teams", "99.9% uptime", 가짜 testimonial, placeholder명(Jane Doe/John Smith/Acme/Nexus). Instead: 실제 수치, 라벨된 placeholder, 또는 사용자에게 질문. -- **AI nav 지문** — wordmark-left + 4-5 inline link + button-right + full-width + 1px hairline border-bottom + white bg. -- **AI footer 지문** — 4 column(Product/Company/Resources/Legal) + social icon row + tiny copyright + 1px top-border + grey bg. -- **monotonous spacing** — 어디나 같은 spacing 값, 섹션 간 rule/ornament/색 전환 없음, 4px 배수 scale 벗어난 arbitrary padding(`17px`). Instead: rhythm 있는 spacing scale. -- **bento-grid 남용**, **decoration > content**(heading마다 장식 icon). 단 **density 자체는 slop이 아니다** — 차별적 product signal(data/reasoning/status)을 담은 밀도는 유지, 장식만 제거. -- **default-attractor sameness** — 직전 build와 같은 macrostructure 지문, variation knob 안 바꾸고 archetype 재사용. **이것이 root thesis**: slop = 브리프와 독립적으로 내린 선택. -- horizontal scroll(320-1920px 어디서든). Instead: `overflow-x:clip`, image grid track은 `minmax(0,1fr)`. +Structures of hierarchy·density·decoration·"the default that is not a choice". + +- **[CORE] generic AI macrostructure: Hero -> 3 features -> testimonials -> CTA -> footer** — a skeleton that shows up regardless of topic. Instead: a brief-specific structure (each section has a reason to exist). +- **[CORE] 3-equal-column card grid (icon-above-heading, ~24px gap)** — Instead: asymmetric/size variation, some image·some text, some column-span. +- **[CORE] everything-centered / full-viewport centered hero** — `min-height:100vh` all centered = auto-fail. Instead: centered elements <=2, introduce asymmetry. +- **[CORE] decorative numbered markers (01/02/03)** — allowed only when it is a real sequence (ordering information). Decorative numbering is slop. +- **[CORE] a tiny uppercase tracked eyebrow chip above every section** — "AI editorial scaffolding". Placing the eyebrow on the same line as the heading is an auto-fail (it must be a single vertical column stack). A structural device must encode the truth of the content, not be decoration. +- **[CORE] invented metrics / quote-slop / data-slop** — invented "10x faster", "trusted by 50,000+ teams", "99.9% uptime", fake testimonials, placeholder names (Jane Doe/John Smith/Acme/Nexus). Instead: real numbers, labeled placeholders, or a question to the user. +- **AI nav fingerprint** — wordmark-left + 4-5 inline links + button-right + full-width + a 1px hairline border-bottom + white bg. +- **AI footer fingerprint** — 4 columns (Product/Company/Resources/Legal) + a social icon row + tiny copyright + a 1px top-border + grey bg. +- **monotonous spacing** — the same spacing value everywhere, no rule/ornament/color transition between sections, arbitrary padding off the 4px-multiple scale (`17px`). Instead: a spacing scale with rhythm. +- **bento-grid overuse**, **decoration > content** (a decorative icon on every heading). But **density itself is not slop** — keep density that carries a differentiating product signal (data/reasoning/status), remove only the decoration. +- **default-attractor sameness** — the same macrostructure fingerprint as the last build, reusing the archetype without changing the variation knob. **This is the root thesis**: slop = a choice made independently of the brief. +- horizontal scroll (anywhere from 320-1920px). Instead: `overflow-x:clip`, use `minmax(0,1fr)` for image grid tracks. --- -## 3. Lane별 quick rules - -### Web / SaaS landing (가장 깊게 커버됨) -위 VISUAL/STRUCTURAL ban 전부 적용 + §4 numeric floor. hero는 eyebrow+headline+lede+CTA가 1280x800에서 스크롤 없이, `padding-block-end >= 1.3x padding-block-start`. AI nav/footer 지문·aurora-blob·재그린 chrome 금지. 모든 장식 image에 honesty test. - -### PPT / 덱 -- web font/color/gradient/decoration ban 전부 적용. -- **fixed-stage discipline**: 고정 1920x1080 canvas를 uniform scale, 모든 화면에서 16:9 유지(letterbox/pillarbox, reflow 금지). 슬라이드 전환은 `.active`/`.visible`(visibility/opacity/pointer-events), `display:none/block` 금지. -- **density 모드**: speaker-led = 1 idea + 1-3 bullet, 큰 타입 / reading-first = 4-8 bullet 또는 4-6 card. **"split, don't shrink"** — 넘치면 새 슬라이드, 줄이지 말 것. -- slide 본문 >=24px(이상 28-36), title-to-body >=2.5x, contrast >=4.5:1. -- **scaffolding 노출 절대 금지**(NON-NEGOTIABLE): 화면에 "preview"/"template"/"Option A/B/C"/파일경로/요구사항 노트/style-preset 이름 렌더 금지. 납품 전 보이는 텍스트 점검. real 덱 chrome(title/section/date/author/page number)만. -- page number는 덱 셸이 소유 — 단일 페이지에 self-draw 금지(이중 번호 `02/03` + `6/16` 유발). -- 하나의 연속 motion narrative("voiced PowerPoint" 장면별 fade-up 금지). 같은 image를 슬라이드마다 반복 금지(title/closing의 logo 제외). -- **색 절제(슬라이드 특히)**: <=3 committed hue 또는 monochrome. 긍정/부정 델타는 hue 추가 없이 색+방향기호(↑/↓)로 인코딩. tint는 1종 zone-fill로 제한. -- **생성 일관성 방법론**(빌드 실행은 ppt-master, 일관성은 anti-slop 소관): 다수 슬라이드를 per-slide agent로 병렬 생성할 때 literal chrome snippet 묶음(BUILDKIT) + gold reference 1-2장(앵커 슬라이드)을 공유해 동일 chrome을 복제하게 한다. chrome 고정·콘텐츠만 변주(색만 바꾼 변주는 variety 불인정과 같은 맥락). -- **납품 전 검증 함정**(slop은 렌더에서 드러난다): (1) 레이아웃 진실은 PowerPoint/cairosvg 기준 — LibreOffice는 spAutoFit 미리보기 한계로 overflow를 숨긴다. (2) SVG는 빌드 전 XML well-formed 일괄 검사(HTML named entity ` `·font-family 따옴표 짝 실수가 흔함). (3) 산출 pptx의 텍스트/수치 검증은 group shape **재귀** 필요(`` -> PPTX group; 얕은 walk는 false-negative). - -### Dashboard / Admin UI -- 증거 GAP (정직 표기) -**6개 repo 어디도 대시보드 전용 ruleset이 없다.** 모두 landing/덱/prose lane. 따라서 이 lane은 가장 얇은 근거이며, 전용 소스 확보 시 보강 대상. 현재는 transfer되는 규칙으로 운영: -- impeccable의 component/contrast/density 규칙이 data-dense UI에 그대로 적용: WCAG 대비(4.5:1 / 3:1), gray-on-color, monotonous-spacing, nested-card, cramped-padding(폰트 크기에 비례한 임계), **clipped-overflow-container**(`overflow:hidden`이 tooltip/menu/popover를 자르는 흔한 대시보드 버그), text-overflow/horizontal-scroll, tight-leading, side-tab border, design-system drift. -- hallmark form-state 게이트(transfer): 상태 간 border-width 변동, focus-ring을 outline 아닌 border로, input 높이 != 인접 button 높이(44px floor), 빈 helper-text slot 붕괴(`min-height:1lh` 예약), disabled를 opacity만으로 신호. -- **huashu density 역전(핵심 가드레일)**: 대시보드의 본분은 dense data — anti-slop이 정보 밀도를 평탄화하면 안 된다. **"여백 늘리기" 반사 금지.** 장식만 제거, product signal 밀도는 유지. +## 3. Per-lane quick rules + +### Web / SaaS landing (covered most deeply) +Apply all the VISUAL/STRUCTURAL bans above + the §4 numeric floor. The hero has eyebrow+headline+lede+CTA with no scroll at 1280x800, `padding-block-end >= 1.3x padding-block-start`. No AI nav/footer fingerprint·aurora-blob·redrawn chrome. Apply the honesty test to every decorative image. + +### PPT / decks +- Apply all web font/color/gradient/decoration bans. +- **fixed-stage discipline**: a fixed 1920x1080 canvas uniformly scaled, keeping 16:9 on every screen (letterbox/pillarbox, no reflow). Slide transitions use `.active`/`.visible` (visibility/opacity/pointer-events), no `display:none/block`. +- **density modes**: speaker-led = 1 idea + 1-3 bullets, large type / reading-first = 4-8 bullets or 4-6 cards. **"split, don't shrink"** — on overflow, add a new slide, do not shrink. +- slide body >=24px (ideally 28-36), title-to-body >=2.5x, contrast >=4.5:1. +- **never expose scaffolding** (NON-NEGOTIABLE): do not render "preview"/"template"/"Option A/B/C"/file paths/requirement notes/style-preset names on screen. Check visible text before delivery. Only real deck chrome (title/section/date/author/page number). +- the page number is owned by the deck shell — no self-drawing on a single page (which causes double numbering `02/03` + `6/16`). +- one continuous motion narrative (no per-scene fade-up "voiced PowerPoint"). Do not repeat the same image on every slide (except the logo on title/closing). +- **color restraint (especially slides)**: <=3 committed hues or monochrome. Encode a positive/negative delta with color + a direction symbol (↑/↓) rather than adding a hue. Limit tint to a single zone-fill. +- **generation-consistency methodology** (build execution is ppt-master; consistency is anti-slop's domain): when generating many slides in parallel via per-slide agents, share a literal chrome-snippet bundle (BUILDKIT) + 1-2 gold reference slides (anchor slides) so the same chrome is replicated. Fix the chrome·vary only the content (a variation that changes only the color does not count as variety, in the same spirit). +- **pre-delivery verification pitfalls** (slop reveals itself in the render): (1) layout truth is PowerPoint/cairosvg, not LibreOffice — LibreOffice hides overflow with its spAutoFit-preview limitation. (2) run a batch XML well-formed check on the SVG before build (an HTML named entity ` `·a mismatched font-family quote is common). (3) verifying text/numbers in the output pptx needs **recursion** through group shapes (`` -> PPTX group; a shallow walk is a false-negative). + +### Dashboard / Admin UI -- evidence GAP (stated honestly) +**None of the 6 repos has a dashboard-specific ruleset.** All are landing/deck/prose lanes. So this lane has the thinnest basis and is a reinforcement target once dedicated sources are secured. For now it runs on transferred rules: +- impeccable's component/contrast/density rules apply directly to a data-dense UI: WCAG contrast (4.5:1 / 3:1), gray-on-color, monotonous-spacing, nested-card, cramped-padding (a threshold proportional to font size), **clipped-overflow-container** (the common dashboard bug where `overflow:hidden` clips a tooltip/menu/popover), text-overflow/horizontal-scroll, tight-leading, side-tab border, design-system drift. +- hallmark form-state gates (transferred): border-width shifts between states, a focus-ring as a border instead of an outline, input height != adjacent button height (44px floor), collapse of an empty helper-text slot (reserve with `min-height:1lh`), signaling disabled by opacity alone. +- **huashu density inversion (the key guardrail)**: a dashboard's job is dense data — anti-slop must not flatten information density. **No "increase whitespace" reflex.** Remove only decoration, keep the product-signal density. --- -## 4. Numeric floor sweep (자동검증 가능) +## 4. Numeric floor sweep (auto-verifiable) -| 항목 | floor | +| Item | floor | |---|---| -| contrast | 본문 >=4.5:1, large(>=24px 또는 >=18.67px bold) >=3:1 | -| 본문 폰트 | >=14px (mobile 16px, slide 본문 >=24px) | +| contrast | body >=4.5:1, large (>=24px or >=18.67px bold) >=3:1 | +| body font | >=14px (mobile 16px, slide body >=24px) | | type-scale ratio | >=1.25 (slide title >=2.5x body) | -| line-length | <=80ch (이상 65-75ch) | -| line-height | 본문 >=1.3 | -| 색 수 | <=3-4 (1 primary + 1 secondary + 1 accent + grays) | +| line-length | <=80ch (ideally 65-75ch) | +| line-height | body >=1.3 | +| color count | <=3-4 (1 primary + 1 secondary + 1 accent + grays) | | touch target | 44x44px | -| accent footprint | viewport의 ~5% 이하 (atmospheric 장르 예외 ~20%) | -| honesty test | 모든 장식 image — 빼도 정보 안 줄면 제거 | +| accent footprint | <=~5% of viewport (atmospheric genre exception ~20%) | +| honesty test | every decorative image — remove it if information does not decrease | diff --git a/plugins/docs-forge/.claude-plugin/plugin.json b/plugins/docs-forge/.claude-plugin/plugin.json index 77323fd6..76777189 100644 --- a/plugins/docs-forge/.claude-plugin/plugin.json +++ b/plugins/docs-forge/.claude-plugin/plugin.json @@ -1,5 +1,5 @@ { "name": "docs-forge", - "version": "0.3.0", + "version": "0.3.1", "description": "README/CHANGELOG generation with CRO best practices, plus deployment-doc templates and MOC index generation" } diff --git a/plugins/docs-forge/.codex-plugin/plugin.json b/plugins/docs-forge/.codex-plugin/plugin.json index 031261f8..525cc5be 100644 --- a/plugins/docs-forge/.codex-plugin/plugin.json +++ b/plugins/docs-forge/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "docs-forge", - "version": "0.3.0", + "version": "0.3.1", "description": "README/CHANGELOG generation with CRO best practices, plus deployment-doc templates and MOC index generation", "author": { "name": "YoungjaeDev" diff --git a/plugins/docs-forge/CLAUDE.md b/plugins/docs-forge/CLAUDE.md index 3350026b..33a00706 100644 --- a/plugins/docs-forge/CLAUDE.md +++ b/plugins/docs-forge/CLAUDE.md @@ -31,8 +31,8 @@ Comprehensive reference documents in `references/`: | `TEMPLATES.md` | Copy-paste templates for 6 project types | | `CRO_CHECKLIST.md` | Conversion optimization checklist | | `EXAMPLES_ANALYSIS.md` | Detailed analysis of each example project | -| `DEPLOY_DOC_PATTERNS.md` | Deployment-doc skeleton, filled example, anti-patterns (Korean) | -| `MOC_PATTERNS.md` | MOC hook-sourcing ladder, lightweight + strict examples (Korean) | +| `DEPLOY_DOC_PATTERNS.md` | Deployment-doc skeleton, filled example, anti-patterns (Korean-default output examples) | +| `MOC_PATTERNS.md` | MOC hook-sourcing ladder, lightweight + strict examples (Korean-default output examples) | ## Analyzed Examples diff --git a/plugins/docs-forge/references/DEPLOY_DOC_PATTERNS.md b/plugins/docs-forge/references/DEPLOY_DOC_PATTERNS.md index 4bb3972d..5918a697 100644 --- a/plugins/docs-forge/references/DEPLOY_DOC_PATTERNS.md +++ b/plugins/docs-forge/references/DEPLOY_DOC_PATTERNS.md @@ -1,8 +1,12 @@ -# 배포 문서 패턴 +# Deploy Doc Patterns -클라이언트 전달용 배포 / 절차 문서(`.md`)의 표준 골격, 채워진 예시, 안티패턴. `deploy-doc-guide` 스킬의 `## Quick Reference`가 SSOT이며 이 문서는 그 골격을 구체화한다. +The standard skeleton, a filled example, and anti-patterns for client-facing +deployment / procedure documents (`.md`). The `## Quick Reference` in the +`deploy-doc-guide` skill is the SSOT; this document concretizes that skeleton. +The skeleton and example below are shown in the Korean-default output form the +tool generates (use `--lang en` for English labels). -## 골격 +## Skeleton ```markdown # <문서 제목 (--title)> @@ -31,11 +35,11 @@ <단계 본문.> ``` -- 문서 제목은 `# H1`(`--title`), 그 바로 아래에 **무제목 요약 단락**(2-3줄, 자체 섹션 헤딩 없음)을 두고 첫 `##` 위에 배치. 제목이 없으면 요약이 파일 최상단. 요약에 언급한 단계 개수 == `### N.` 헤딩 수. -- `## 전제조건`의 모든 줄은 `- [ ]`. -- `## 절차`의 모든 단계는 연속 번호 `### N.`. +- The document title is `# H1` (`--title`); directly below it, place an **untitled summary paragraph** (2-3 lines, no section heading of its own) above the first `##`. If there is no title, the summary is the very top of the file. The step count named in the summary must equal the number of `### N.` headings. +- Every line under `## 전제조건` is a `- [ ]` item. +- Every step under `## 절차` is a contiguously numbered `### N.` heading. -## 채워진 예시 +## Filled example ```markdown # 추론 서비스 배포 @@ -68,10 +72,10 @@ 다이제스트 일치 여부부터 역추적한다. ``` -> 구조만 참조 모델(`pcb-goldfinger-chamfer` 배포 문서)을 모사했으며 내용은 일반 예시다. +> Only the structure is modeled on a reference deploy doc (`pcb-goldfinger-chamfer`); the content is a generic example. -## 안티패턴 +## Anti-patterns -- **SSOT 인라인화** — 포트 표, 스키마, 가중치 경로 같은 계약을 절차 본문에 복붙. 명세가 갱신되면 문서가 즉시 거짓이 된다. 링크로 위임할 것. -- **`### N.` 없는 prose 단계** — "먼저 ~하고, 그다음 ~한다" 식 문단형 절차. 번호 헤딩으로 분해해야 추적·검증 가능. -- **요약/본문 번호 불일치** — 요약은 "3단계"라 하는데 `### N.`는 4개. 독자가 신뢰를 잃는 첫 신호. number-match 규칙으로 차단. +- **Inlining the SSOT** — copy-pasting contracts such as port tables, schemas, or weight paths into the procedure body. The moment the spec changes, the doc becomes false. Delegate to a link instead. +- **Prose steps without `### N.`** — a paragraph-style procedure ("first do X, then do Y"). Decompose it into numbered headings so it is traceable and verifiable. +- **Summary/body count mismatch** — the summary says "3 steps" but there are 4 `### N.` headings. The first signal that makes a reader lose trust; the number-match rule blocks it. diff --git a/plugins/docs-forge/references/MOC_PATTERNS.md b/plugins/docs-forge/references/MOC_PATTERNS.md index b1e3725c..0d6281e5 100644 --- a/plugins/docs-forge/references/MOC_PATTERNS.md +++ b/plugins/docs-forge/references/MOC_PATTERNS.md @@ -1,21 +1,25 @@ -# MOC 패턴 +# MOC Patterns -임의 폴더용 Map of Content(MOC) 생성의 hook 소싱 사다리, 경량/strict 출력 예시, llm-wiki `index.md` 매핑. `moc-guide` 스킬의 `## Quick Reference`가 SSOT다. +The hook-sourcing ladder, lightweight/strict output examples, and llm-wiki +`index.md` mapping for generating a Map of Content (MOC) over an arbitrary +folder. The `## Quick Reference` in the `moc-guide` skill is the SSOT. Output +examples below use the Korean-default form (hooks reflect the Korean docs being +indexed). -## Hook 소싱 +## Hook sourcing -파일별 1줄 hook은 아래 precedence ladder로 결정한다(첫 히트 채택): +The one-line hook for each file is decided by this precedence ladder (first hit wins): -1. frontmatter `description:` 또는 `summary:` -2. 첫 `# H1` 다음 첫 비어있지 않은 단락 (~100-120자 절단) -3. 첫 `##` 소제목 텍스트 -4. 최후: 휴머나이즈한 파일명 + hook = `(요약 없음)` 플래그 +1. frontmatter `description:` or `summary:` +2. the first non-empty paragraph after the first `# H1` (truncate to ~100-120 chars) +3. the first `##` subheading text +4. fallback: humanized filename + a `(요약 없음)` (no-summary) flag -링크 텍스트는 frontmatter `title:` → 첫 `# H1` → 파일명 순. strict 모드에서 frontmatter `id`가 있으면 `[[id]]` 링크 형태 선호. +Link text precedence: frontmatter `title:` → first `# H1` → filename. In strict mode, when a file's frontmatter carries an `id`, prefer the `[[id]]` link form. -## 경량 출력 예시 +## Lightweight output example -출력1(파일별 hook 불릿)과 출력2(도메인별 테이블)를 같은 `MOC.md` 본문에 둔다. +Output 1 (per-file hook bullets) and output 2 (per-domain table) go in the same `MOC.md` body. ```markdown # docs MOC @@ -35,7 +39,7 @@ | [Rollback](deploy/rollback.md) | (요약 없음) | ``` -## strict(wiki) 출력 예시 +## Strict (wiki) output example ```markdown # docs Map of Content (MOC) @@ -51,12 +55,12 @@ - [Rollback](deploy/rollback.md) — 배포 롤백 절차. ``` -## llm-wiki index.md 매핑 +## llm-wiki index.md mapping -strict 모드는 `plugins/llm-wiki/skills/bootstrap-wiki/assets/templates/wiki-skeleton/index.md`의 컨벤션을 미러한다: +Strict mode mirrors the convention in `plugins/llm-wiki/skills/bootstrap-wiki/assets/templates/wiki-skeleton/index.md`: -- `## ` 그룹 + `- [page-title](/.md) — 1-line hook` 불릿 -- 2-depth 최대, MOC-first 진입 규칙 -- frontmatter `id` 있으면 `[[id]]` 선호, typed cross-ref(`> Refines:` / `> Contradicts:` / `> Evidence:` / `> See-also:` 등) +- `## ` group sections plus `- [page-title](/.md) — 1-line hook` bullets. +- 2-depth maximum, MOC-first entry rule. +- When frontmatter has an `id`, prefer `[[id]]`, with typed cross-refs (`> Refines:` / `> Contradicts:` / `> Evidence:` / `> See-also:` and so on). -단, frontmatter 전체 스키마(`last_verified` / `status` / `volatility` / `sources`)와 staleness 모델은 **강제하지 않는다** — 그 모델과 실제 lore wiki 유지보수는 `llm-wiki` 플러그인(`ingest-finding` / `lint-wiki` 등)에 위임한다. docs-forge MOC는 임의 폴더를 한눈에 보는 일반화된 인덱스이지 lore 시스템이 아니다. +The full frontmatter schema (`last_verified` / `status` / `volatility` / `sources`) and the staleness model, however, are **not enforced** — that model and the actual lore-wiki maintenance are delegated to the `llm-wiki` plugin (`ingest-finding` / `lint-wiki`, etc.). The docs-forge MOC is a generalized at-a-glance index over an arbitrary folder, not a lore system. diff --git a/plugins/gws-sync/.claude-plugin/plugin.json b/plugins/gws-sync/.claude-plugin/plugin.json index f05ef0ad..ed4900bc 100644 --- a/plugins/gws-sync/.claude-plugin/plugin.json +++ b/plugins/gws-sync/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "gws-sync", - "version": "0.1.1", + "version": "0.1.2", "description": "로컬 폴더 → Google Drive 단방향 제안형 동기화 (gws CLI 기반, MCP 아님). 매핑 설정 파일(.gws-sync.json)로 로컬↔Drive 폴더 대응을 기억하고, 실행 시 Drive 트리 탐색 → 신규·변경 diff 리포트 → 업로드 위치 AskUserQuestion 승인 → 업로드(기존 파일은 content update로 ID·공유링크 보존). 삭제는 제안만(자동 삭제 금지), Drive→로컬 다운로드 범위 밖. gws 미설치 시 공식 docs 기반 설치 안내 출력 후 중단(자동 설치 안 함). googleworkspace/cli 공식 스킬/레시피 95종 카탈로그(llms.txt)를 references에 동봉 — 상황에 유용한 미설치 스킬을 npx skills add로 제안.", "skills": ["./skills/gws-sync"] } diff --git a/plugins/gws-sync/.codex-plugin/plugin.json b/plugins/gws-sync/.codex-plugin/plugin.json index 2ad3eedb..e0ab99f8 100644 --- a/plugins/gws-sync/.codex-plugin/plugin.json +++ b/plugins/gws-sync/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "gws-sync", - "version": "0.1.1", + "version": "0.1.2", "description": "로컬 폴더 → Google Drive 단방향 제안형 동기화 (gws CLI 기반, MCP 아님). 매핑 설정 파일(.gws-sync.json)로 로컬↔Drive 폴더 대응을 기억하고, 실행 시 Drive 트리 탐색 → 신규·변경 diff 리포트 → 업로드 위치 AskUserQuestion 승인 → 업로드(기존 파일은 content update로 ID·공유링크 보존). 삭제는 제안만(자동 삭제 금지), Drive→로컬 다운로드 범위 밖. gws 미설치 시 공식 docs 기반 설치 안내 출력 후 중단(자동 설치 안 함). googleworkspace/cli 공식 스킬/레시피 95종 카탈로그(llms.txt)를 references에 동봉 — 상황에 유용한 미설치 스킬을 npx skills add로 제안.", "author": { "name": "YoungjaeDev" diff --git a/plugins/gws-sync/CLAUDE.md b/plugins/gws-sync/CLAUDE.md index 69de33e6..ee5be042 100644 --- a/plugins/gws-sync/CLAUDE.md +++ b/plugins/gws-sync/CLAUDE.md @@ -1,32 +1,34 @@ # gws-sync Plugin -로컬 폴더 → Google Drive **단방향 제안형 동기화**. gws CLI(공식 googleworkspace/cli) 기반 — MCP가 아니라 CLI를 부른다. 인증(`gws auth login`)은 전제. +Local folder → Google Drive **one-way, proposal-based sync**. Built on the gws +CLI (the official googleworkspace/cli) — it calls the CLI, not an MCP server. +Authentication (`gws auth login`) is a prerequisite. ## Skill | Skill | Description | |-------|-------------| -| `gws-sync` | 매핑 설정(`.gws-sync.json`) 기억 → Drive 트리 탐색 → 신규·변경 diff 리포트 → **업로드 위치 AskUserQuestion 승인(필수)** → 업로드(기존 파일은 content update — 파일 ID·공유 링크·버전 히스토리 보존). 삭제는 제안만. | +| `gws-sync` | Remembers the mapping config (`.gws-sync.json`) → walks the Drive tree → produces a new/changed diff report → **requires AskUserQuestion approval of the upload location** → uploads (existing files use a content update, preserving the file ID, share link, and version history). Deletion is proposal-only. | -## 설계 원칙 (하드 룰) +## Design principles (hard rules) -1. **단방향** — 로컬 → Drive만. Drive 변경을 로컬로 내리지 않는다. -2. **제안형** — 모든 쓰기는 diff 리포트 + 사용자 승인 뒤에만. -3. **삭제 자동 실행 금지** — Drive 고아 파일은 목록으로 제안만. -4. **update ≠ 재업로드** — 기존 파일 갱신은 `files update --upload`(ID 유지). 새 파일을 만들어 링크를 깨지 않는다. +1. **One-way** — local → Drive only. Drive-side changes are never pulled back down to local. +2. **Proposal-based** — every write happens only after a diff report plus user approval. +3. **No automatic deletion** — orphaned Drive files are proposed as a list, never deleted. +4. **Update ≠ re-upload** — updating an existing file uses `files update --upload` (keeping the ID). It never creates a new file that would break the link. -## 의존 +## Dependencies -- `gws` CLI **필수** — 미설치 시 설치 안내(`npm install -g @googleworkspace/cli` + github.com/googleworkspace/cli) 출력 후 중단. 자동 설치하지 않는다. -- `references/gws-skills-llms.txt` — 공식 스킬 54종 + 레시피 41종 카탈로그. 사용자 상황에 맞는 미설치 스킬/레시피를 `npx skills add` 문구로 제안하는 인덱스. +- The `gws` CLI is **required** — if it is missing, print install guidance (`npm install -g @googleworkspace/cli` + github.com/googleworkspace/cli) and stop. Do not install it automatically. +- `references/gws-skills-llms.txt` — a catalog of the 54 official skills + 41 recipes. An index for proposing an uninstalled skill/recipe that fits the user's situation, via an `npx skills add` line. -## 구조 +## Structure ```text gws-sync/ ├── .claude-plugin/plugin.json -├── CLAUDE.md # 이 파일 +├── CLAUDE.md # this file └── skills/gws-sync/ - ├── SKILL.md # 0.전제 확인 → 1.매핑 설정 → 2.위치 승인 → 3.diff→승인→업로드 + ├── SKILL.md # 0. prerequisite check → 1. mapping config → 2. location approval → 3. diff → approval → upload └── references/gws-skills-llms.txt ``` diff --git a/plugins/gws-sync/skills/gws-sync/SKILL.md b/plugins/gws-sync/skills/gws-sync/SKILL.md index 72253676..6adbeb5e 100644 --- a/plugins/gws-sync/skills/gws-sync/SKILL.md +++ b/plugins/gws-sync/skills/gws-sync/SKILL.md @@ -3,19 +3,19 @@ name: gws-sync description: 로컬 폴더 → Google Drive 단방향 제안형 동기화 — gws CLI 기반(MCP 아님, 인증 전제). 매핑 설정 파일(.gws-sync.json)로 로컬↔Drive 폴더 대응을 기억하고, 실행 시 Drive 트리를 탐색해 신규·변경 diff 리포트를 만든 뒤, 업로드 위치를 AskUserQuestion으로 승인받아 업로드한다. 삭제는 제안만(자동 삭제 금지). gws 미설치면 공식 docs 설치 안내를 출력하고 중단. 트리거 — "Drive에 올려줘/동기화해줘", "이 폴더 Drive랑 맞춰줘", "산출물 Drive 갱신", "gws sync", "드라이브 업로드". 단발 파일 1개 업로드는 gws-drive-upload 스킬이 가볍다(설치돼 있으면 그쪽 제안). --- -# gws-sync — 로컬 → Drive 단방향 제안형 동기화 +# gws-sync — local → Drive one-way proposal-based sync -**설계 원칙**: ① 단방향(로컬 → Drive)만 — Drive 쪽 변경을 로컬로 내리지 않는다 ② 제안형 — 모든 쓰기는 diff 리포트 + 사용자 승인 뒤에만 ③ 삭제는 절대 자동 실행하지 않는다(제안만) ④ Drive 파일 갱신은 새 파일 생성이 아니라 **기존 파일 content update**(파일 ID 유지 — 공유 링크·버전 히스토리 보존). +**Design principles**: (1) One-way (local → Drive) only — never pull Drive-side changes back to local. (2) Proposal-based — every write happens only after a diff report plus user approval. (3) Never delete automatically (proposal only). (4) Updating a Drive file is a **content update of the existing file**, not a new-file creation (the file ID is kept, so share links and version history survive). -## 0. 전제 확인 (매 실행) +## 0. Prerequisite check (every run) -1. `gws --version` — **미설치면 중단**하고 설치 안내 출력: "gws CLI가 필요합니다. 설치: `npm install -g @googleworkspace/cli` 또는 공식 문서 github.com/googleworkspace/cli 참조. 설치 후 첫 사용이면 `gws auth setup`(1회) → `gws auth login`으로 인증하세요(`gcloud` 미설치 환경은 공식 README의 수동 OAuth 설정 참조)." (자동 설치하지 않는다 — 제안만.) -2. 인증·스코프 확인: 가벼운 읽기 호출(`gws drive files list --params '{"pageSize": 1}'`)이 실패하면 인증 안내 후 중단 — 첫 사용이면 `gws auth setup`, 이후는 `gws auth login`. **읽기 성공이 쓰기 스코프를 보장하지 않는다** — 업로드/업데이트 단계에서 권한 오류가 나면 drive 쓰기 스코프로 재인증하도록 안내(예: `gws auth login --scopes drive`, 정확한 플래그는 `gws auth --help` 확인). 읽기 검증만으로 쓰기 가능하다고 단정하지 않는다. -3. 유용 스킬 제안(선택): 작업 상황이 카탈로그의 다른 gws 스킬/레시피와 맞으면(예: 업로드 후 팀 공유 → recipe-share-folder-with-team) `references/gws-skills-llms.txt`에서 찾아 **설치 제안 문구**를 함께 출력한다. 설치 명령은 현재 `skills` CLI에서 정확한 형태를 확인한 뒤 제시한다(`references/gws-skills-llms.txt`의 형태를 그대로 쓰되, 미확인이면 "설치 방법은 skills CLI로 확인하세요"라고만). 제안만 하고 강제하지 않는다. +1. `gws --version` — **if missing, stop** and print install guidance: "gws CLI가 필요합니다. 설치: `npm install -g @googleworkspace/cli` 또는 공식 문서 github.com/googleworkspace/cli 참조. 설치 후 첫 사용이면 `gws auth setup`(1회) → `gws auth login`으로 인증하세요(`gcloud` 미설치 환경은 공식 README의 수동 OAuth 설정 참조)." (Do not install automatically — propose only.) +2. Confirm auth and scope: if a light read call (`gws drive files list --params '{"pageSize": 1}'`) fails, print auth guidance and stop — `gws auth setup` on first use, `gws auth login` thereafter. **A successful read does not guarantee write scope** — if the upload/update step hits a permission error, guide the user to re-authenticate with the drive write scope (e.g. `gws auth login --scopes drive`; confirm the exact flag with `gws auth --help`). Never assume write access from a read check alone. +3. Suggest useful skills (optional): if the task matches another gws skill/recipe in the catalog (e.g. share with the team after upload → recipe-share-folder-with-team), find it in `references/gws-skills-llms.txt` and print an **install-suggestion line** alongside. Confirm the exact install command form with the current `skills` CLI before presenting it (use the form in `references/gws-skills-llms.txt` verbatim, or if unconfirmed just say "설치 방법은 skills CLI로 확인하세요"). Suggest only — never force. -## 1. 매핑 설정 파일 — `.gws-sync.json` +## 1. Mapping config file — `.gws-sync.json` -로컬 repo 루트(또는 사용자 지정 위치)에 매핑을 기억한다: +Remember the mapping at the local repo root (or a user-specified location): ```json { @@ -31,35 +31,35 @@ description: 로컬 폴더 → Google Drive 단방향 제안형 동기화 — gw } ``` -- `files`는 로컬 파일명 → Drive 파일 ID 캐시. **캐시 ID는 힌트일 뿐 신뢰의 근거가 아니다** — 업데이트 전 반드시 §3-4에서 그 ID가 승인된 폴더 안에 있고·trashed 아니고·해당 로컬 파일명과 유일 매칭되는지 재확인한다(캐시가 stale하면 엉뚱한 Drive 파일을 덮어쓸 수 있다). 첫 업로드 후 자동 기록. -- 설정 파일이 없으면 §2의 위치 승인 플로우로 만들고, 승인된 매핑을 저장한다("다음부터는 안 묻고 이 폴더로" 여부도 함께 확인). +- `files` is a local-filename → Drive-file-ID cache. **A cached ID is only a hint, not a basis for trust** — before updating, always re-confirm in §3-4 that the ID sits inside the approved folder, is not trashed, and matches that local filename uniquely (a stale cache can overwrite the wrong Drive file). It is recorded automatically after the first upload. +- If the config file is absent, create it through the location-approval flow in §2 and store the approved mapping (also confirming whether to "skip the prompt and use this folder from now on"). -## 2. 업로드 위치 승인 (MANDATORY — AskUserQuestion) +## 2. Upload-location approval (MANDATORY — AskUserQuestion) -매핑이 없거나 사용자가 새 대상 폴더를 말한 경우: +When there is no mapping, or the user names a new target folder: -1. **Drive 트리 탐색** — 폴더 후보를 검색한다. Drive 쿼리 문법상 폴더 MIME는 정확한 값 `'application/vnd.google-apps.folder'`로 써야 하고(`mimeType = folder`는 매칭 안 됨), trashed 제외도 명시한다: +1. **Walk the Drive tree** — search for candidate folders. Drive query syntax requires the exact folder MIME value `'application/vnd.google-apps.folder'` (`mimeType = folder` does not match), and must exclude trashed items explicitly: ```bash - gws drive files list --params '{"q": "name contains '\''<이름>'\'' and mimeType = '\''application/vnd.google-apps.folder'\'' and trashed = false", "fields": "files(id,name,parents)", "supportsAllDrives": true, "includeItemsFromAllDrives": true}' + gws drive files list --params '{"q": "name contains '\'''\'' and mimeType = '\''application/vnd.google-apps.folder'\'' and trashed = false", "fields": "files(id,name,parents)", "supportsAllDrives": true, "includeItemsFromAllDrives": true}' ``` - 후보 폴더의 하위 목록을 확인해 맥락을 잡는다. -2. **AskUserQuestion으로 위치 제안·승인** — 후보 2~3개(+ "새 폴더 생성" 옵션)를 제시하고 사용자가 고른 위치만 쓴다. **승인 없이 업로드 금지.** 매핑이 이미 있으면 이 단계는 생략(설정이 곧 승인 기록). + Inspect each candidate folder's children to establish context. +2. **Propose and approve the location via AskUserQuestion** — present 2-3 candidates (plus a "create new folder" option) and write only to the location the user chooses. **No upload without approval.** If a mapping already exists, skip this step (the config is itself the approval record). -## 3. diff 리포트 → 승인 → 업로드 +## 3. diff report → approval → upload -1. **로컬 스캔**: 매핑의 `local` 폴더에서 `include` 패턴 파일 수집. -2. **Drive 스캔**: 대상 폴더로 **범위를 좁혀** 목록을 받는다 — parent 필터·trashed 제외·shared-drive 플래그·페이지네이션 필수(제약 없는 `files list`는 무관한 파일까지 끌어와 diff를 오염시킨다): +1. **Local scan**: collect files matching the `include` patterns under the mapping's `local` folder. +2. **Drive scan**: **narrow the scope** to the target folder and list it — a parent filter, trashed exclusion, the shared-drive flags, and pagination are all required (an unconstrained `files list` pulls in unrelated files and pollutes the diff): ```bash gws drive files list --params '{"q": "'\'''\'' in parents and trashed = false", "fields": "nextPageToken, files(id,name,size,modifiedTime,mimeType,parents)", "supportsAllDrives": true, "includeItemsFromAllDrives": true}' --page-all ``` -3. **diff 리포트** (표로 출력): - - **신규**: 로컬에만 있음 → `+upload` 대상 - - **변경**: 양쪽에 있고 로컬이 다름(크기 또는 로컬 mtime > Drive modifiedTime) → content update 대상 - - **동일**: 스킵 - - **Drive 고아**: Drive에만 있음 → **삭제 제안만** ("로컬에 없는 파일 N건 — 삭제는 직접 해주세요" + 목록). 자동 삭제 절대 금지. -4. **업데이트 대상 ID 재확인(MANDATORY)**: 각 '변경' 파일에 대해 2단계 스캔 결과에서 **승인된 폴더 안·trashed=false·해당 로컬 파일명과 정확히 1건 매칭**되는 Drive item 하나를 확정한다. 캐시 ID가 이 결과와 어긋나거나(폴더 밖·trashed·이름 불일치) 동명 파일이 여러 개면 **자동 진행을 멈추고 AskUserQuestion으로 대상 ID를 사용자에게 고르게 한다**. 확정된 ID로만 캐시를 갱신. -5. **승인**: 리포트를 보여주고 진행 여부 확인(신규/변경 건수가 0이면 "동기화 최신" 보고 후 종료). -5b. **승인 매니페스트 고정 (MANDATORY)**: 5의 승인 직후, 실제로 승인된 항목만을 **동결된 매니페스트**로 적는다. 각 항목은 `{local, action(new|update), target, size, mtime}` — `target`은 new면 대상 folderId, update면 4에서 확정한 fileId. 이후 업로드는 **이 매니페스트만** 읽는다. 승인과 실행 사이에 로컬을 다시 스캔해 새로 나타난 파일을 끼워 넣지 않는다 — 승인은 이 목록에 한해서만 유효하다. +3. **diff report** (print as a table): + - **New**: local-only → an `+upload` target + - **Changed**: present on both sides and locally different (size differs, or local mtime > Drive modifiedTime) → a content-update target + - **Identical**: skip + - **Drive orphan**: Drive-only → **proposal only** ("N files not present locally — please delete them yourself" + the list). Never delete automatically. +4. **Re-confirm update-target IDs (MANDATORY)**: for each "changed" file, from the §3-2 scan results pin down the single Drive item that is **inside the approved folder, trashed=false, and matches that local filename exactly once**. If the cached ID disagrees with that result (outside the folder, trashed, name mismatch) or several same-named files exist, **stop the automatic flow and use AskUserQuestion to let the user pick the target ID**. Update the cache only with the confirmed ID. +5. **Approval**: show the report and confirm whether to proceed (if the new/changed count is 0, report "already in sync" and exit). +5b. **Freeze the approval manifest (MANDATORY)**: immediately after the §5 approval, write only the actually-approved items into a **frozen manifest**. Each item is `{local, action(new|update), target, size, mtime}` — `target` is the destination folderId for `new`, or the fileId confirmed in §4 for `update`. Every subsequent upload reads **only this manifest**. Do not re-scan local between approval and execution to slip in newly-appeared files — the approval is valid only for this list. ```json {"approved": [ @@ -67,22 +67,22 @@ description: 로컬 폴더 → Google Drive 단방향 제안형 동기화 — gw {"local": "exports/notes.pdf", "action": "new", "target": "1aQthLJ...", "size": 20481, "mtime": 1720000100} ]} ``` -6. **실행 — 승인 매니페스트만 (바인딩)**: 매니페스트의 각 항목만 순서대로 처리한다. 각 항목 실행 **직전에** 로컬 파일과 대상 ID를 다시 읽어 매니페스트 값과 대조한다 — 파일이 사라졌거나·크기/mtime가 승인 시점과 달라졌거나·`update` 대상 ID가 §4 확정값과 어긋나면 **그 항목만 건너뛰지 말고 전체 실행을 멈추고**(abort) §3 재-diff·재승인으로 되돌린다(조용한 우회·부분 강행 금지). **매니페스트에 없는 파일은 어떤 경우에도 업로드하지 않는다.** - - 신규(My Drive 폴더): `gws drive +upload --parent ` → 반환 ID를 `files` 캐시에 기록. - - 신규(Shared Drive 폴더): `+upload` 헬퍼는 `supportsAllDrives`를 전달하지 않아 팀 Drive 업로드가 실패한다(upstream googleworkspace/cli #722). 대상 폴더가 Shared Drive면 raw create 경로로 우회 — `gws drive files create --params '{"supportsAllDrives": true}' --params-name-parents ...`(정확한 create 인자·부모 지정 문법은 `gws drive files create --help` 확인). 매핑의 `driveFolderId`가 Shared Drive 소속인지는 2단계 스캔의 `parents`/드라이브 조회로 판별. - - 변경: 4에서 확정한 ID로만 `gws drive files update --params '{"fileId": "", "supportsAllDrives": true}' --upload ` — 새 파일을 만들지 않고 기존 ID를 갱신(update는 My Drive·Shared Drive 모두 `supportsAllDrives`로 처리). -7. **검증**: 업로드 후 대상 폴더를 재조회해 건수·이름 확인, 결과 표 보고. +6. **Execute — approval manifest only (binding)**: process each manifest item in order. **Immediately before** executing each item, re-read the local file and target ID and compare them against the manifest values — if the file has disappeared, its size/mtime differs from approval time, or an `update` target ID disagrees with the §4-confirmed value, **do not skip just that item; abort the entire run** and return to §3 for a re-diff and re-approval (no silent workaround, no partial force-through). **Never upload a file absent from the manifest, under any circumstances.** + - New (My Drive folder): `gws drive +upload --parent ` → record the returned ID in the `files` cache. + - New (Shared Drive folder): the `+upload` helper does not pass `supportsAllDrives`, so team-Drive uploads fail (upstream googleworkspace/cli #722). If the target folder is a Shared Drive, route around it with the raw create path — `gws drive files create --params '{"supportsAllDrives": true}' --params-name-parents ...` (confirm the exact create arguments and parent-specification syntax with `gws drive files create --help`). Determine whether the mapping's `driveFolderId` belongs to a Shared Drive via the `parents`/drive lookup in the §3-2 scan. + - Changed: use only the ID confirmed in §4: `gws drive files update --params '{"fileId": "", "supportsAllDrives": true}' --upload ` — update the existing ID without creating a new file (update handles both My Drive and Shared Drive via `supportsAllDrives`). +7. **Verify**: after upload, re-query the target folder to confirm counts and names, and report the result as a table. -## 하드 룰 +## Hard rules -- 쓰기(upload/update)는 diff 리포트 + 승인 없이 실행하지 않는다. -- **업로드는 §5b 승인 매니페스트에 있는 항목만 대상으로 한다** — 매니페스트에 없는 파일은 업로드 금지, 매니페스트 값과 실물(로컬 파일·대상 ID)이 어긋나면 부분 강행하지 말고 abort 후 재승인. 승인 후 재스캔으로 목록을 늘리지 않는다. -- 삭제·이동·권한 변경은 이 스킬 범위 밖 — 제안 문구만. -- Drive → 로컬 다운로드(양방향)는 범위 밖. -- 대용량/다건이어도 한 파일씩 순차 업로드(부분 실패 시 어디까지 갔는지 보고). -- `.gws-sync.json`은 커밋 대상 여부를 사용자에게 확인(파일 ID가 내부 정보일 수 있음 — 공유 repo면 .gitignore 제안). +- Never run a write (upload/update) without a diff report plus approval. +- **Upload only items present in the §5b approval manifest** — never upload a file absent from the manifest; if a manifest value and reality (local file, target ID) disagree, do not force part of it through — abort and re-approve. Never grow the list by re-scanning after approval. +- Deletion, moving, and permission changes are out of scope for this skill — proposal text only. +- Drive → local download (two-way) is out of scope. +- Even for large or many-file runs, upload one file at a time sequentially (on partial failure, report how far it got). +- Confirm with the user whether `.gws-sync.json` should be committed (file IDs may be internal information — propose `.gitignore` for a shared repo). -## 의존·참조 +## Dependencies / references -- `gws` CLI(필수, 미설치 시 설치 안내 후 중단) — 전역 플래그·인증·출력 형식은 gws-shared 스킬(설치 시) 또는 `gws --help`. -- `references/gws-skills-llms.txt` — 공식 스킬/레시피 95종 카탈로그(서비스 54 + 레시피 41). 상황 제안용 인덱스. +- `gws` CLI (required; if missing, print install guidance and stop) — global flags, auth, and output format live in the gws-shared skill (if installed) or `gws --help`. +- `references/gws-skills-llms.txt` — a catalog of the 95 official skills/recipes (54 services + 41 recipes). An index for situational suggestions. diff --git a/plugins/mem0-ops/.claude-plugin/plugin.json b/plugins/mem0-ops/.claude-plugin/plugin.json index cebcc701..2f09ad1c 100644 --- a/plugins/mem0-ops/.claude-plugin/plugin.json +++ b/plugins/mem0-ops/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "mem0-ops", - "version": "0.1.1", + "version": "0.1.2", "description": "Fleet-level mem0 diagnostics and cleanup — complements the upstream mem0 plugin (which owns per-project quality). fleet-scan reports per-app noise ratio, junk app_id candidates, and app/user_id fragmentation across all apps; doctor checks config posture (MEM0_RERANK env, ~/.mem0/settings.json auto_save precedence trap, project decay flag, hook timeout budget, identity fragmentation); cleanup does backup-then-delete by metadata.type or whole junk app behind a dry-run default plus a skill-layer per-app confirmation gate (the script alone gates on --execute only). stdlib-only REST scripts, zero LLM cost for the deterministic parts.", "skills": [ "./skills/fleet-scan", diff --git a/plugins/mem0-ops/.codex-plugin/plugin.json b/plugins/mem0-ops/.codex-plugin/plugin.json index d8e1d9cf..eff23304 100644 --- a/plugins/mem0-ops/.codex-plugin/plugin.json +++ b/plugins/mem0-ops/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "mem0-ops", - "version": "0.1.1", + "version": "0.1.2", "description": "Fleet-level mem0 diagnostics and cleanup — complements the upstream mem0 plugin (which owns per-project quality). fleet-scan reports per-app noise ratio, junk app_id candidates, and app/user_id fragmentation across all apps; doctor checks config posture (MEM0_RERANK env, ~/.mem0/settings.json auto_save precedence trap, project decay flag, hook timeout budget, identity fragmentation); cleanup does backup-then-delete by metadata.type or whole junk app behind a dry-run default plus a skill-layer per-app confirmation gate (the script alone gates on --execute only). stdlib-only REST scripts, zero LLM cost for the deterministic parts.", "author": { "name": "YoungjaeDev" diff --git a/plugins/mem0-ops/CLAUDE.md b/plugins/mem0-ops/CLAUDE.md index 4034e7fb..6c15b047 100644 --- a/plugins/mem0-ops/CLAUDE.md +++ b/plugins/mem0-ops/CLAUDE.md @@ -1,15 +1,17 @@ # mem0-ops -플릿 레벨 mem0 진단·정리. upstream `mem0@mem0-plugins`(프로젝트 내부 품질: -health/memory-reviewer/stats/dream)와 역할 분리 — 이 플러그인은 app_id **간** -운영만 담당한다. 기능 복제 금지. +Fleet-level mem0 diagnostics and cleanup. Roles are split from the upstream +`mem0@mem0-plugins` (which owns in-project memory quality: +health/memory-reviewer/stats/dream) — this plugin handles only cross-`app_id` +operations. Do not duplicate upstream functionality. -| Skill | 역할 | +| Skill | Role | |---|---| -| `fleet-scan` | 전 앱 노이즈율·쓰레기 후보·파편화 리포트 (read-only) | -| `doctor` | 설정 자세 점검 — rerank env, auto_save 파일 우선순위 함정, decay, 훅 timeout, 정체성 파편화 (제안만) | -| `cleanup` | 백업→타입/앱 단위 삭제. dry-run 기본, `--execute` + 스킬 레이어 사용자 확인(스크립트 단독 실행은 `--execute`만 게이트) | +| `fleet-scan` | Fleet-wide noise-rate, junk-candidate, and fragmentation report (read-only) | +| `doctor` | Configuration-posture checks — rerank env, the auto_save file-precedence trap, decay, hook timeout, identity fragmentation (suggestions only) | +| `cleanup` | Backup, then delete by type or app. Dry-run by default; `--execute` plus a skill-layer user confirmation gates it (running the script standalone is gated by `--execute` alone) | -스크립트는 stdlib + REST 직결(`scripts/_api.py`). upstream 스크립트/venv 의존 -없음. `MEM0_API_KEY` 필수. 근거 스펙: +The scripts are stdlib-only and talk to the REST API directly +(`scripts/_api.py`), with no dependency on the upstream scripts or venv. +`MEM0_API_KEY` is required. Design spec: `docs/superpowers/specs/2026-07-07-mem0-ops-plugin-design.md`. diff --git a/plugins/notebook/.claude-plugin/plugin.json b/plugins/notebook/.claude-plugin/plugin.json index 37564871..ec1c4063 100644 --- a/plugins/notebook/.claude-plugin/plugin.json +++ b/plugins/notebook/.claude-plugin/plugin.json @@ -1,5 +1,5 @@ { "name": "notebook", - "version": "1.0.1", + "version": "1.0.2", "description": "Safe Jupyter notebook editing" } diff --git a/plugins/notebook/.codex-plugin/plugin.json b/plugins/notebook/.codex-plugin/plugin.json index dcc99350..87698f3a 100644 --- a/plugins/notebook/.codex-plugin/plugin.json +++ b/plugins/notebook/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "notebook", - "version": "1.0.1", + "version": "1.0.2", "description": "Safe Jupyter notebook editing", "author": { "name": "YoungjaeDev" diff --git a/plugins/notebook/skills/edit-notebook/SKILL.md b/plugins/notebook/skills/edit-notebook/SKILL.md index 99d76a72..d779d986 100644 --- a/plugins/notebook/skills/edit-notebook/SKILL.md +++ b/plugins/notebook/skills/edit-notebook/SKILL.md @@ -11,7 +11,7 @@ Edit Jupyter Notebook files using NotebookEdit tool only. ### Tool Selection - .ipynb = NotebookEdit only -- `Edit`, `Write`, `Bash(sed/cat)` 사용 금지 +- Never use `Edit`, `Write`, or `Bash(sed/cat)` on `.ipynb` ### Cell Insertion: cell_id Tracking (Required) diff --git a/plugins/project-init/.claude-plugin/plugin.json b/plugins/project-init/.claude-plugin/plugin.json index a6303707..32b70d91 100644 --- a/plugins/project-init/.claude-plugin/plugin.json +++ b/plugins/project-init/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "project-init", - "version": "0.4.3", + "version": "0.4.4", "description": "Agent-harness project lifecycle. `new` — one-shot first-day bootstrap (interview, .claude/ scaffold, minimal CLAUDE.md, AGENTS.md with Codex GitHub cloud reviewer guidelines in general/ml/web variants, README/CHANGELOG seed, gh repo create + initial push) behind a hardened preflight guard that refuses a non-empty cwd. `wiring` — its inverse for existing repos: a read-only 14-axis setup diagnostic (FAIL / WARN / ASK / INFO / SKIP / OK) covering guidance files, .claude/rules paths: scoping defeated by @import, llm-wiki layout + staging backlog, Serena onboarding, memory posture, MCP duplicate registration, Codex CLI posture + AGENTS.md byte budget, spec homes, gws-sync, .tmp, core.hooksPath, .gitignore coverage. ASK answers persist to .claude/state/wiring.json. Shared read-only detector: scripts/project_state.sh.", "author": { "name": "YoungjaeDev" diff --git a/plugins/project-init/.codex-plugin/plugin.json b/plugins/project-init/.codex-plugin/plugin.json index 29492f0c..4037385c 100644 --- a/plugins/project-init/.codex-plugin/plugin.json +++ b/plugins/project-init/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "project-init", - "version": "0.4.3", + "version": "0.4.4", "description": "Agent-harness project lifecycle. `new` — one-shot first-day bootstrap (interview, .claude/ scaffold, minimal CLAUDE.md, AGENTS.md with Codex GitHub cloud reviewer guidelines in general/ml/web variants, README/CHANGELOG seed, gh repo create + initial push) behind a hardened preflight guard that refuses a non-empty cwd. `wiring` — its inverse for existing repos: a read-only 14-axis setup diagnostic (FAIL / WARN / ASK / INFO / SKIP / OK) covering guidance files, .claude/rules paths: scoping defeated by @import, llm-wiki layout + staging backlog, Serena onboarding, memory posture, MCP duplicate registration, Codex CLI posture + AGENTS.md byte budget, spec homes, gws-sync, .tmp, core.hooksPath, .gitignore coverage. ASK answers persist to .claude/state/wiring.json. Shared read-only detector: scripts/project_state.sh.", "author": { "name": "YoungjaeDev" diff --git a/plugins/project-init/CLAUDE.md b/plugins/project-init/CLAUDE.md index a4809cd1..9335f318 100644 --- a/plugins/project-init/CLAUDE.md +++ b/plugins/project-init/CLAUDE.md @@ -1,79 +1,79 @@ # Project-Init Plugin -프로젝트의 **에이전트 하네스 lifecycle** 을 orchestrate. 두 방향이 대칭을 이룬다. +Orchestrates a project's **agent-harness lifecycle**. The two directions are symmetric. -- `new` — Day-1 셋업 (`.claude/`, CLAUDE.md, AGENTS.md, README/CHANGELOG, gh repo create+push). **빈 디렉토리 전용.** -- `wiring` — 이미 존재하는 repo 의 하네스 설정 진단. **`new` 의 역방향.** read-only 탐지 후 `AskUserQuestion` 게이트 뒤에서만 수정. +- `new` — Day-1 setup (`.claude/`, CLAUDE.md, AGENTS.md, README/CHANGELOG, gh repo create + push). **Empty directories only.** +- `wiring` — diagnoses the harness config of an already-existing repo. **The inverse of `new`.** Read-only detection, then edits only behind an `AskUserQuestion` gate. ## Surfaces | Surface | Entry | Description | |---------|-------|-------------| -| Command | `/project-init:new` | 명시적 사용자 호출 — bootstrap 의 primary surface. | -| Skill | `new` | Codex (및 Claude Code) 의 capability-discovery 용. description 이 좁게 잡혀 "bootstrap a new project in this empty dir" 류만 매치. | -| Skill | `wiring` | 기존 repo 진단. command surface 없음 — `/project-init:wiring` 스킬 호출로 충분하고, command 는 Codex 로 emit 되지 않아 본문만 이중화된다. | +| Command | `/project-init:new` | Explicit user invocation — the primary surface for bootstrap. | +| Skill | `new` | For capability discovery by Codex (and Claude Code). The description is scoped narrowly so only phrases like "bootstrap a new project in this empty dir" match. | +| Skill | `wiring` | Diagnoses an existing repo. No command surface — a `/project-init:wiring` skill call is enough, and a command would not be emitted to Codex, only duplicating the body. | -`new` 의 두 surface 는 본문 첫 블록에 **preflight hard guard** 를 둔다 — `.git/` / `.claude/` / source-file 이 cwd 에 하나라도 있으면 abort. description 기반 매칭에만 기대지 않고 runtime 에서 강제. `wiring` 에는 이 가드가 없다 (정의상 비어있지 않은 repo 에서만 의미). +Both surfaces of `new` put a **preflight hard guard** in the first block of the body — if `.git/`, `.claude/`, or a source file exists anywhere in cwd, abort. It does not rely on description-based matching alone; it enforces at runtime. `wiring` has no such guard (by definition it is only meaningful in a non-empty repo). -## 탐지 SSOT +## Detection SSOT -`scripts/project_state.sh` 가 프로젝트 상태 탐지를 **혼자** 담당한다. 순수 read-only, JSON 한 덩어리 출력. +`scripts/project_state.sh` is **solely** responsible for project-state detection. Pure read-only, emitting a single JSON blob. -- `wiring` 은 14 축 전체를 소비한다. 그중 4 축은 "파일이 있나"가 아니라 **"그 설정이 실제로 발효하나"** 를 본다 — `core.hooksPath`(clone 마다 켜야 함), `.claude/rules` 의 `paths:` 스코핑을 `@import` 가 무력화했는지, 같은 MCP 서버가 두 user-scope 파일에 등록돼 한쪽 정의가 통째로 버려지는지, Codex `AGENTS.md` 가 `project_doc_max_bytes` 예산 안에 드는지. -- 결함이 아니라 **결정**인 축(`git remote`, `gws-sync`)은 `ASK` 로 낸다. 답은 `.claude/state/wiring.json` 의 `answers` 에 적히고 스크립트가 그대로 실어 보낸다 — 스킬은 이미 답한 항목을 다시 묻지 않는다. 값은 머신마다 다르므로(Drive 폴더 id 등) gitignored state 에 남고, `CLAUDE.md` 에는 **경로 포인터 한 줄**만 둔다. 매번 짖는 경고는 사람이 무시하게 되고, 그러면 진짜 `FAIL` 도 같이 묻힌다. -- **`ASK` 는 반드시 묻는 단계를 가진다** (Step 3.5). 보고서에 `(unanswered)` 로 찍기만 하고 묻는 곳이 없으면 답이 기록되지 않고 다음 실행에서 같은 줄이 그대로 반복된다 — 클래스가 장식이 된다. 답하지 않고 닫은 질문은 키를 남기지 않는다. 기록되지 않은 `ASK` 는 기록된 "아니오" 가 아니다. -- 억제 조건은 **한 곳에만** 쓴다. `gws_sync` 의 판정은 답변만으로 정해지지 않고 `.gws-sync.json` 존재와 `gws` CLI 유무를 함께 읽는다 — 답을 기록한 뒤에도 파일시스템이 움직인다. 같은 조건을 판정표·산문·질문 단계에 세 번 적으면 세 번 어긋난다. -- **고아 MCP 등록은 다루지 않는다.** 삭제된 플러그인이 남긴 서버는 사용 이력이 있어야 판정 가능해 내장 `/doctor` 의 영역이다. 반면 **중복 등록**은 두 파일 키의 교집합이라 순수 계산이다 — 결정론으로 못 잡는 걸 잡는 척하지 않는다. -- `idempotent-seed.sh diagnose` 는 이 스크립트를 감싸 legacy 출력 형태(`cwd`/`dir_name`/`git`/`seeded`/`code_signal`)만 골라낸다. 탐지 로직을 다시 구현하지 않는다. -- **`new` 의 Step 0 hard guard 는 여기에 흡수하지 않는다.** 가드는 의존성 0 (순수 `find`) 이고 `PLUGIN_ROOT` 리졸버보다 **먼저** 돌아야 한다. 스크립트 호출로 바꾸면 "PLUGIN_ROOT 해석 실패 시 가드가 조용히 실행되지 않는" 실패 모드가 새로 생긴다. 안전 장치는 lazy-load 뒤로 옮기지 않는다. +- `wiring` consumes all 14 axes. Four of them look at not "does the file exist" but **"does the config actually take effect"** — `core.hooksPath` (must be turned on per clone), whether an `@import` has defeated the `paths:` scoping of `.claude/rules`, whether the same MCP server registered in two user-scope files causes one definition to be discarded wholesale, and whether Codex `AGENTS.md` fits within the `project_doc_max_bytes` budget. +- An axis that is a **decision** rather than a defect (`git remote`, `gws-sync`) is emitted as `ASK`. The answer is written to `answers` in `.claude/state/wiring.json` and the script carries it forward as-is — the skill never re-asks an already-answered item. Because values differ per machine (Drive folder ids, etc.), they stay in gitignored state, and `CLAUDE.md` keeps only a **one-line path pointer**. A warning that barks every run trains people to ignore it, and then a real `FAIL` gets buried with it. +- **An `ASK` must have a step that actually asks** (Step 3.5). If it is only stamped `(unanswered)` in the report with nowhere to ask, no answer is recorded and the next run repeats the same line verbatim — the class becomes decoration. A question closed without an answer leaves no key. An unrecorded `ASK` is not a recorded "no". +- Write a suppression condition in **one place only**. The `gws_sync` verdict is not decided by the answer alone — it also reads whether `.gws-sync.json` exists and whether the `gws` CLI is present, so the filesystem moves even after the answer is recorded. Writing the same condition three times across the verdict table, the prose, and the question step means it drifts three ways. +- **Orphan MCP registrations are not handled.** A server left behind by a deleted plugin needs usage history to judge, so it is the built-in `/doctor`'s territory. A **duplicate registration**, by contrast, is the intersection of two files' keys, so it is pure computation — do not pretend to catch what determinism cannot. +- `idempotent-seed.sh diagnose` wraps this script and picks out only the legacy output shape (`cwd`/`dir_name`/`git`/`seeded`/`code_signal`). It does not re-implement the detection logic. +- **The Step 0 hard guard of `new` is not absorbed here.** The guard has zero dependencies (pure `find`) and must run **before** the `PLUGIN_ROOT` resolver. Turning it into a script call would introduce a new failure mode where "the guard silently does not run if PLUGIN_ROOT resolution fails". A safety device is never moved behind a lazy-load. -`find` 는 "없음" 을 exit 1 로 표현한다. `set -o pipefail` 아래서 `find ... | wc -l` 는 정상적인 빈 결과에 스크립트를 죽인다. 모든 `find` 는 `find_or_empty` / `count_files` 헬퍼를 거치고, `code_signal` 은 `head` 로 인한 SIGPIPE 오탐을 피하려고 `-print -quit` 를 쓴다. +`find` expresses "not found" as exit 1. Under `set -o pipefail`, `find ... | wc -l` kills the script on a legitimate empty result. Every `find` goes through the `find_or_empty` / `count_files` helpers, and `code_signal` uses `-print -quit` to avoid a `head`-induced SIGPIPE false positive. -`jq` 도 같은 함정을 판다. 손상된 사용자 설정 파일 하나에 `jq` 가 non-zero 로 끝나면 그 실패가 명령 치환을 타고 올라와 `set -e` 가 스크립트를 죽인다 — 한 축을 판정하지 못하는 대신 진단이 통째로 사라지고, 사용자는 출력조차 못 본다. 축 하나의 실패는 그 축 안에 가두고 (`mcp.unreadable` 처럼) 나머지 진단은 계속 낸다. 그리고 **"못 봤다" 를 "문제 없다" 로 보고하지 않는다.** +`jq` digs the same pit. If `jq` exits non-zero on a single corrupted user config file, that failure rides up through command substitution and `set -e` kills the script — instead of failing to judge one axis, the whole diagnostic vanishes and the user sees no output at all. Confine one axis's failure to that axis (like `mcp.unreadable`) and keep emitting the rest of the diagnostic. And **never report "did not see it" as "no problem".** -외부 도구 값을 읽어 `jq --argjson` 에 넘길 때는 원문 형식을 믿지 않는다. TOML 은 값 뒤 인라인 주석과 정수의 `_` 구분자를 허용하므로, `sed` 로 긁어낸 `65536 # bytes` 는 유효한 설정이면서 유효하지 않은 JSON 이다. 숫자는 정규화 후 전부 숫자인지 확인하고, 아니면 문서화된 기본값으로 떨어진다. +When reading an external tool's value to pass to `jq --argjson`, do not trust the source format. TOML allows an inline comment after a value and a `_` separator in integers, so `65536 # bytes` scraped by `sed` is a valid config yet invalid JSON. Normalize numbers and confirm they are all digits; otherwise fall back to the documented default. -Codex 설정 위치는 `${CODEX_HOME:-$HOME/.codex}` 다 (`codex --help`). `$HOME/.codex` 를 하드코딩하면 `CODEX_HOME` 을 쓰는 머신에서 `config: false` 로 보고되어 approval/sandbox 자세와 doc-budget 판정이 통째로 사라진다. +The Codex config location is `${CODEX_HOME:-$HOME/.codex}` (`codex --help`). Hardcoding `$HOME/.codex` reports `config: false` on a machine that uses `CODEX_HOME`, wiping out the approval/sandbox posture and doc-budget verdicts wholesale. -## 원칙 +## Principles -- **Preflight hard guard is non-negotiable**: `commands/new.md` 와 `skills/new/SKILL.md` 양쪽 Step 0 에 동일한 가드가 박혀 있다. description 만으로 잘못된 트리거를 막을 수 없다는 전제 — 모델이 description 을 잘못 해석해도 runtime 이 막는다. 가드 제거는 사용자의 명시적 (high-friction, 의도적) 결정이어야 한다. -- **wiring 은 남의 영역을 진단하지 않는다**: 위키 페이지 건강도는 `/llm-wiki:lint-wiki`, mem0 스토어/설정 자세는 `/mem0-ops:doctor` 가 소유한다. wiring 은 파일시스템 신호만 본다 — "위키가 있는가 / 레이아웃이 맞는가 / 미드레인 캡처가 쌓였는가" 까지. 겹치면 두 진단이 서로 다른 답을 내는 날이 온다. -- **결함마다 담당 스킬을 지목한다**: 다음 행동이 없는 판정은 노이즈다. 기계적·되돌릴 수 있는 수정 (`.gitignore` 라인, `.tmp/` 생성, `core.hooksPath`, serena `project_name`) 만 wiring 이 직접 고치고, 판단이 필요한 것 (`.staging` 큐레이션, wiki bootstrap/migrate, CLAUDE.md 저작, spec 이전, Serena 온보딩, mem0 변경) 은 전부 위임한다. -- **Minimal seeding, explicit follow-ups**: Day-1 에 필요한 것만 시드. tech-stack 기반 rules 생성과 wiki 도메인 인터뷰는 **호출 X, 안내만**. 빈 프로젝트에 generic 콘텐츠 만들면 사용자 덮어쓰기 비용 발생. -- **Owner gate is mandatory**: 사용자가 personal + 다중 org 컨텍스트라 owner 자동 결정 금지. `AskUserQuestion` 으로 명시 선택. -- **Codex GitHub reviewer surface**: AGENTS.md `## Review guidelines` 섹션이 Codex GitHub cloud reviewer 가 자동으로 읽는 영역. **레포 생성 시점에 시드**해야 첫 PR 부터 효과. -- **Idempotent re-runs**: 같은 디렉토리에서 두 번째 호출 시 기존 파일 보존 + 단계 skip + 안내 메시지. 절대 덮어쓰지 않음. (단, hard guard 가 .git/.claude 존재만으로도 abort 시키므로 일반 경로에서는 idempotent 재실행이 발생하지 않는다 — 가드를 우회한 partial seed 회복 경로에서만 의미.) +- **Preflight hard guard is non-negotiable**: the same guard is embedded in Step 0 of both `commands/new.md` and `skills/new/SKILL.md`. The premise is that a description alone cannot block a wrong trigger — even if the model misreads the description, runtime blocks it. Removing the guard must be an explicit (high-friction, deliberate) user decision. +- **wiring does not diagnose another owner's territory**: wiki-page health is owned by `/llm-wiki:lint-wiki`, and mem0 store/config posture by `/mem0-ops:doctor`. wiring looks only at filesystem signals — "does a wiki exist / is the layout right / has mid-drain capture piled up". Overlap means the day comes when two diagnostics give different answers. +- **Name the owning skill for each defect**: a verdict with no next action is noise. wiring directly fixes only mechanical, reversible edits (a `.gitignore` line, creating `.tmp/`, `core.hooksPath`, serena `project_name`); anything needing judgment (`.staging` curation, wiki bootstrap/migrate, CLAUDE.md authoring, spec migration, Serena onboarding, mem0 changes) is delegated. +- **Minimal seeding, explicit follow-ups**: seed only what Day 1 needs. Tech-stack-based rule generation and the wiki-domain interview are **not invoked, only pointed to**. Generating generic content in an empty project imposes an overwrite cost on the user. +- **Owner gate is mandatory**: since the user has a personal + multiple-org context, never auto-decide the owner. Require an explicit choice via `AskUserQuestion`. +- **Codex GitHub reviewer surface**: the AGENTS.md `## Review guidelines` section is what the Codex GitHub cloud reviewer reads automatically. It must be **seeded at repo-creation time** to take effect from the first PR. +- **Idempotent re-runs**: on a second invocation in the same directory, preserve existing files + skip steps + print a notice. Never overwrite. (But since the hard guard aborts on the mere presence of `.git`/`.claude`, an idempotent re-run does not occur on the normal path — it only matters on the recovery path for a partial seed that bypassed the guard.) -## 파일 구성 +## File layout ```text plugins/project-init/ ├── .claude-plugin/plugin.json -├── commands/new.md # 명시적 슬래시 surface (preflight guard + 포인터) +├── commands/new.md # explicit slash surface (preflight guard + pointer) ├── skills/ -│ ├── new/SKILL.md # bootstrap 스킬 surface (동일 preflight guard + 포인터) -│ └── wiring/SKILL.md # 기존 repo 진단 (read-only 탐지 + 게이트 수정) +│ ├── new/SKILL.md # bootstrap skill surface (same preflight guard + pointer) +│ └── wiring/SKILL.md # existing-repo diagnostic (read-only detection + gated edits) ├── references/ -│ ├── new-procedure.md # 본문 (Phase 0–7) — 두 surface 가 공유 +│ ├── new-procedure.md # the body (Phase 0–7) — shared by both surfaces │ ├── codex-review-discovery.md # AGENTS.md vs /review CLI -│ └── gh-repo-create-flow.md # owner 추론 + visibility 결정 -├── assets/ # 출력물에 직접 들어가는 템플릿 +│ └── gh-repo-create-flow.md # owner inference + visibility decision +├── assets/ # templates that go directly into the output │ ├── AGENTS.review-guidelines.md # general variant (base) │ ├── AGENTS.review-guidelines.ml.md # ML/data variant -│ ├── AGENTS.review-guidelines.web.md # 웹/풀스택 variant +│ ├── AGENTS.review-guidelines.web.md # web/full-stack variant │ ├── README.minimal.md │ └── CHANGELOG.initial.md ├── scripts/ │ ├── infer-github-context.sh # gh api user + orgs -│ ├── idempotent-seed.sh # 충돌 가드 + .claude/ + .llmwiki/ 시드 (diagnose = 래퍼) -│ └── project_state.sh # 탐지 SSOT — read-only 14 축 JSON +│ ├── idempotent-seed.sh # conflict guard + .claude/ + .llmwiki/ seed (diagnose = wrapper) +│ └── project_state.sh # detection SSOT — read-only 14-axis JSON └── CLAUDE.md # this file ``` ## Preflight guard contract -`commands/new.md` 와 `skills/new/SKILL.md` Step 0 에 동일한 POSIX shell 블록: +The same POSIX shell block sits in Step 0 of `commands/new.md` and `skills/new/SKILL.md`: ```bash FIRST_EXISTING=$(find . -mindepth 1 -maxdepth 5 \ @@ -94,7 +94,7 @@ fi - **Abort message**: surfaces cwd + the first offending entry + a redirect to `/rules-forge:write-rules` or `/llm-wiki:bootstrap-wiki` for the "scaffold an existing project" case. - **Non-POSIX hosts**: PowerShell-default environments must invoke via `bash -c ''` (Git Bash / WSL / Cygwin). The intent of the check, not the literal shell, is what matters — equivalent PowerShell rewrites are acceptable as long as they refuse the same conditions. -수정할 때는 두 파일 양쪽을 동시에 업데이트해야 한다. 한쪽만 바꾸면 surface 간 동작이 갈린다. +When modifying it, update both files at once. Changing only one makes the surfaces diverge in behavior. ## Cross-runtime plugin root resolution @@ -118,43 +118,43 @@ fi - Under **Codex 0.135**, no equivalent env var is currently exposed, so the resolver falls back to `~/.codex/plugins/cache//project-init//`. Users can override with `CODEX_PLUGIN_CACHE` or set `PLUGIN_ROOT` directly. - All subsequent bash blocks reference `${PLUGIN_ROOT}/scripts/...` and `${PLUGIN_ROOT}/assets/...`. Adding a new asset / script means updating only the procedure file — no per-surface duplication. -## Placeholder 규약 +## Placeholder convention -assets/ 의 템플릿은 다음 placeholder 만 사용한다 (sed 치환): +The templates under `assets/` use only these placeholders (sed substitution): -| Placeholder | 의미 | +| Placeholder | Meaning | |-------------|------| -| `{{PROJECT_NAME}}` | 프로젝트 이름 (Phase 1 응답) | -| `{{ONE_LINER}}` | 한 줄 description | -| `{{OWNER}}` | personal account 또는 org 이름 | +| `{{PROJECT_NAME}}` | project name (Phase 1 answer) | +| `{{ONE_LINER}}` | one-line description | +| `{{OWNER}}` | personal account or org name | | `{{LICENSE}}` | MIT / Apache-2.0 / GPL-3.0 / None | -| `{{YEAR}}` | 현재 연도 | +| `{{YEAR}}` | current year | -추가 placeholder 도입 시 `references/new-procedure.md` Phase 4/5 의 sed 라인을 함께 업데이트. +When introducing a new placeholder, update the sed lines in Phase 4/5 of `references/new-procedure.md` as well. -## AGENTS.md Variant 정책 +## AGENTS.md variant policy -3 개 파일은 동일한 골격을 공유한다: +The three files share the same skeleton: -1. `## Project context` — `{{PROJECT_NAME}}` + `{{ONE_LINER}}` (1-2 줄) -2. `## Build / Test / Lint` — 자리 표시자 TODO -3. `## Review guidelines` — **Codex 클라우드 리뷰어가 읽는 섹션** - - `### Do not flag` (린터 영역 — 도구가 처리) +1. `## Project context` — `{{PROJECT_NAME}}` + `{{ONE_LINER}}` (1-2 lines) +2. `## Build / Test / Lint` — placeholder TODO +3. `## Review guidelines` — **the section the Codex cloud reviewer reads** + - `### Do not flag` (linter territory — handled by tooling) - `### P0 — Correctness / Security` - `### P1 — Performance / Maintainability` - - `### Domain-specific` (variant 별로 다름; general 은 TODO 만) + - `### Domain-specific` (differs per variant; general has only a TODO) -variant 차이는 `### Domain-specific` 섹션 + `### P0` / `### P1` 에 도메인별 1-2 항목 추가. **base 위에 도메인 섹션만 다르게** — 코드 중복 최소화. +The variant difference is the `### Domain-specific` section plus 1-2 domain-specific items added to `### P0` / `### P1`. **Only the domain sections differ on top of the base** — minimizing code duplication. ## Out of Scope -- CI/CD workflow seed (`.github/workflows/`) — variant 별 다양성 너무 큼 -- Pre-commit hook seed — 같은 이유 -- Boilerplate auto-download (cookiecutter, copier) — `Skill("code-scout:research-orchestrator")` 별도 호출 -- Multi-language 인터뷰 분기 — 한/영 혼용 단일 버전 유지 +- CI/CD workflow seed (`.github/workflows/`) — too much per-variant variety +- Pre-commit hook seed — same reason +- Boilerplate auto-download (cookiecutter, copier) — a separate `Skill("code-scout:research-orchestrator")` call +- Multi-language interview branching — a single mixed Korean/English version is maintained -## 참조 +## References - Plugin versioning rules: `.claude/rules/plugin-versioning.md` - Codex GitHub integration: -- 관련 follow-up: `/rules-forge:write-rules`, `/llm-wiki:bootstrap-wiki` +- Related follow-ups: `/rules-forge:write-rules`, `/llm-wiki:bootstrap-wiki` diff --git a/plugins/project-init/commands/new.md b/plugins/project-init/commands/new.md index 715edd1a..405c1a7e 100644 --- a/plugins/project-init/commands/new.md +++ b/plugins/project-init/commands/new.md @@ -4,13 +4,13 @@ description: First-day project bootstrap — interview, .claude/ scaffold, CLAUD # /project-init:new -새 디렉토리에서 한 번 호출해 "Day 1 ready" 프로젝트를 만든다 — 인터뷰 → 로컬 시드 → gh 레포 생성 → 초기 커밋/푸시. +Called once in a new directory to produce a "Day 1 ready" project — interview → local seed → gh repo create → initial commit/push. -> **Trigger surface**: 명시적 user invocation 만. 자동 트리거 없음 (잘못된 디렉토리에서 실행되면 위험). +> **Trigger surface**: explicit user invocation only. No automatic trigger (running it in the wrong directory is dangerous). ## Step 0 — Preflight hard guard (NON-NEGOTIABLE, runs before any other body content) -이 가드는 `references/new-procedure.md` 의 Phase 0 보다 먼저 실행된다. 비어있지 않은 디렉토리에서는 abort 한다. +This guard runs before Phase 0 of `references/new-procedure.md`. It aborts in a non-empty directory. ```bash # Hard guard — refuses to run if cwd contains ANYTHING beyond ignorable OS junk. @@ -40,10 +40,10 @@ The legacy Phase 0 idempotency guard (in the procedure file) is now redundant fo ## Step 1 — Procedure -가드를 통과하면 전체 Phase 0–7 를 따른다. 본문은 이 플러그인의 `references/new-procedure.md` 에 있다 — `new` skill 도 동일 파일을 가리킨다. Claude Code 에서는 `${CLAUDE_PLUGIN_ROOT}/references/new-procedure.md` 로 해석되고, Codex 에서는 plugin cache 디렉토리 기준 동일 상대 경로 (`references/new-procedure.md`) 로 해석된다. +Once the guard passes, follow the full Phase 0–7. The body lives in this plugin's `references/new-procedure.md` — the `new` skill points to the same file. Under Claude Code it resolves to `${CLAUDE_PLUGIN_ROOT}/references/new-procedure.md`; under Codex it resolves to the same relative path (`references/new-procedure.md`) against the plugin cache directory. -Reference에 포함된 내용: -- Phase 0 — Preflight (gh auth, identity, owner candidates 추출). +What the reference covers: +- Phase 0 — Preflight (gh auth, identity, owner-candidate extraction). - Phase 1 — Project identity interview (name / owner / visibility / license, batched AskUserQuestion). - Phase 2 — `.claude/` + `.llmwiki/` scaffold. - Phase 3 — CLAUDE.md minimal stub. diff --git a/plugins/project-init/references/codex-review-discovery.md b/plugins/project-init/references/codex-review-discovery.md index 1324f821..e6de08b7 100644 --- a/plugins/project-init/references/codex-review-discovery.md +++ b/plugins/project-init/references/codex-review-discovery.md @@ -1,54 +1,54 @@ # Codex Review Discovery — AGENTS.md vs `/review` CLI -이 문서는 `/project-init:new` 의 Phase 4 (AGENTS.md seed) 가 왜 레포 생성 시점에 시드해야 효과적인지 정리한다. +This document explains why Phase 4 (AGENTS.md seed) of `/project-init:new` is only effective when seeded at repo-creation time. -## 두 가지 Codex review 경로 +## Two Codex review paths -| 경로 | 트리거 | AGENTS.md 영향 | +| Path | Trigger | AGENTS.md effect | |------|--------|----------------| -| **Codex GitHub cloud reviewer** | PR open / `@codex review` 댓글 | **자동**으로 레포 루트 `AGENTS.md` 의 `## Review guidelines` 섹션을 로드해 시스템 프롬프트에 포함 | -| **Codex CLI (`mcp__codex-cli__review` 또는 `chatgpt-codex review`)** | 로컬에서 명시적 호출 | AGENTS.md 는 같은 위치/형식이면 동일하게 읽힘 (CLI 가 cwd 의 `AGENTS.md` discover) | +| **Codex GitHub cloud reviewer** | PR open / `@codex review` comment | **Automatically** loads the `## Review guidelines` section of the repo-root `AGENTS.md` into the system prompt | +| **Codex CLI (`mcp__codex-cli__review` or `chatgpt-codex review`)** | explicit local invocation | AGENTS.md is read the same way if it is in the same location/format (the CLI discovers `AGENTS.md` in cwd) | -핵심 사실: Codex cloud reviewer 는 `AGENTS.md` 의 `## Review guidelines` 헤더 아래 콘텐츠를 우선적으로 참고한다. 다른 섹션 (`## Project context`, `## Build / Test / Lint`) 도 시스템 프롬프트에 들어가지만 review 의 critical path 는 review guidelines 섹션이다. +Key fact: the Codex cloud reviewer preferentially consults the content under the `## Review guidelines` header of `AGENTS.md`. Other sections (`## Project context`, `## Build / Test / Lint`) also enter the system prompt, but the critical path for review is the review-guidelines section. -> 출처: [OpenAI Codex GitHub integration](https://developers.openai.com/codex/integrations/github) — "Codex reads `AGENTS.md` to learn the codebase conventions before reviewing". +> Source: [OpenAI Codex GitHub integration](https://developers.openai.com/codex/integrations/github) — "Codex reads `AGENTS.md` to learn the codebase conventions before reviewing". -핵심 정정 (2026-07-13): "리뷰어는 `AGENTS.md` 섹션만 읽고 참조 파일은 따라가지 않는다" 는 인상은 과장이다. best-practices 문서가 예외를 명시한다 — *"If you and your team have a `code_review.md` file and reference it from `AGENTS.md`, Codex can follow that guidance during review as well."* 즉 `AGENTS.md` 가 명시적으로 참조하는 루트 `code_review.md` 는 리뷰어가 **따라갈 수 있다** (단 "can follow" = 소프트 개런티로, `## Review guidelines` 섹션 자체의 시스템 프롬프트 하드 주입보다 약하다. 임의 산문 "read X" redirect 와는 다르다 — 그건 참조된 리뷰 파일이 아니라 안 따라간다). 이 저장소는 이 패턴을 채택했다: `AGENTS.md` 에 하드 P0/P1 최소본 + 루트 `code_review.md` 전문. +Important correction (2026-07-13): the impression that "the reviewer only reads `AGENTS.md` sections and does not follow referenced files" is overstated. The best-practices doc names an exception — *"If you and your team have a `code_review.md` file and reference it from `AGENTS.md`, Codex can follow that guidance during review as well."* So the reviewer **can follow** a root `code_review.md` that `AGENTS.md` explicitly references (but "can follow" is a soft guarantee, weaker than the hard system-prompt injection of the `## Review guidelines` section itself. It differs from an arbitrary prose "read X" redirect — the reviewer does not follow that, only a referenced review file). This repo adopted this pattern: a hard P0/P1 minimum in `AGENTS.md` plus the full text in a root `code_review.md`. -> 출처: [OpenAI Codex best practices](https://developers.openai.com/codex/learn/best-practices) (verified 2026-07-13) — `code_review.md` 소프트 개런티. GitHub cloud reviewer 는 P0/P1 만 코멘트로 표면화: [Codex code review](https://developers.openai.com/codex/code-review). +> Source: [OpenAI Codex best practices](https://developers.openai.com/codex/learn/best-practices) (verified 2026-07-13) — the `code_review.md` soft guarantee. The GitHub cloud reviewer surfaces only P0/P1 as comments: [Codex code review](https://developers.openai.com/codex/code-review). -## 왜 "레포 생성 시점에" 시드해야 하나 +## Why seed it "at repo-creation time" -1. **첫 PR 부터 효과**: AGENTS.md 가 main 브랜치에 없으면 첫 PR 리뷰 시 Codex 가 generic 기준 (lint stuff, style nits) 으로 리뷰한다. -2. **Default branch protection**: AGENTS.md 를 첫 commit 에 포함하면 protected branch policy 와 무관하게 모든 PR 이 이미 base 에 깔린 가이드라인을 본다. -3. **사용자 학습 효과**: 빈 프로젝트에 AGENTS.md 가 있으면 첫 PR 작성자가 "여기는 이런 기준" 을 미리 인지. +1. **Effective from the first PR**: if AGENTS.md is not on the main branch, Codex reviews the first PR against generic criteria (lint stuff, style nits). +2. **Default branch protection**: including AGENTS.md in the first commit means every PR sees guidelines already present in the base, regardless of protected-branch policy. +3. **User-learning effect**: with AGENTS.md present in an empty project, the first PR author knows up front "these are the standards here". -## Review guidelines 섹션 핵심 구조 +## Core structure of the Review guidelines section -Codex review 가 잘 작동하는 패턴 — 4 개 섹션: +The pattern that makes Codex review work well — 4 sections: -1. **`### Do not flag`** (린터/포매터 영역) — **선두에 배치**. Codex 가 generic lint nit 을 코멘트하는 비용을 차단. -2. **`### P0 — Correctness / Security`** — must-block 항목. -3. **`### P1 — Performance / Maintainability`** — should-block 항목. -4. **`### Domain-specific`** — 프로젝트 고유 invariant. variant 별로 다름. +1. **`### Do not flag`** (linter/formatter territory) — **placed first**. Blocks the cost of Codex commenting on generic lint nits. +2. **`### P0 — Correctness / Security`** — must-block items. +3. **`### P1 — Performance / Maintainability`** — should-block items. +4. **`### Domain-specific`** — project-unique invariants. Differs per variant. -### "Do not flag" 가 선두인 이유 +### Why "Do not flag" comes first -부정형 (negative) 스코핑이 긍정형 (positive) 보다 review noise 를 더 효과적으로 줄인다. Codex 는 새 PR 을 보면 lint-level diff 부터 코멘트하려는 경향이 있는데, "do not flag" 가 먼저 보이면 그 욕구가 시스템 프롬프트 단계에서 억제된다. +Negative scoping reduces review noise more effectively than positive scoping. Codex, on seeing a new PR, tends to comment on lint-level diffs first; when "do not flag" appears first, that urge is suppressed at the system-prompt stage. -## CodeRabbit 와의 조율 +## Coordination with CodeRabbit -CodeRabbit 은 `AGENTS.md` 를 읽지 않는다 — 자체 `.coderabbit.yaml` 또는 review-instruction 시스템을 사용한다. 따라서: +CodeRabbit does not read `AGENTS.md` — it uses its own `.coderabbit.yaml` or review-instruction system. Therefore: -- AGENTS.md 의 review guidelines 는 Codex 만을 1차 타겟. -- CodeRabbit instruction (필요 시) 은 별도 `.coderabbit.yaml` 또는 `.github/CODEOWNERS` 와 함께 관리. -- `/github-dev:cr-fix` 명령이 두 봇의 결과를 동시에 처리하며 tier 정책으로 noise 를 정리. +- The review guidelines in AGENTS.md primarily target Codex. +- CodeRabbit instructions (if needed) are managed separately with `.coderabbit.yaml` or `.github/CODEOWNERS`. +- The `/github-dev:cr-fix` command processes both bots' results at once and cleans up noise with a tier policy. -> 참고: `.claude/spec/2026-05-06-codex-review-integration.md` — `cr-fix` 의 CR + Codex 통합 세부 내용. +> See: `.claude/spec/2026-05-06-codex-review-integration.md` — details of `cr-fix`'s CR + Codex integration. -## AGENTS.md 가 이미 존재하는 경우 +## When AGENTS.md already exists -`/project-init:new` 의 Phase 4 는 idempotent 가드를 가진다: +Phase 4 of `/project-init:new` has an idempotent guard: -- AGENTS.md 가 이미 있으면 덮어쓰지 않음 + 사용자에게 "기존 AGENTS.md 에 `## Review guidelines` 섹션이 없으면 manual 추가 권장" 안내. -- 기존 AGENTS.md 에 review guidelines 섹션이 없는지 grep 으로 확인 후 사용자 결정 게이트. +- If AGENTS.md already exists, do not overwrite it, and advise the user "if your existing AGENTS.md has no `## Review guidelines` section, adding one manually is recommended". +- Grep to check whether the existing AGENTS.md lacks a review-guidelines section, then gate on the user's decision. diff --git a/plugins/project-init/references/gh-repo-create-flow.md b/plugins/project-init/references/gh-repo-create-flow.md index de5ccc6a..272fc395 100644 --- a/plugins/project-init/references/gh-repo-create-flow.md +++ b/plugins/project-init/references/gh-repo-create-flow.md @@ -1,29 +1,30 @@ -# gh repo create — Owner 추론 + Visibility 결정 트리 +# gh repo create — Owner inference + Visibility decision tree -`/project-init:new` Phase 1 인터뷰와 Phase 6 레포 생성의 의사결정 컨텍스트. +The decision context for the `/project-init:new` Phase 1 interview and Phase 6 repo creation. -## Owner 추론 (자동 X, 인터뷰 필수) +## Owner inference (not automatic, interview required) -사용자가 personal account + 부업/소속 org 들을 동시에 가지는 경우가 일반적이라 **owner 자동 결정 금지**. `gh api` 로 후보만 수집하고 `AskUserQuestion` 으로 선택받는다. +It is common for a user to hold a personal account plus side-project/employer orgs at once, so **never auto-decide the owner**. Collect candidates with `gh api` and take the choice via `AskUserQuestion`. -### 후보 수집 명령 +### Candidate-collection commands ```bash # Personal account PERSONAL=$(gh api user --jq '.login') # Orgs (paginated) -# gh CLI 는 --slurp 와 --jq 동시 사용을 거부하므로 --slurp 출력을 local jq 로 -# 파이프한다. --paginate 단독 + --jq 는 multi-page 시 jq 가 separate JSON -# document 를 받아 페이지 경계에서 첫 페이지만 남게 됨 (PR #24 의 실제 finding). +# gh CLI refuses --slurp and --jq together, so pipe the --slurp output to a +# local jq. --paginate alone + --jq makes jq receive a separate JSON document +# per page, leaving only the first page at the page boundary on multi-page +# results (an actual finding from PR #24). ORGS=$(gh api --paginate --slurp /user/orgs | jq -c '[.[][].login]') ``` -> `--paginate` 만 단독으로 쓰면 30 개 초과 결과가 multi-document 로 흘러서 -> `--jq` 가 첫 페이지만 잡는다. `--slurp` 으로 array-of-arrays 로 묶고 -> `jq '[.[][].login]'` 로 flatten 하는 패턴이 portable + correct. +> Used alone, `--paginate` streams results beyond 30 as multiple documents, so +> `--jq` catches only the first page. Bundling them into an array-of-arrays with +> `--slurp` and flattening with `jq '[.[][].login]'` is the portable, correct pattern. -### 결정 트리 +### Decision tree ``` Q: "Where to create the repo?" @@ -33,38 +34,38 @@ Q: "Where to create the repo?" └─ ... ``` -옵션 description 에 "Personal" / "Organization" 명시 — 사용자가 두 org 가 비슷한 이름일 때 헷갈리지 않게. +Spell out "Personal" / "Organization" in each option's description — so the user is not confused when two orgs have similar names. -## Visibility 결정 +## Visibility decision ``` Q: "Visibility?" ├─ Private (Recommended) ├─ Public -└─ Internal ← org owner 일 때만 노출 (personal 은 internal 불가) +└─ Internal ← shown only for an org owner (personal accounts cannot use internal) ``` -Recommended default 가 Private 인 이유: -- 신규 프로젝트는 아직 정리되지 않은 secret / debug commit / WIP 코드를 포함할 가능성. 나중에 public 으로 전환은 한 줄이지만 (`gh repo edit --visibility public`), public → private 전환 후 fork 회수는 불가능. -- 의도가 public OSS 라도 첫 1 주는 private 으로 두고 정리 후 전환하는 패턴이 안전. +Why the recommended default is Private: +- A new project may contain not-yet-cleaned secrets / debug commits / WIP code. Switching to public later is one line (`gh repo edit --visibility public`), but after a public → private switch you cannot recall forks. +- Even if the intent is public OSS, keeping it private for the first week and switching after cleanup is the safe pattern. -> Public 으로 전환 명령: `gh repo edit {{OWNER}}/{{PROJECT_NAME}} --visibility public --accept-visibility-change-consequences` +> Command to switch to public: `gh repo edit {{OWNER}}/{{PROJECT_NAME}} --visibility public --accept-visibility-change-consequences` -## License 결정 +## License decision -License 는 visibility 와 독립이다 (private 레포에도 license 둘 수 있음). +License is independent of visibility (a private repo can carry a license too). -| Option | 언제 | +| Option | When | |--------|------| -| **MIT** (Recommended) | 단순 permissive, 가장 호환성 높음 | -| **Apache-2.0** | 특허 grant 명시 필요할 때 | -| **GPL-3.0** | copyleft 의도 (derivative 도 GPL 유지 강제) | -| **None** | 명시적으로 license 안 둘 때 (private 레포라면 "사실상 all rights reserved") | +| **MIT** (Recommended) | simple permissive, highest compatibility | +| **Apache-2.0** | when an explicit patent grant is needed | +| **GPL-3.0** | copyleft intent (forces derivatives to stay GPL) | +| **None** | when deliberately not setting a license (for a private repo, effectively "all rights reserved") | -`gh repo create` 의 `--license ` 플래그로 자동 LICENSE 파일 생성 가능 (template 사용). 단 license 가 None 이면 생략. +The `--license ` flag of `gh repo create` can auto-generate a LICENSE file (using a template). Omit it when the license is None. ```bash -# License 자동 시드 +# Auto-seed the license gh repo create "${OWNER}/${PROJECT_NAME}" \ --${VISIBILITY,,} \ --description "${ONE_LINER}" \ @@ -72,44 +73,44 @@ gh repo create "${OWNER}/${PROJECT_NAME}" \ --source=. --remote=origin --push ``` -> 한계: `gh repo create --license` 는 빈 레포 (코드 없음) 일 때만 license 파일을 자동 생성한다. `--source=.` 와 함께 쓰면 이미 commit 가 있어서 license 자동 생성이 안 될 수 있음 — 그 경우 별도로 `gh api -X POST /repos/.../contents/LICENSE` 로 시드하거나 사용자에게 manual 안내. V1 에서는 명령에 `--license` 만 넣고 실패해도 무시 (사용자 안내). +> Limitation: `gh repo create --license` auto-generates the license file only for an empty repo (no code). Combined with `--source=.` there are already commits, so license auto-generation may not happen — in that case seed it separately with `gh api -X POST /repos/.../contents/LICENSE` or advise the user to do it manually. In V1, just pass `--license` in the command and ignore failure (advise the user). -## Push 흐름 +## Push flow ```bash -# 0. git init (이미 .git 있으면 skip) +# 0. git init (skip if .git already exists) [ -d .git ] || git init -b main -# 1. 모든 시드 파일 stage +# 1. Stage all seed files git add .claude/ CLAUDE.md AGENTS.md README.md CHANGELOG.md # 2. Initial commit git commit -m "chore: bootstrap project skeleton via project-init" -# 3. gh repo create + 자동 push +# 3. gh repo create + auto push gh repo create "${OWNER}/${PROJECT_NAME}" \ --${VISIBILITY,,} \ --description "${ONE_LINER}" \ --source=. --remote=origin --push ``` -`--source=.` 는 현재 디렉토리를 git source 로 지정. `--remote=origin` 은 자동으로 `origin` remote 등록. `--push` 는 현재 branch 를 push. +`--source=.` designates the current directory as the git source. `--remote=origin` registers the `origin` remote automatically. `--push` pushes the current branch. -## 실패 시 복구 +## Recovery on failure -| 실패 | 복구 | +| Failure | Recovery | |------|------| -| `gh repo create` — repo 이름 충돌 | Phase 1 재시도 (다른 이름 선택). local commit 은 그대로 보존. | -| `gh repo create` — 권한 부족 (org 멤버 X) | Phase 1 owner 재선택 권유. | -| Push 실패 — 네트워크 / auth | `git remote add origin ...` + `git push -u origin main` 수동 명령 안내. | -| Initial commit 실패 — gitignore 빠짐 | 임시 `.env`, `node_modules/` 등이 stage 됐는지 확인. `.gitignore` 시드는 V1 scope 밖이라 사용자가 명시적으로 처리. | +| `gh repo create` — repo name collision | retry Phase 1 (pick a different name). The local commit is preserved as-is. | +| `gh repo create` — insufficient permission (not an org member) | suggest re-choosing the owner in Phase 1. | +| Push failure — network / auth | advise the manual `git remote add origin ...` + `git push -u origin main` commands. | +| Initial commit failure — missing gitignore | check whether a temporary `.env`, `node_modules/`, etc. got staged. `.gitignore` seeding is outside V1 scope, so the user handles it explicitly. | ## Idempotency -같은 디렉토리에서 `/project-init:new` 두 번째 호출 시: -1. `.git` 이 이미 존재하면 `git init` skip. -2. AGENTS.md / CLAUDE.md / README.md / CHANGELOG.md 중 어느 하나라도 이미 존재하면 Phase 4 / 5 에서 해당 파일은 skip + 안내. -3. `.claude/` 가 이미 있으면 Phase 2 의 `.gitkeep` 만 추가 (디렉토리 구조 자체는 보존). -4. `gh repo` 가 이미 존재하면 — `gh repo view ${OWNER}/${PROJECT_NAME}` 으로 확인 후 사용자에게 "remote 만 wire 할까요?" 결정. +On a second `/project-init:new` invocation in the same directory: +1. If `.git` already exists, skip `git init`. +2. If any of AGENTS.md / CLAUDE.md / README.md / CHANGELOG.md already exists, skip that file in Phase 4 / 5 and print a notice. +3. If `.claude/` already exists, add only the Phase 2 `.gitkeep` (the directory structure itself is preserved). +4. If the `gh repo` already exists — confirm with `gh repo view ${OWNER}/${PROJECT_NAME}`, then ask the user "wire only the remote?". -이 가드는 `scripts/idempotent-seed.sh` 가 담당한다. +This guard is handled by `scripts/idempotent-seed.sh`. diff --git a/plugins/project-init/references/new-procedure.md b/plugins/project-init/references/new-procedure.md index 2507c9ad..822a859b 100644 --- a/plugins/project-init/references/new-procedure.md +++ b/plugins/project-init/references/new-procedure.md @@ -2,22 +2,22 @@ Shared procedure body for `/project-init:new` (command) and the `new` skill. Both surfaces resolve this file via `references/new-procedure.md` relative to the plugin's installed root — Claude Code exposes that root as `${PLUGIN_ROOT}`; Codex 0.135 places it under `~/.codex/plugins/cache//project-init//`. -> **Trigger surface**: 명시적 user invocation 만. 자동 트리거 없음 (잘못된 디렉토리에서 실행되면 위험). The preflight guard below MUST run before any destructive op — both surfaces re-state the guard at the top of their body so it cannot be skipped. +> **Trigger surface**: explicit user invocation only. No automatic trigger (running it in the wrong directory is dangerous). The preflight guard below MUST run before any destructive op — both surfaces re-state the guard at the top of their body so it cannot be skipped. -## 핵심 원칙 +## Core principles -- **Minimal seeding, explicit follow-ups**: Day 1 에 진짜 필요한 것 (`.claude/` 빈 구조, CLAUDE.md stub, AGENTS.md review guidelines, README/CHANGELOG, gh 레포) 만 시드. tech-stack 기반 rules 생성 (`/rules-forge:write-rules`) 와 wiki domain 인터뷰 (`/llm-wiki:bootstrap-wiki`) 는 **호출하지 않고 Phase 7 안내만**. 빈 프로젝트에 generic 콘텐츠 생성하면 사용자가 덮어쓰는 비용 발생. -- **Owner gate is mandatory**: 사용자가 부업 컨텍스트 (개인 + 조직 레포) 를 가져 owner 결정은 자동화 금지 — Phase 1 인터뷰에서 반드시 묻는다. -- **Codex GitHub reviewer surface**: `AGENTS.md` 의 `## Review guidelines` 섹션이 Codex GitHub cloud reviewer 가 자동으로 읽는 영역. 레포 생성 시점에 시드해야 첫 PR 부터 효과. +- **Minimal seeding, explicit follow-ups**: seed only what Day 1 truly needs (the empty `.claude/` structure, a CLAUDE.md stub, AGENTS.md review guidelines, README/CHANGELOG, the gh repo). Tech-stack-based rule generation (`/rules-forge:write-rules`) and the wiki-domain interview (`/llm-wiki:bootstrap-wiki`) are **not invoked — only pointed to in Phase 7**. Generating generic content in an empty project imposes an overwrite cost on the user. +- **Owner gate is mandatory**: since the user has a side-project context (personal + org repos), owner selection must not be automated — always ask in the Phase 1 interview. +- **Codex GitHub reviewer surface**: the `## Review guidelines` section of `AGENTS.md` is what the Codex GitHub cloud reviewer reads automatically. It must be seeded at repo-creation time to take effect from the first PR. -## 사전 조건 +## Prerequisites -- `gh` CLI 설치 + `gh auth status` OK -- `git` 설치 -- `jq` 설치 (Phase 0 의 `infer-github-context.sh` 와 일부 placeholder 치환 헬퍼가 의존) -- 현재 디렉토리가 작업 대상 — `pwd` 출력을 사용자에게 보여주고 진행 확인 +- `gh` CLI installed + `gh auth status` OK +- `git` installed +- `jq` installed (Phase 0's `infer-github-context.sh` and some placeholder-substitution helpers depend on it) +- The current directory is the target — show the user the `pwd` output and confirm before proceeding -## Phase 0 — Preflight (자동, no prompt) +## Phase 0 — Preflight (automatic, no prompt) ```bash # --- Plugin root resolution (cross-runtime) --------------------------------- @@ -49,33 +49,33 @@ if [ -z "$PLUGIN_ROOT" ] \ exit 1 fi -# 인증 확인 +# Auth check gh auth status || { echo "[abort] gh CLI not authenticated. Run: gh auth login"; exit 1; } -# Git identity 추출 +# Extract git identity GIT_USER_NAME=$(git config --global user.name || echo "") GIT_USER_EMAIL=$(git config --global user.email || echo "") -# 현재 디렉토리 상태 진단 +# Diagnose current directory state CWD=$(pwd) DIR_NAME=$(basename "$CWD") HAS_GIT=$([ -d .git ] && echo "yes" || echo "no") HAS_CLAUDE=$([ -d .claude ] && echo "yes" || echo "no") HAS_CODE=$(find . -maxdepth 2 -type f \( -name "*.py" -o -name "*.ts" -o -name "*.js" -o -name "*.go" -o -name "*.rs" -o -name "*.java" \) 2>/dev/null | head -1 | wc -l) -# GitHub owner 후보 수집 +# Collect GitHub owner candidates bash "$PLUGIN_ROOT/scripts/infer-github-context.sh" -# 출력: JSON { "personal": "", "orgs": ["", "", ...] } +# Output: JSON { "personal": "", "orgs": ["", "", ...] } ``` > The hard preflight guard (refusing any cwd content beyond `.git/` and OS metadata) runs **before** this Phase 0 block — see the top of `commands/new.md` and `skills/new/SKILL.md`. The legacy Phase 0 idempotency soft-guard below is retained for backward-compatible behavior on truly-fresh runs (e.g. user removes `.gitkeep` files between attempts) but is now subordinate to the hard guard. -만약 `HAS_CLAUDE=yes` 또는 `.git/` 안에 commit 가 이미 있는 경우 — **idempotency guard** 발동: -- `AskUserQuestion` 으로 "이미 셋업된 디렉토리. 계속 시도하면 기존 파일은 보존되지만 일부 단계가 skip 됨. 계속?" 확인. +If `HAS_CLAUDE=yes` or a commit already exists in `.git/` — the **idempotency guard** fires: +- Confirm via `AskUserQuestion`: "This directory is already set up. Continuing preserves existing files but skips some steps. Continue?" ## Phase 1 — Project Identity Interview -**Single batched `AskUserQuestion` — 4 questions** (description 은 자유 텍스트라 Other 로 받음). +**Single batched `AskUserQuestion` — 4 questions** (the description is free text, so take it via Other). Question 1: **Project name** - header: "Name" @@ -83,31 +83,31 @@ Question 1: **Project name** Question 2: **Owner** - header: "Owner" -- options: 동적 생성 — Phase 0 의 personal account + 모든 orgs. 각 옵션 description 에 "Personal" / "Organization" 표시. +- options: generated dynamically — the personal account + all orgs from Phase 0. Mark each option's description "Personal" / "Organization". Question 3: **Visibility** - header: "Visibility" - options: "Private (Recommended)" / "Public" -- (org owner 면 "Internal" 추가) +- (add "Internal" for an org owner) Question 4: **License** - header: "License" - options: "MIT (Recommended)" / "Apache-2.0" / "GPL-3.0" / "None" -> Description (one-liner) 은 별도 평문 질문 X — Phase 1 응답 받은 직후 평문으로 한 줄 짧게 묻거나, AskUserQuestion 의 Other 입력으로 받는다. 평문 description 입력이 더 자연스러우므로 별도 짧은 질문 1 회 허용. +> The description (one-liner) is not a separate plain-text question — ask it briefly in one line right after the Phase 1 answers, or take it via the AskUserQuestion Other input. A plain-text description is more natural, so one extra short question is allowed. ## Phase 2 — `.claude/` Scaffold (structure only) ```bash bash ${PLUGIN_ROOT}/scripts/idempotent-seed.sh ensure-claude-dirs -# 생성: .claude/{spec,rules}/.gitkeep + .llmwiki/{raw,wiki}/.gitkeep +# Creates: .claude/{spec,rules}/.gitkeep + .llmwiki/{raw,wiki}/.gitkeep ``` -`bootstrap-wiki` / `write-rules` 는 호출하지 않는다 — 빈 프로젝트에는 적을 lore 도, tech-stack signal 도 없다. +Do not invoke `bootstrap-wiki` / `write-rules` — an empty project has no lore to record and no tech-stack signal. ## Phase 3 — CLAUDE.md Minimal Stub -기존 `CLAUDE.md` 가 있으면 skip with notice. 없으면 다음 형태로 작성: +If an existing `CLAUDE.md` is present, skip with a notice. Otherwise write it in this form (this stub is the seeded output; keep it in the user's language): ```markdown # @@ -135,39 +135,40 @@ bash ${PLUGIN_ROOT}/scripts/idempotent-seed.sh ensure-claude-dirs > 사용자의 global `~/.claude/CLAUDE.md` 가 항상 우선한다. 이 파일은 프로젝트 한정 규칙만 보관한다. ``` -placeholder (``, ``) 는 Phase 1 응답으로 치환. +Substitute the placeholders (`{{PROJECT_NAME}}`, `{{ONE_LINER}}`) with the Phase 1 answers. -## Phase 4 — AGENTS.md Seed (★ 이 플러그인의 차별점) +## Phase 4 — AGENTS.md Seed (★ this plugin's differentiator) -**Variant 선택**: Phase 1 description 키워드로 추천하되 사용자 확인. +**Variant selection**: recommend based on Phase 1 description keywords, but confirm with the user. | Keyword in description | Recommended variant | |------------------------|---------------------| | "deep learning", "ML", "model", "training", "dataset", "vision", "NLP" | `ml` | | "web", "fullstack", "frontend", "backend", "API", "REST", "GraphQL" | `web` | -| 그 외 / 명확하지 않음 | `general` (base) | +| otherwise / unclear | `general` (base) | `AskUserQuestion`: - header: "Variant" -- options: " (Recommended)" / 나머지 2 개 +- options: " (Recommended)" / the other 2 -> 응답을 `VARIANT` 변수에 할당 (예: `general` / `ml` / `web`). 사용자가 비워두거나 응답 누락 시 default `VARIANT=general`. +> Assign the answer to the `VARIANT` variable (e.g. `general` / `ml` / `web`). If the user leaves it blank or omits the answer, default to `VARIANT=general`. ```bash -# Portable in-place sed — GNU sed 는 `sed -i 'cmd' file`, BSD/macOS sed 는 -# `sed -i '' 'cmd' file` 시그니처. `sed --version` 으로 분기한다. +# Portable in-place sed — GNU sed uses `sed -i 'cmd' file`, BSD/macOS sed uses +# the `sed -i '' 'cmd' file` signature. Branch on `sed --version`. if sed --version >/dev/null 2>&1; then sed_inplace() { sed -i "$@"; } else sed_inplace() { sed -i '' "$@"; } fi -# POSIX 소문자화 — ${VAR,,} 는 Bash 4+ 전용이라 macOS 기본 /bin/bash (3.2) 에서 -# bad substitution 으로 깨진다. tr 로 대체 (Phase 6 visibility 정규화에서도 재사용). +# POSIX lowercasing — ${VAR,,} is Bash 4+ only, so it breaks with a bad +# substitution on macOS default /bin/bash (3.2). Replace with tr (reused in the +# Phase 6 visibility normalization too). to_lower() { printf '%s' "$1" | tr '[:upper:]' '[:lower:]'; } -# AskUserQuestion 라벨 ("ml (Recommended)" / "web" / "general") 을 -# 파일명 토큰 (general|ml|web) 으로 정규화. 알 수 없는 값은 abort. +# Normalize the AskUserQuestion label ("ml (Recommended)" / "web" / "general") +# to a filename token (general|ml|web). Abort on an unknown value. variant_lower=$(to_lower "$VARIANT") case "$variant_lower" in *ml*) VARIANT_FLAG="ml" ;; @@ -177,11 +178,11 @@ case "$variant_lower" in esac SRC="${PLUGIN_ROOT}/assets/AGENTS.review-guidelines.${VARIANT_FLAG}.md" -# Variant 가 general 이면 base 파일 +# For the general variant, use the base file [ "$VARIANT_FLAG" = "general" ] && SRC="${PLUGIN_ROOT}/assets/AGENTS.review-guidelines.md" -# sed replacement 컨텍스트에서 위험한 문자 (\, &, |) escape — 사용자 입력에 -# "Frontend & Backend" 같은 `&` 가 있으면 sed 가 매치 전체를 다시 삽입한다. +# Escape characters dangerous in a sed replacement context (\, &, |) — if user +# input contains a `&` like "Frontend & Backend", sed re-inserts the whole match. esc_sed() { printf '%s' "$1" | sed 's/[\\&|]/\\&/g'; } PROJECT_NAME_ESC=$(esc_sed "$PROJECT_NAME") ONE_LINER_ESC=$(esc_sed "$ONE_LINER") @@ -190,7 +191,7 @@ LICENSE_ESC=$(esc_sed "$LICENSE") if [ ! -f AGENTS.md ]; then cp "$SRC" AGENTS.md - # placeholder 치환 (escape 된 값 사용) + # Substitute placeholders (using the escaped values) sed_inplace "s|{{PROJECT_NAME}}|${PROJECT_NAME_ESC}|g" AGENTS.md sed_inplace "s|{{ONE_LINER}}|${ONE_LINER_ESC}|g" AGENTS.md sed_inplace "s|{{OWNER}}|${OWNER_ESC}|g" AGENTS.md @@ -199,13 +200,13 @@ else fi ``` -AGENTS.md 의 `## Review guidelines` 섹션은 Codex GitHub cloud reviewer 가 자동으로 읽는다 ([OpenAI Codex GitHub integration](https://developers.openai.com/codex/integrations/github)) — 사용자에게 한 줄 안내. +The `## Review guidelines` section of AGENTS.md is read automatically by the Codex GitHub cloud reviewer ([OpenAI Codex GitHub integration](https://developers.openai.com/codex/integrations/github)) — give the user a one-line note. ## Phase 5 — README + CHANGELOG ```bash -# 새로 시드한 파일만 추적 — 기존 파일에 의도적으로 둔 {{PROJECT_NAME}} 류 -# placeholder 가 변조되지 않도록 cp 한 파일에만 치환을 적용한다. +# Track only newly-seeded files — apply substitution only to the cp'd files so +# that deliberate {{PROJECT_NAME}}-style placeholders in existing files are not tampered with. SEEDED_FILES=() if [ ! -f README.md ]; then cp "${PLUGIN_ROOT}/assets/README.minimal.md" README.md @@ -216,7 +217,7 @@ if [ ! -f CHANGELOG.md ]; then SEEDED_FILES+=("CHANGELOG.md") fi -# Phase 4 에서 정의한 sed_inplace / *_ESC 재사용 — escape + 플랫폼 portable +# Reuse sed_inplace / *_ESC defined in Phase 4 — escaped + platform-portable for f in "${SEEDED_FILES[@]}"; do sed_inplace "s|{{PROJECT_NAME}}|${PROJECT_NAME_ESC}|g" "$f" sed_inplace "s|{{ONE_LINER}}|${ONE_LINER_ESC}|g" "$f" @@ -225,7 +226,7 @@ for f in "${SEEDED_FILES[@]}"; do done ``` -게이트: README.md 첫 30줄 미리보기 후 수정 기회. 한 번 더 호출하지 않고 inline `Edit` 로 즉시 수정. +Gate: preview the first 30 lines of README.md, then allow edits. Fix inline with `Edit` immediately rather than invoking again. ## Phase 6 — GitHub Repo Creation @@ -241,12 +242,12 @@ if ! grep -qxF '.claude/state/' .gitignore 2>/dev/null; then printf '%s\n' '.claude/state/' >> .gitignore fi -# Stage all seeded files (이미 존재한 파일은 git add 가 no-op) +# Stage all seeded files (git add is a no-op for already-existing files) git add .claude/ .llmwiki/ CLAUDE.md AGENTS.md README.md CHANGELOG.md .gitignore -# Idempotent re-run 경로: Phase 4/5 가 모두 skip 했고 staged diff 가 없으면 -# `git commit` 이 `nothing to commit` 으로 실패해 이후 gh repo create 까지 -# abort 된다. staged 변경 존재 여부로 분기한다. +# Idempotent re-run path: if Phase 4/5 both skipped and there is no staged diff, +# `git commit` fails with `nothing to commit` and aborts the later gh repo create. +# Branch on whether staged changes exist. if ! git diff --cached --quiet; then git commit -m "chore: bootstrap project skeleton via project-init" else @@ -254,12 +255,12 @@ else fi ``` -`AskUserQuestion`: dry-run 미리보기 후 confirm. +`AskUserQuestion`: confirm after a dry-run preview. ```bash -# AskUserQuestion 라벨 ("Private (Recommended)", "Public", "Internal") 을 -# gh CLI 토큰 (private|public|internal) 으로 정규화. -# Phase 4 의 to_lower 헬퍼 재사용 (POSIX tr — Bash 3.2 호환). +# Normalize the AskUserQuestion label ("Private (Recommended)", "Public", "Internal") +# to a gh CLI token (private|public|internal). +# Reuse the Phase 4 to_lower helper (POSIX tr — Bash 3.2 compatible). vis_lower=$(to_lower "$VISIBILITY") case "$vis_lower" in *private*) VIS_FLAG="private" ;; @@ -268,9 +269,9 @@ case "$vis_lower" in *) echo "[abort] Unknown visibility: $VISIBILITY"; exit 1 ;; esac -# Idempotent re-run 가드: origin remote 가 이미 있으면 `gh repo create -# --remote=origin` 이 중복 등록을 시도하다 실패한다. 기존 remote 가 가리키는 -# URL 을 노출하고 사용자에게 manual push 명령을 안내한다. +# Idempotent re-run guard: if an origin remote already exists, `gh repo create +# --remote=origin` fails trying to register a duplicate. Surface the URL the +# existing remote points to and give the user a manual push command. if git remote get-url origin >/dev/null 2>&1; then EXISTING=$(git remote get-url origin) echo "[skip] origin remote already exists ($EXISTING) — skipping gh repo create." @@ -285,7 +286,7 @@ else fi ``` -License 가 None 이 아니면 — gh repo create 후 `gh api` 로 LICENSE 파일 생성하거나 사용자에게 "later" 안내. 단순화를 위해 V1 에서는 안내만. +If the license is not None — after gh repo create, create the LICENSE file via `gh api`, or advise the user to do it "later". For simplicity, V1 only advises. ## Phase 7 — Summary + Next Actions @@ -315,19 +316,19 @@ Next actions (call when ready): (wiki 적재까지 내장 — 별도 skill 불필요) ``` -## 실패 처리 +## Failure handling -| 단계 | 실패 시 동작 | +| Step | Behavior on failure | |------|--------------| -| Preflight hard guard | abort + 안내 (use `/rules-forge:write-rules` or `/llm-wiki:bootstrap-wiki` for non-empty dirs) | -| Phase 0 — gh auth | abort + 안내 (`gh auth login`) | -| Phase 0 — idempotency guard 사용자 abort | 즉시 stop, partial seed 보존 | -| Phase 6 — `gh repo create` | local 변경/커밋은 그대로, push 만 실패. 사용자에게 manual retry 명령 안내 | -| Phase 6 — repo 이름 충돌 | gh CLI error 메시지 그대로 노출 + Phase 1 재시도 권유 | +| Preflight hard guard | abort + notice (use `/rules-forge:write-rules` or `/llm-wiki:bootstrap-wiki` for non-empty dirs) | +| Phase 0 — gh auth | abort + notice (`gh auth login`) | +| Phase 0 — idempotency guard user abort | stop immediately, preserve the partial seed | +| Phase 6 — `gh repo create` | local changes/commits stay intact, only push fails. Advise the user of a manual retry command | +| Phase 6 — repo name collision | surface the gh CLI error message verbatim + suggest retrying Phase 1 | ## Out of Scope - CI/CD workflow seed (`.github/workflows/`) - pre-commit hook seed -- 외부 boilerplate auto-download (cookiecutter 등 — 필요하면 `Skill("code-scout:research-orchestrator")` 별도 호출) -- 다국어 인터뷰 분기 — 한/영 혼용 단일 버전 유지 +- external boilerplate auto-download (cookiecutter etc. — if needed, a separate `Skill("code-scout:research-orchestrator")` call) +- multi-language interview branching — a single mixed Korean/English version is maintained diff --git a/plugins/slidev/.claude-plugin/plugin.json b/plugins/slidev/.claude-plugin/plugin.json index 51e8ac1f..48704d21 100644 --- a/plugins/slidev/.claude-plugin/plugin.json +++ b/plugins/slidev/.claude-plugin/plugin.json @@ -1,5 +1,5 @@ { "name": "slidev", - "version": "1.2.1", + "version": "1.2.2", "description": "Slidev markdown presentation generator with interview workflow and KubeCon-level visual enhancement" } diff --git a/plugins/slidev/.codex-plugin/plugin.json b/plugins/slidev/.codex-plugin/plugin.json index b8a7c0a9..cac8ca88 100644 --- a/plugins/slidev/.codex-plugin/plugin.json +++ b/plugins/slidev/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "slidev", - "version": "1.2.1", + "version": "1.2.2", "description": "Slidev markdown presentation generator with interview workflow and KubeCon-level visual enhancement", "author": { "name": "YoungjaeDev" diff --git a/plugins/slidev/skills/create-slide/references/animations.md b/plugins/slidev/skills/create-slide/references/animations.md index fd02e522..270db875 100644 --- a/plugins/slidev/skills/create-slide/references/animations.md +++ b/plugins/slidev/skills/create-slide/references/animations.md @@ -1,201 +1,201 @@ -# Slidev 애니메이션 레퍼런스 +# Slidev animation reference -Slidev는 강력한 애니메이션 시스템을 제공하여 클릭 기반 전환, 텍스트 마킹, 복잡한 모션, 코드 변화 애니메이션 등을 지원합니다. +Slidev provides a powerful animation system supporting click-based transitions, text marking, complex motion, code-change animation, and more. -## 1. v-click - 기본 클릭 애니메이션 +## 1. v-click - basic click animation -요소를 클릭할 때마다 순차적으로 나타나게 만듭니다. +Makes elements appear sequentially on each click. -### 태그 방식 +### Tag form ```md -첫 번째 클릭에 나타남 +Appears on the first click -두 번째 클릭에 나타남 +Appears on the second click -세 번째 클릭에 나타남 +Appears on the third click ``` -### 디렉티브 방식 (인라인) +### Directive form (inline) ```md -
클릭 1
-
클릭 2
-

클릭 3

+
Click 1
+
Click 2
+

Click 3

``` -### 번호 지정 +### Specifying a number -특정 클릭 순서를 지정할 수 있습니다: +You can specify a particular click order: ```md -
세 번째로 나타남
-
첫 번째로 나타남
-
두 번째로 나타남
+
Appears third
+
Appears first
+
Appears second
``` -### 클릭 후 숨기기 +### Hide after click ```md -
클릭하면 나타났다가 다음 클릭에 사라짐
-
이제 이게 나타남
+
Appears on click, then disappears on the next click
+
Now this appears
``` -### 커스텀 클릭 카운트 +### Custom click count -Frontmatter에서 슬라이드의 총 클릭 수를 지정: +Specify the slide's total click count in frontmatter: ```md --- clicks: 5 --- -# 슬라이드 제목 +# Slide title -
첫 번째
-
두 번째
-
세 번째
-
네 번째
-
다섯 번째
+
First
+
Second
+
Third
+
Fourth
+
Fifth
``` -### 실용 예제 +### Practical example ```md -# 제품 특징 +# Product features -## 빠른 성능 -10배 빠른 로딩 속도 +## Fast performance +10x faster loading speed -## 안정성 -99.9% 가동 시간 보장 +## Reliability +99.9% uptime guaranteed -## 확장성 -무제한 사용자 지원 +## Scalability +Unlimited user support ``` --- -## 2. v-clicks - 자동 순차 애니메이션 +## 2. v-clicks - automatic sequential animation -여러 자식 요소를 자동으로 순차적으로 나타나게 합니다. +Makes multiple child elements appear automatically in sequence. -### 기본 사용 +### Basic usage ```md -- 첫 번째 항목 -- 두 번째 항목 -- 세 번째 항목 -- 네 번째 항목 +- First item +- Second item +- Third item +- Fourth item ``` -### Depth 지정 +### Specifying depth -중첩된 요소의 깊이를 제어: +Control the depth of nested elements: ```md -- Level 1 항목 - - Level 2 항목 (같이 나타남) - - Level 2 항목 (같이 나타남) -- Level 1 항목 - - Level 2 항목 (같이 나타남) +- Level 1 item + - Level 2 item (appears together) + - Level 2 item (appears together) +- Level 1 item + - Level 2 item (appears together) ``` -### Every 속성 +### The every property -N개씩 묶어서 나타나게: +Reveal in groups of N: ```md -- 항목 1 (첫 클릭) -- 항목 2 (첫 클릭) -- 항목 3 (두 번째 클릭) -- 항목 4 (두 번째 클릭) +- Item 1 (first click) +- Item 2 (first click) +- Item 3 (second click) +- Item 4 (second click) ``` -### 복합 예제 +### Compound example ```md -# 로드맵 +# Roadmap ## Q1 2024 -- 기능 A 출시 -- 베타 테스트 시작 +- Launch feature A +- Start the beta test ## Q2 2024 -- 공식 출시 -- 마케팅 캠페인 +- Official launch +- Marketing campaign ## Q3 2024 -- 글로벌 확장 -- 파트너십 체결 +- Global expansion +- Sign partnerships ``` --- -## 3. v-after - 이전 클릭과 함께 표시 +## 3. v-after - appear with the previous click -이전 클릭 요소와 동시에 나타나게 합니다. +Makes an element appear at the same time as the previous click element. -### 기본 사용 +### Basic usage ```md -
첫 번째 클릭에 나타남
-
첫 번째 클릭에 같이 나타남
+
Appears on the first click
+
Appears together on the first click
``` -### v-click과 결합 +### Combined with v-click ```md -
첫 번째
-
첫 번째와 함께
-
두 번째
-
두 번째와 함께
+
First
+
With the first
+
Second
+
With the second
``` -### 실용 예제 +### Practical example ```md -# 아키텍처 +# Architecture
@@ -226,94 +226,94 @@ Node.js + Express --- -## 4. v-mark - 인라인 텍스트 마킹 +## 4. v-mark - inline text marking -텍스트를 강조하거나 표시할 수 있습니다. +Lets you emphasize or mark text. -### 기본 마킹 타입 +### Basic mark types ```md -# 텍스트 강조 +# Text emphasis -이것은 기본 마크입니다. +This is a basic mark. -이것은 밑줄입니다. +This is an underline. -이것은 원형 강조입니다. +This is a circle emphasis. -이것은 하이라이트입니다. +This is a highlight. -이것은 박스입니다. +This is a box. -이것은 취소선입니다. +This is a strikethrough. ``` -### 색상 지정 +### Specifying color ```md -이것은 빨간 밑줄입니다. +This is a red underline. -이것은 노란 하이라이트입니다. +This is a yellow highlight. -이것은 초록 원입니다. +This is a green circle. ``` -### 클릭과 결합 +### Combined with clicks ```md -# 중요 포인트 +# Key points
-성능이 10배 향상되었습니다. +Performance improved 10x.
-비용은 $100 $50으로 절감. +Cost reduced from $100 to $50.
``` -### 실용 예제 +### Practical example ```md -# 마이그레이션 계획 +# Migration plan -- Phase 1: 데이터 백업 -- Phase 2: 시스템 전환 -- Phase 3: 검증 및 모니터링 +- Phase 1: Data backup +- Phase 2: System cutover +- Phase 3: Verification and monitoring
-⚠️ 주의: 다운타임 예상 시간 2시간 +⚠️ Caution: expected downtime 2 hours
``` --- -## 5. v-motion - 복잡한 모션 애니메이션 +## 5. v-motion - complex motion animation -CSS 속성을 애니메이션화하여 복잡한 전환 효과를 만듭니다. +Animate CSS properties to create complex transition effects. -### 기본 사용 +### Basic usage ```md
- 왼쪽에서 슬라이드 + Slide in from the left
``` -### 복합 애니메이션 +### Compound animation ```md
- 페이드 + 슬라이드 + Fade + slide
``` -### 클릭 기반 모션 +### Click-based motion ```md
- 클릭하면 확대 및 회전 + Scale and rotate on click
``` -### 딜레이 및 타이밍 +### Delay and timing ```md
- 딜레이와 이징 적용 + Delay and easing applied
``` -### 실용 예제: 카드 애니메이션 +### Practical example: card animation ```md -# 제품 소개 +# Product intro
@@ -369,8 +369,8 @@ CSS 속성을 애니메이션화하여 복잡한 전환 효과를 만듭니다. :initial="{ y: 100, opacity: 0 }" :enter="{ y: 0, opacity: 1, transition: { delay: 0 } }"> -## 기능 1 -빠른 성능 +## Feature 1 +Fast performance
@@ -379,8 +379,8 @@ CSS 속성을 애니메이션화하여 복잡한 전환 효과를 만듭니다. :initial="{ y: 100, opacity: 0 }" :enter="{ y: 0, opacity: 1, transition: { delay: 200 } }"> -## 기능 2 -안정성 +## Feature 2 +Reliability
@@ -389,8 +389,8 @@ CSS 속성을 애니메이션화하여 복잡한 전환 효과를 만듭니다. :initial="{ y: 100, opacity: 0 }" :enter="{ y: 0, opacity: 1, transition: { delay: 400 } }"> -## 기능 3 -확장성 +## Feature 3 +Scalability @@ -399,98 +399,98 @@ CSS 속성을 애니메이션화하여 복잡한 전환 효과를 만듭니다. --- -## 6. Slide Transitions - 슬라이드 전환 효과 +## 6. Slide Transitions - slide transition effects -슬라이드 간 전환 애니메이션을 제어합니다. +Controls the transition animation between slides. -### Frontmatter 전환 설정 +### Frontmatter transition setting ```md --- transition: slide-left --- -# 슬라이드 1 +# Slide 1 --- transition: slide-right --- -# 슬라이드 2 +# Slide 2 --- transition: fade --- -# 슬라이드 3 +# Slide 3 ``` -### 사용 가능한 전환 효과 +### Available transitions ```md --- -# 왼쪽으로 슬라이드 +# slide to the left transition: slide-left --- --- -# 오른쪽으로 슬라이드 +# slide to the right transition: slide-right --- --- -# 위로 슬라이드 +# slide up transition: slide-up --- --- -# 아래로 슬라이드 +# slide down transition: slide-down --- --- -# 페이드 +# fade transition: fade --- --- -# View Transition API 사용 (Chrome 111+) +# use the View Transition API (Chrome 111+) transition: view-transition --- --- -# 전환 효과 없음 +# no transition transition: none --- ``` -### 전역 전환 설정 +### Global transition setting -모든 슬라이드에 기본 전환 효과 적용: +Apply a default transition to all slides: ```md --- -# 첫 슬라이드 (전역 설정) +# first slide (global setting) theme: apple-basic transition: slide-left --- -# 슬라이드 1 +# Slide 1 --- -# 슬라이드 2 (전역 설정 상속) +# Slide 2 (inherits the global setting) --- transition: fade --- -# 슬라이드 3 (개별 설정 우선) +# Slide 3 (a per-slide setting wins) ``` -### 커스텀 전환 +### Custom transition -Vue transition 컴포넌트 사용: +Use a Vue transition component: ```md --- @@ -517,66 +517,66 @@ transition: my-custom-transition --- -## 7. Shiki Magic Move - 코드 변화 애니메이션 +## 7. Shiki Magic Move - code-change animation -코드 블록 간 변화를 부드럽게 애니메이션으로 보여줍니다. +Smoothly animates the changes between code blocks. -### 기본 사용 +### Basic usage ````md # Code Evolution ````md magic-move ```js -// Step 1: 기본 함수 +// Step 1: a basic function function greet(name) { console.log('Hello ' + name); } ``` ```js -// Step 2: ES6 템플릿 리터럴 +// Step 2: an ES6 template literal function greet(name) { console.log(`Hello ${name}`); } ``` ```js -// Step 3: 화살표 함수 +// Step 3: an arrow function const greet = (name) => { console.log(`Hello ${name}`); }; ``` ```js -// Step 4: 최종 버전 +// Step 4: the final version const greet = (name) => console.log(`Hello ${name}!`); ``` ```` ```` -### 다중 파일 변화 +### Multi-step change ````md # Refactoring ````md magic-move ```js -// Before: 모놀리식 +// Before: monolithic function processUser(user) { - // 검증 + // validate if (!user.email) throw new Error('No email'); - // 처리 + // process const normalized = user.email.toLowerCase(); - // 저장 + // save db.save({ email: normalized }); } ``` ```js -// After: 모듈화 +// After: modularized function validateUser(user) { if (!user.email) throw new Error('No email'); } @@ -598,19 +598,19 @@ function processUser(user) { ```` ```` -### 하이라이트와 결합 +### Combined with highlighting ````md ````md magic-move {lines: true} ```js {1} -// 함수 선언 강조 +// highlight the function declaration function calculate(a, b) { return a + b; } ``` ```js {3} -// 리턴 구문 강조 +// highlight the return statement function calculate(a, b) { const result = a + b; return result; @@ -618,7 +618,7 @@ function calculate(a, b) { ``` ```js {2-3} -// 본문 강조 +// highlight the body function calculate(a, b) { const result = a + b; console.log(`Result: ${result}`); @@ -628,21 +628,21 @@ function calculate(a, b) { ```` ```` -### 실용 예제: API 진화 +### Practical example: API evolution ````md -# API 개선 과정 +# API improvement process ````md magic-move ```js -// v1: 기본 REST API +// v1: basic REST API app.get('/users', (req, res) => { res.json(users); }); ``` ```js -// v2: 페이지네이션 추가 +// v2: add pagination app.get('/users', (req, res) => { const { page = 1, limit = 10 } = req.query; const start = (page - 1) * limit; @@ -651,7 +651,7 @@ app.get('/users', (req, res) => { ``` ```js -// v3: 필터링 추가 +// v3: add filtering app.get('/users', (req, res) => { const { page = 1, limit = 10, role } = req.query; let filtered = role ? users.filter(u => u.role === role) : users; @@ -661,7 +661,7 @@ app.get('/users', (req, res) => { ``` ```js -// v4: 에러 처리 및 타입 안정성 +// v4: error handling and type safety app.get('/users', async (req, res) => { try { const { page = 1, limit = 10, role } = req.query; @@ -680,34 +680,34 @@ app.get('/users', async (req, res) => { --- -## 8. Click Markers in Notes - 발표자 노트 자동 스크롤 +## 8. Click Markers in Notes - auto-scroll presenter notes -발표자 노트에 `[click]` 마커를 추가하여 클릭마다 자동으로 스크롤됩니다. +Add `[click]` markers to presenter notes to auto-scroll on each click. -### 기본 사용 +### Basic usage ```md -# 제품 특징 +# Product features -- 빠른 성능 -- 높은 안정성 -- 쉬운 확장 +- Fast performance +- High reliability +- Easy to scale ``` -### 복잡한 예제 +### Complex example ```md -# 시스템 아키텍처 +# System architecture
@@ -740,87 +740,87 @@ PostgreSQL + Redis
``` -### 타이밍 힌트 +### Timing hints ```md -# 데모 +# Demo -1. 로그인 -2. 대시보드 확인 -3. 데이터 업로드 -4. 리포트 생성 +1. Log in +2. Check the dashboard +3. Upload data +4. Generate a report ``` --- -## 애니메이션 조합 패턴 +## Animation combination patterns -### 패턴 1: 순차적 리스트 +### Pattern 1: sequential list ```md -# 구현 단계 +# Implementation steps -- Phase 1: 요구사항 분석 -- Phase 2: 설계 및 프로토타입 -- Phase 3: 개발 및 테스트 -- Phase 4: 배포 및 모니터링 +- Phase 1: Requirements analysis +- Phase 2: Design and prototype +- Phase 3: Development and testing +- Phase 4: Deployment and monitoring ``` -### 패턴 2: 강조 포인트 +### Pattern 2: emphasized points ```md -# 핵심 메트릭 +# Key metrics
-응답 시간: 50ms +Response time: 50ms
-처리량: 10,000 req/s +Throughput: 10,000 req/s
-에러율: 0.01% +Error rate: 0.01%
``` -### 패턴 3: 비교 강조 +### Pattern 3: comparison emphasis ```md # Before vs After @@ -830,28 +830,28 @@ PostgreSQL + Redis
## Before -- 느린 로딩 -- 높은 메모리 사용 -- 복잡한 코드 +- Slow loading +- High memory usage +- Complex code
## After -- 빠른 로딩 -- 낮은 메모리 사용 -- 간결한 코드 +- Fast loading +- Low memory usage +- Concise code
``` -### 패턴 4: 카드 애니메이션 +### Pattern 4: card animation ```md -# 팀 소개 +# Team intro
@@ -861,7 +861,7 @@ PostgreSQL + Redis :enter="{ scale: 1, rotate: 0, transition: { delay: 0 } }"> ## Frontend -3명 +3 people
@@ -871,7 +871,7 @@ PostgreSQL + Redis :enter="{ scale: 1, rotate: 0, transition: { delay: 200 } }"> ## Backend -4명 +4 people @@ -881,7 +881,7 @@ PostgreSQL + Redis :enter="{ scale: 1, rotate: 0, transition: { delay: 400 } }"> ## DevOps -2명 +2 people @@ -890,58 +890,58 @@ PostgreSQL + Redis --- -## 성능 최적화 +## Performance optimization -### 애니메이션 수 제한 +### Limit the number of animations -슬라이드당 클릭 수를 10개 이하로 유지하는 것이 좋습니다: +Keeping the click count per slide at 10 or fewer is recommended: ```md --- -clicks: 10 # 명시적으로 제한 +clicks: 10 # limit explicitly --- ``` -### Transform 우선 사용 +### Prefer transform -성능을 위해 `transform` 속성 사용: +Use the `transform` property for performance: ```md - +
- +
``` -### 복잡한 애니메이션 그룹화 +### Group complex animations -여러 요소를 컨테이너로 묶어서 애니메이션: +Wrap multiple elements in a container to animate them together: ```md
-
항목 1
-
항목 2
-
항목 3
+
Item 1
+
Item 2
+
Item 3
``` --- -## 디버깅 팁 +## Debugging tips -### 클릭 카운트 확인 +### Check the click count -개발자 도구에서 현재 클릭 상태 확인: +Check the current click state in devtools: ```js -// 브라우저 콘솔 +// browser console $slidev.nav.clicks ``` -### 애니메이션 속도 조절 +### Adjust animation speed -CSS로 전역 애니메이션 속도 조절: +Adjust global animation speed with CSS: ```css ``` -### 애니메이션 비활성화 (테스트용) +### Disable animation (for testing) ```md --- -clicks: 0 # 모든 클릭 애니메이션 건너뛰기 +clicks: 0 # skip all click animations --- ``` diff --git a/plugins/slidev/skills/create-slide/references/components.md b/plugins/slidev/skills/create-slide/references/components.md index a3d648ce..b52fe53e 100644 --- a/plugins/slidev/skills/create-slide/references/components.md +++ b/plugins/slidev/skills/create-slide/references/components.md @@ -1,77 +1,77 @@ -# Slidev 내장 컴포넌트 레퍼런스 +# Slidev built-in component reference -Slidev에서 제공하는 모든 내장 컴포넌트의 상세 가이드입니다. +A detailed guide to every built-in component Slidev provides. --- ## Navigation & Structure -### 1. Toc - 목차 컴포넌트 +### 1. Toc - table-of-contents component -슬라이드 목차를 자동으로 생성합니다. +Automatically generates a slide table of contents. **Props:** -- `columns`: 컬럼 수 (기본값: 1) -- `maxDepth`: 최대 헤딩 깊이 (기본값: Infinity) -- `minDepth`: 최소 헤딩 깊이 (기본값: 1) -- `mode`: 표시 모드 - 'all' | 'onlyCurrentTree' | 'onlySiblings' (기본값: 'all') -- `listClass`: 목록 CSS 클래스 +- `columns`: number of columns (default: 1) +- `maxDepth`: maximum heading depth (default: Infinity) +- `minDepth`: minimum heading depth (default: 1) +- `mode`: display mode - 'all' | 'onlyCurrentTree' | 'onlySiblings' (default: 'all') +- `listClass`: list CSS class -**사용 예시:** +**Example:** ```vue --- layout: intro --- -# 목차 +# Table of Contents ``` -### 2. Link - 슬라이드 네비게이션 링크 +### 2. Link - slide navigation link -특정 슬라이드로 이동하는 링크를 생성합니다. +Creates a link that jumps to a specific slide. **Props:** -- `to`: 대상 슬라이드 번호 또는 경로 -- `title`: 링크 텍스트 (선택사항) +- `to`: target slide number or path +- `title`: link text (optional) -**사용 예시:** +**Example:** ```vue -5번 슬라이드로 이동 -Intro 슬라이드로 +Go to slide 5 +To the Intro slide ``` -### 3. SlideCurrentNo - 현재 슬라이드 번호 +### 3. SlideCurrentNo - current slide number -현재 슬라이드의 번호를 표시합니다. +Displays the current slide's number. -**사용 예시:** +**Example:** ```vue
/
``` -### 4. SlidesTotal - 전체 슬라이드 수 +### 4. SlidesTotal - total slide count -프레젠테이션의 총 슬라이드 수를 표시합니다. +Displays the total number of slides in the presentation. -**사용 예시:** +**Example:** ```vue
Page of
``` -### 5. TitleRenderer - 슬라이드 제목 렌더링 +### 5. TitleRenderer - render a slide title -특정 슬라이드의 제목을 가져와 표시합니다. +Fetches and displays a specific slide's title. **Props:** -- `no`: 슬라이드 번호 +- `no`: slide number -**사용 예시:** +**Example:** ```vue
@@ -84,58 +84,58 @@ layout: intro ## Visual Elements -### 6. Arrow - 화살표 그리기 +### 6. Arrow - draw an arrow -슬라이드에 화살표를 그립니다. +Draws an arrow on the slide. **Props:** -- `x1`: 시작 x 좌표 (px 또는 %) -- `y1`: 시작 y 좌표 -- `x2`: 끝 x 좌표 -- `y2`: 끝 y 좌표 -- `width`: 선 두께 (기본값: 2) -- `color`: 색상 (기본값: 'currentColor') -- `two-way`: 양방향 화살표 (기본값: false) - -**사용 예시:** +- `x1`: start x coordinate (px or %) +- `y1`: start y coordinate +- `x2`: end x coordinate +- `y2`: end y coordinate +- `width`: line thickness (default: 2) +- `color`: color (default: 'currentColor') +- `two-way`: two-way arrow (default: false) + +**Example:** ```vue ``` -### 7. VDragArrow - 드래그 가능한 화살표 +### 7. VDragArrow - draggable arrow -드래그로 위치를 조정할 수 있는 화살표입니다. +An arrow whose position can be adjusted by dragging. -**사용 예시:** +**Example:** ```vue ``` -### 8. AutoFitText - 자동 크기 조정 텍스트 +### 8. AutoFitText - auto-sizing text -컨테이너에 맞춰 텍스트 크기를 자동으로 조정합니다. +Automatically adjusts text size to fit the container. **Props:** -- `max`: 최대 font-size (기본값: 100px) -- `min`: 최소 font-size (기본값: 10px) +- `max`: maximum font-size (default: 100px) +- `min`: minimum font-size (default: 10px) -**사용 예시:** +**Example:** ```vue - 이 텍스트는 자동으로 크기가 조정됩니다 + This text auto-adjusts its size ``` -### 9. Transform - 변형 래퍼 +### 9. Transform - transform wrapper -요소를 확대/축소하거나 변형합니다. +Scales or transforms an element. **Props:** -- `scale`: 확대/축소 비율 (기본값: 1) -- `origin`: 변형 기준점 (기본값: 'center') +- `scale`: scale ratio (default: 1) +- `origin`: transform origin (default: 'center') -**사용 예시:** +**Example:** ```vue @@ -143,20 +143,20 @@ layout: intro
- 긴 코드를 축소해서 표시 + Show long code scaled down
``` -### 10. VDrag - 드래그 가능한 요소 +### 10. VDrag - draggable element -요소를 드래그로 이동할 수 있게 만듭니다. +Makes an element movable by dragging. -**사용 예시:** +**Example:** ```vue
- 이 박스를 드래그하세요 + Drag this box
@@ -169,18 +169,18 @@ layout: intro ## Media -### 11. SlidevVideo - 비디오 임베드 +### 11. SlidevVideo - video embed -비디오를 슬라이드에 삽입합니다. +Inserts a video into a slide. **Props:** -- `controls`: 컨트롤 표시 여부 (기본값: true) -- `autoplay`: 자동 재생 (기본값: false) -- `autoreset`: 슬라이드 나갈 때 리셋 (기본값: true) -- `poster`: 포스터 이미지 URL -- `timestamp`: 시작 시간 (초) +- `controls`: whether to show controls (default: true) +- `autoplay`: autoplay (default: false) +- `autoreset`: reset when leaving the slide (default: true) +- `poster`: poster image URL +- `timestamp`: start time (seconds) -**사용 예시:** +**Example:** ```vue @@ -196,33 +196,33 @@ layout: intro ``` -### 12. Youtube - YouTube 임베드 +### 12. Youtube - YouTube embed -YouTube 비디오를 삽입합니다. +Inserts a YouTube video. **Props:** -- `id`: YouTube 비디오 ID (필수) -- `width`: 너비 (기본값: 100%) -- `height`: 높이 (기본값: auto) +- `id`: YouTube video ID (required) +- `width`: width (default: 100%) +- `height`: height (default: auto) -**사용 예시:** +**Example:** ```vue ``` -### 13. Tweet - Twitter/X 임베드 +### 13. Tweet - Twitter/X embed -트윗을 슬라이드에 삽입합니다. +Inserts a tweet into a slide. **Props:** -- `id`: 트윗 ID (필수) -- `scale`: 확대/축소 비율 (기본값: 1) -- `conversation`: 대화 스레드 표시 (기본값: 'none') -- `cards`: 카드 표시 여부 (기본값: 'visible') +- `id`: tweet ID (required) +- `scale`: scale ratio (default: 1) +- `conversation`: show the conversation thread (default: 'none') +- `cards`: whether to show cards (default: 'visible') -**사용 예시:** +**Example:** ```vue @@ -238,15 +238,15 @@ YouTube 비디오를 삽입합니다. ## Conditional Rendering -### 14. LightOrDark - 테마 기반 조건부 렌더링 +### 14. LightOrDark - theme-based conditional rendering -Light/Dark 모드에 따라 다른 콘텐츠를 표시합니다. +Displays different content depending on Light/Dark mode. **Slots:** -- `#dark`: Dark 모드에서 표시 -- `#light`: Light 모드에서 표시 +- `#dark`: shown in Dark mode +- `#light`: shown in Light mode -**사용 예시:** +**Example:** ```vue