Files
llm-wiki/docs/superpowers/plans/2026-06-04-three-platform-sync-phase1-commands.md
T

471 lines
22 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 3-플랫폼 동기화 Phase 1 — commands Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Claude의 13개 슬래시 command(`.claude/commands/*.md`)를 Codex CLI **skills**(`.agents/skills/<cmd>/SKILL.md`)와 Antigravity CLI **workflows**(`.agents/workflows/<cmd>.md`)로 생성하는 기능을 `scripts/sync_automation.py``commands` 타깃으로 추가한다.
**Architecture:** Phase 0의 SSOT→생성 모델을 commands로 확장한다. SSOT = `.claude/commands/<cmd>.md`(frontmatter `description`+`argument-hint` + 본문). 생성기는 (1) frontmatter를 플랫폼별 헤더로 변환, (2) `$ARGUMENTS` 토큰을 자연어 각괄호 인자(`argument-hint` 값)로 치환, (3) 본문의 platform-neutral 절차는 그대로 보존, (4) codex skill / antigravity workflow 두 포맷으로 직렬화한다. command 본문은 agent 본문과 달리 Claude 전용 tool 표현(`Read tool` 등)을 쓰지 않고 절차적 prose + shell + 서브에이전트 이름(Phase 0에서 3 플랫폼에 모두 포팅됨)만 참조하므로 기계 변환이 충분하다.
**Tech Stack:** Python 3.12 (stdlib), pytest (venv: `/home/donghyeon/dev/llm-wiki-private/.venv/bin/python`).
---
## 배경 / 확정된 포맷 사실 (공식문서 + 리서치)
- **Codex skills** (`developers.openai.com/codex/skills`): 디스커버리 `<repo>/.agents/skills/<name>/SKILL.md`(repo 커밋). frontmatter 필수 2필드 `name`(폴더명과 일치 권장) + `description`(언제 발동). **인자 placeholder 없음 — 자연어로 전달**(`$ARGUMENTS`/`$1` 미지원). `/skills` picker 또는 `$name` 멘션으로 명시 호출 + description 의미 매칭.
- **Antigravity workflows** (Google Codelabs / atamel.dev): `<repo>/.agents/workflows/<name>.md`, frontmatter **`description`만**(name=파일명), 본문은 prose 지시, 인자는 `<idea>` 식 각괄호 prose(placeholder 없음), `/<name> <args>` 호출.
- Codelab 실제 예시(verbatim):
```
---
description: Start the Autonomous AI Developer Pipeline sequence with a new idea
---
When the user types `/startcycle <idea>`, orchestrate the development process ...
```
- **경로 규약 결정**: 이 repo는 이미 `.agents/`(복수) 규약(`.agents/agents/`, `.agents/hooks.json`)을 쓰고 antigravity가 그것을 로드 중 → **antigravity workflows도 `.agents/workflows/`(복수)** 로 통일. codex skills는 공식 고정 경로 `.agents/skills/`.
- **알려진 충돌(미해결, 경험적 확인 필요)**: 일부 antigravity 빌드는 `.agents/skills/`도 skill로 읽어, codex command-skill이 antigravity에 semantic-trigger skill로 *이중 등록*될 수 있음(workflow + skill). 공식문서로 확정 불가 → **Task 1에서 실제 설치된 CLI로 경험적 확인** 후 필요 시 완화.
### 13개 command (SSOT: `.claude/commands/*.md`)
`blogify` · `branch` · `branch-spec` · `coverage` · `daily` · `depth` · `ingest` · `interviewize` · `lint` · `migrate-claims` · `projectize` · `query` · `tag`
frontmatter 공통: `description:` + `argument-hint:`. 본문은 `$ARGUMENTS` 토큰 + 절차(`## 작업 절차`) + 규칙. 일부는 `.claude/hooks/wiki_structure_lint.py`(실제 repo 스크립트, 크로스플랫폼 실행 가능 — 유지)와 포팅된 서브에이전트(`branch-depth-auditor` 등) 참조.
---
## File Structure
- Modify: `scripts/sync_automation.py` — `COMMAND_NAMES` 리스트, command frontmatter 파서 재사용(`parse_frontmatter`), `transform_command_body`, `render_codex_skill`, `render_antigravity_workflow`, `generate_command_one`, `main()` 의 `target` choices에 `commands` 추가.
- Modify: `scripts/test_sync_automation.py` — command 변환 단위 테스트.
- Create (생성물): `.agents/skills/<cmd>/SKILL.md` ×13 (codex), `.agents/workflows/<cmd>.md` ×13 (antigravity).
- Create: `docs/superpowers/notes/2026-06-04-phase1-empirical-format-check.md` — Task 1 경험적 확인 결과 기록.
- Modify (말미): `CLAUDE.md` §2 표 + `.codex/agents/README.md` — commands→skills/workflows 매핑 1단락.
> 책임 경계: 생성기는 frontmatter 변환 + `$ARGUMENTS` 치환 + 포맷 직렬화만. 본문 절차 prose는 platform-neutral이므로 보존. codex skill 본문에서 antigravity 전용 표기를 만들지 않고, antigravity workflow 본문에서 codex 전용 표기를 만들지 않는다(생성기가 플랫폼별로 분기).
---
## Task 1: 경험적 포맷·충돌 확인 + 결정 잠금
**Files:**
- Create: `docs/superpowers/notes/2026-04-phase1-empirical-format-check.md` (디렉토리 없으면 생성)
> 목적: 공식문서가 확정 못한 두 가지를 실제 설치된 CLI로 확인하고, 생성기 타깃 경로/인자 규약을 잠근다. CLI가 없으면 "가정 + 보류" 로 명시 기록(생성물은 가정대로 진행, 추후 검증).
- [ ] **Step 1: 설치 여부 확인**
```bash
cd /home/donghyeon/dev/llm-wiki-private
command -v codex && codex --version 2>&1 | head -1 || echo "codex: NOT INSTALLED"
ls -d ~/.gemini/antigravity-cli 2>/dev/null && echo "antigravity-cli home present" || echo "antigravity: home absent"
command -v agy 2>&1 || echo "agy (antigravity CLI) not on PATH"
```
- [ ] **Step 2: (codex 있으면) skill 디스커버리 경로 확인**
scratch skill을 만들어 codex가 `.agents/skills/`를 읽는지 확인:
```bash
mkdir -p /tmp/codex-skill-probe/.agents/skills/probe-skill
printf -- '---\nname: probe-skill\ndescription: probe codex skill discovery\n---\nprobe body\n' > /tmp/codex-skill-probe/.agents/skills/probe-skill/SKILL.md
# codex의 skills 목록 확인 (codex 설치 시): 예) `codex` TUI에서 /skills, 또는 가능한 CLI 서브커맨드
codex --help 2>&1 | grep -iE "skill|prompt" || echo "no skill subcommand surfaced in --help"
```
결과(읽힘/안읽힘/불명)를 노트에 기록.
- [ ] **Step 3: (antigravity 있으면) `.agents/skills/` 이중 로드 여부 확인**
antigravity가 `.agents/skills/`를 skill로 읽는지(=codex command-skill 이중 등록 위험) 실제 빌드에서 확인. 가능한 방법: antigravity CLI의 skill/workflow 목록 출력 커맨드, 또는 `~/.gemini/antigravity-cli/` 로그/registry 확인. 결과를 노트에 기록.
- [ ] **Step 4: 결정 기록**
노트에 다음을 표로 확정(경험 결과 또는 "UNVERIFIED — 가정"):
| 항목 | 결정 | 근거 |
|---|---|---|
| codex skill 경로 | `.agents/skills/<cmd>/SKILL.md` | 공식 디스커버리 경로 |
| antigravity workflow 경로 | `.agents/workflows/<cmd>.md` | repo `.agents/` 복수 규약 일치 |
| `$ARGUMENTS` 매핑 | argument-hint 각괄호 prose로 치환 | 양 플랫폼 placeholder 미지원 |
| `.agents/skills/` antigravity 이중로드 | {{읽음→완화 필요 / 안읽음→무관 / UNVERIFIED}} | Step 3 결과 |
- [ ] **Step 5: Commit**
```bash
cd /home/donghyeon/dev/llm-wiki-private
git add docs/superpowers/notes/
git commit -m "docs(phase1): empirical format + skills-collision check, lock target paths"
```
---
## Task 2: command 파싱 + skill/workflow 직렬화 (순수 함수, TDD)
**Files:**
- Modify: `scripts/sync_automation.py`
- Test: `scripts/test_sync_automation.py`
- [ ] **Step 1: Write the failing test**
```python
# append to scripts/test_sync_automation.py
_SAMPLE_CMD = (
"---\n"
"description: 브랜치 노트의 구현 착수 깊이 점검\n"
"argument-hint: <브랜치 이름>\n"
"---\n\n"
"브랜치 노트 1개의 깊이를 점검합니다.\n\n"
"**브랜치 이름:** $ARGUMENTS\n\n"
"## 작업 절차\n1. `branch-depth-auditor` 서브에이전트를 디스패치한다.\n"
)
def test_transform_command_body_replaces_arguments():
out = s.transform_command_body(_body_of(_SAMPLE_CMD), "<브랜치 이름>")
assert "$ARGUMENTS" not in out
assert "<브랜치 이름>" in out
# platform-neutral 절차/에이전트 참조는 보존
assert "branch-depth-auditor 서브에이전트를 디스패치" in out
def test_render_codex_skill_frontmatter():
out = s.render_codex_skill(
name="depth",
description="브랜치 노트의 구현 착수 깊이 점검",
arg_hint="<브랜치 이름>",
body="**브랜치 이름:** <브랜치 이름>\n\n## 작업 절차\n1. ...\n",
)
fm, body = s.parse_frontmatter(out)
assert fm["name"] == "depth"
assert fm["description"] # non-empty
assert "$ARGUMENTS" not in body
assert "## 작업 절차" in body
def test_render_antigravity_workflow_frontmatter_and_invocation():
out = s.render_antigravity_workflow(
name="depth",
description="브랜치 노트의 구현 착수 깊이 점검",
arg_hint="<브랜치 이름>",
body="## 작업 절차\n1. ...\n",
)
fm, body = s.parse_frontmatter(out)
assert set(fm.keys()) == {"description"} # name comes from filename, not frontmatter
# 호출 안내가 본문 상단에 있어야 함 (Codelab 패턴)
assert "/depth <브랜치 이름>" in body
assert "## 작업 절차" in body
```
(헬퍼 `_body_of` 는 테스트 상단에 추가: `def _body_of(md): return s.parse_frontmatter(md)[1]`.)
- [ ] **Step 2: Run test to verify it fails**
Run: `cd /home/donghyeon/dev/llm-wiki-private && .venv/bin/python -m pytest scripts/test_sync_automation.py -k "command or codex_skill or workflow" -v`
Expected: FAIL with `AttributeError: ... 'transform_command_body'`.
- [ ] **Step 3: Write minimal implementation**
```python
# add near COMMAND-related code in sync_automation.py
COMMAND_NAMES = [
"blogify", "branch", "branch-spec", "coverage", "daily", "depth",
"ingest", "interviewize", "lint", "migrate-claims", "projectize",
"query", "tag",
]
CLAUDE_COMMANDS = REPO / ".claude" / "commands"
CODEX_SKILLS = REPO / ".agents" / "skills"
ANTIGRAV_WORKFLOWS = REPO / ".agents" / "workflows"
def transform_command_body(body: str, arg_hint: str) -> str:
# Neither Codex skills nor Antigravity workflows support a $ARGUMENTS
# placeholder; both take arguments as natural language. Replace the token
# with the argument-hint's angle-bracket prose so the body still reads well.
return body.replace("$ARGUMENTS", arg_hint)
def render_codex_skill(name: str, description: str, arg_hint: str, body: str) -> str:
# description drives implicit trigger; fold in the arg hint for clarity.
desc = f"{description} (입력: {arg_hint})"
return (
"---\n"
f"name: {name}\n"
f"description: {desc}\n"
"---\n\n"
f"{body.rstrip()}\n"
)
def render_antigravity_workflow(name: str, description: str, arg_hint: str, body: str) -> str:
invocation = f"사용자가 `/{name} {arg_hint}` 를 입력하면 아래 절차를 수행한다.\n\n"
return (
"---\n"
f"description: {description}\n"
"---\n\n"
f"{invocation}{body.rstrip()}\n"
)
```
- [ ] **Step 4: Run test to verify it passes**
Run: `cd /home/donghyeon/dev/llm-wiki-private && .venv/bin/python -m pytest scripts/test_sync_automation.py -k "command or codex_skill or workflow" -v`
Expected: PASS.
- [ ] **Step 5: Commit**
```bash
cd /home/donghyeon/dev/llm-wiki-private
git add scripts/sync_automation.py scripts/test_sync_automation.py
git commit -m "feat(sync): command body transform + codex skill / antigravity workflow renderers"
```
---
## Task 3: command 로더 + CLI `commands` 타깃 (TDD)
**Files:**
- Modify: `scripts/sync_automation.py`
- Test: `scripts/test_sync_automation.py`
- [ ] **Step 1: Write the failing test**
```python
def test_load_command_inputs_for_existing_command():
ci = s.load_command_inputs("depth")
assert ci.name == "depth"
assert ci.description
assert ci.arg_hint.startswith("<") or "--" in ci.arg_hint
assert "$ARGUMENTS" in ci.body or "작업 절차" in ci.body # raw body still has token
def test_generate_command_writes_both(tmp_path, monkeypatch):
monkeypatch.setattr(s, "CODEX_SKILLS", tmp_path / "skills")
monkeypatch.setattr(s, "ANTIGRAV_WORKFLOWS", tmp_path / "workflows")
s.generate_command_one("depth", check=False)
skill = tmp_path / "skills" / "depth" / "SKILL.md"
wf = tmp_path / "workflows" / "depth.md"
assert skill.exists() and wf.exists()
sfm, sbody = s.parse_frontmatter(skill.read_text())
assert sfm["name"] == "depth" and "$ARGUMENTS" not in sbody
wfm, wbody = s.parse_frontmatter(wf.read_text())
assert "/depth" in wbody and "$ARGUMENTS" not in wbody
def test_main_commands_target_check_is_clean_after_generate():
# after generation (Task 4), --check must be drift-free
rc = s.main(["commands", "--check"])
assert rc == 0
```
> 마지막 테스트는 Task 4 생성 이후에만 통과한다. Task 3 단계에서는 앞 두 테스트만 대상으로 실행하고, 세 번째는 Task 4 검증에서 green 확인.
- [ ] **Step 2: Run test to verify it fails**
Run: `cd /home/donghyeon/dev/llm-wiki-private && .venv/bin/python -m pytest scripts/test_sync_automation.py -k "load_command or generate_command" -v`
Expected: FAIL with `AttributeError: ... 'load_command_inputs'`.
- [ ] **Step 3: Write minimal implementation**
```python
@dataclass
class CommandInputs:
name: str
description: str
arg_hint: str
body: str
def load_command_inputs(name: str) -> CommandInputs:
fm, body = parse_frontmatter((CLAUDE_COMMANDS / f"{name}.md").read_text())
return CommandInputs(
name=name,
description=fm.get("description", "").strip(),
arg_hint=fm.get("argument-hint", "").strip(),
body=body,
)
def generate_command_one(name: str, check: bool, drift: list[str] | None = None) -> None:
drift = drift if drift is not None else []
ci = load_command_inputs(name)
tbody = transform_command_body(ci.body, ci.arg_hint)
skill_text = render_codex_skill(ci.name, ci.description, ci.arg_hint, tbody)
wf_text = render_antigravity_workflow(ci.name, ci.description, ci.arg_hint, tbody)
_write_or_check(CODEX_SKILLS / name / "SKILL.md", skill_text, check, drift)
_write_or_check(ANTIGRAV_WORKFLOWS / f"{name}.md", wf_text, check, drift)
```
그리고 `main()` 을 확장: `target` choices에 `commands` 추가하고 분기.
```python
def main(argv: list[str] | None = None) -> int:
ap = argparse.ArgumentParser(description="Sync Claude agents/commands -> Codex/Antigravity native files")
ap.add_argument("target", choices=["agents", "commands"], help="what to sync")
ap.add_argument("--check", action="store_true", help="fail (exit 2) if outputs drift from SSOT")
ap.add_argument("--only", help="single name (default: all)")
args = ap.parse_args(argv)
if args.target == "agents":
names = [args.only] if args.only else AGENT_NAMES
gen = generate_one
label = "agents (codex .toml + antigravity agent.json)"
else:
names = [args.only] if args.only else COMMAND_NAMES
gen = generate_command_one
label = "commands (codex skill + antigravity workflow)"
drift: list[str] = []
for name in names:
try:
gen(name, check=args.check, drift=drift)
except FileNotFoundError as e:
print(f"ERROR: missing SSOT for '{name}': {e.filename}", file=sys.stderr)
return 1
if args.check and drift:
print("DRIFT detected in:\n " + "\n ".join(drift), file=sys.stderr)
return 2
action = "checked" if args.check else "generated"
print(f"{action} {len(names)} {label}")
return 0
```
- [ ] **Step 4: Run test to verify it passes**
Run: `cd /home/donghyeon/dev/llm-wiki-private && .venv/bin/python -m pytest scripts/test_sync_automation.py -k "load_command or generate_command" -v`
Expected: PASS. Also run the FULL suite to confirm the `main()` refactor didn't break agents:
Run: `.venv/bin/python -m pytest scripts/test_sync_automation.py -q`
Expected: all green. Then sanity: `python3 scripts/sync_automation.py agents --check` still exits 0.
- [ ] **Step 5: Commit**
```bash
cd /home/donghyeon/dev/llm-wiki-private
git add scripts/sync_automation.py scripts/test_sync_automation.py
git commit -m "feat(sync): commands target — load + generate codex skills / antigravity workflows"
```
---
## Task 4: 13개 command 전체 생성 + 검증 + drift-0
**Files:**
- Generate: `.agents/skills/<cmd>/SKILL.md` ×13, `.agents/workflows/<cmd>.md` ×13
- [ ] **Step 1: 생성 + 검증**
```bash
cd /home/donghyeon/dev/llm-wiki-private
python3 scripts/sync_automation.py commands
echo "--- counts ---"
echo "skills: $(ls .agents/skills/*/SKILL.md | wc -l) | workflows: $(ls .agents/workflows/*.md | wc -l)"
echo "--- validate ---"
.venv/bin/python -c "
import sys; sys.path.insert(0,'scripts'); import sync_automation as s
for n in s.COMMAND_NAMES:
sfm,sbody=s.parse_frontmatter(open(f'.agents/skills/{n}/SKILL.md').read())
assert sfm['name']==n and sfm['description'] and '\$ARGUMENTS' not in sbody, n
wfm,wbody=s.parse_frontmatter(open(f'.agents/workflows/{n}.md').read())
assert 'description' in wfm and f'/{n}' in wbody and '\$ARGUMENTS' not in wbody, n
print('all 13 commands ok (skill name+desc, workflow desc+invocation, no \$ARGUMENTS)')
"
echo "--- no {{ }} placeholders leaked into workflows (antigravity G3) ---"
! grep -l '{{' .agents/workflows/*.md || echo "WARNING: {{ }} found"
```
Expected: `skills: 13 | workflows: 13`, validation ok, no `{{` warning.
- [ ] **Step 2: drift-0**
```bash
cd /home/donghyeon/dev/llm-wiki-private
python3 scripts/sync_automation.py commands --check; echo "exit=$?"
```
Expected: `checked 13 commands ...` + `exit=0`.
- [ ] **Step 3: 전체 테스트(세 번째 main commands check 테스트 포함)**
Run: `.venv/bin/python -m pytest scripts/test_sync_automation.py -q`
Expected: all green.
- [ ] **Step 4: Commit**
```bash
cd /home/donghyeon/dev/llm-wiki-private
git add .agents/skills/ .agents/workflows/
git commit -m "feat(sync): generate 13 commands as codex skills + antigravity workflows"
```
---
## Task 5: 대표 command 실호출 스모크 (CLI 있으면)
> Phase 0 agents와 달리 commands는 사용자가 실제로 호출하는 표면이므로, 설치된 CLI에서 1~2개를 실호출해 형식이 맞는지 확인한다. CLI 미설치면 SKIP + 노트 기록.
- [ ] **Step 1: codex skill 인식 확인 (codex 있으면)**
`.agents/skills/depth/SKILL.md` 가 codex의 `/skills` 또는 `$depth` 로 인식되는지 확인. 인식 안 되면 frontmatter/경로를 Task 1 노트와 대조해 진단.
- [ ] **Step 2: antigravity workflow 인식 확인 (antigravity 있으면)**
`.agents/workflows/depth.md` 가 antigravity에서 `/depth` 로 등록되는지 확인. 동시에 Task 1의 이중로드 가설(코덱스 skill이 antigravity에 새는지)을 `/skills` 목록으로 재확인.
- [ ] **Step 3: 결과를 Task 1 노트에 추가 기록 + (필요 시) 완화**
- 이중로드가 실제로 발생하고 바람직하지 않으면: 완화안을 노트에 적고 사용자에게 에스컬레이션(예: codex skill만 두고 antigravity는 workflow만 쓰도록 build 설정, 또는 경로 분리). **이 단계에서 임의로 큰 구조 변경하지 말 것** — 결과만 보고.
- [ ] **Step 4: Commit (노트 갱신 시)**
```bash
cd /home/donghyeon/dev/llm-wiki-private
git add docs/superpowers/notes/
git commit -m "docs(phase1): empirical smoke results for codex skills / antigravity workflows"
```
---
## Task 6: 문서 갱신 (commands→skills/workflows 매핑)
**Files:**
- Modify: `CLAUDE.md` (§2 디렉터리 역할 표 또는 자동화 섹션)
- Modify: `.codex/agents/README.md`
- [ ] **Step 1: CLAUDE.md 에 1단락**
§2의 자동화 목록에 codex/antigravity의 command 등가물을 명시:
- Codex: `.agents/skills/<cmd>/SKILL.md` (13개, `$cmd` 호출), 생성 `python3 scripts/sync_automation.py commands`.
- Antigravity: `.agents/workflows/<cmd>.md` (13개, `/cmd` 호출).
- 인자는 placeholder 없이 자연어(각괄호 prose).
- [ ] **Step 2: `.codex/agents/README.md` 의 "Native generation" 노트에 commands 줄 추가**
`sync_automation.py commands` 로 13개 command가 `.agents/skills/`(codex) + `.agents/workflows/`(antigravity)에 생성됨을 1줄 추가.
- [ ] **Step 3: 검증 + Commit**
```bash
cd /home/donghyeon/dev/llm-wiki-private
grep -c "sync_automation.py commands" CLAUDE.md .codex/agents/README.md
git add CLAUDE.md .codex/agents/README.md
git commit -m "docs(sync): document commands -> codex skills + antigravity workflows"
```
---
## Phase 1 완료 기준 (Definition of Done)
- `sync_automation.py commands` 타깃 동작 + 테스트 green.
- `.agents/skills/<cmd>/SKILL.md` 13개 + `.agents/workflows/<cmd>.md` 13개 생성·검증.
- `python3 scripts/sync_automation.py commands --check` exit 0 (drift 0).
- `$ARGUMENTS` 토큰이 생성물에 0개, antigravity workflow에 `{{ }}` 0개.
- Task 1/5 경험적 확인 결과가 노트에 기록(또는 CLI 미설치 시 가정으로 명시).
- CLAUDE.md + codex README에 매핑 문서화.
이후: **Phase 2**(hooks → `.codex/hooks.json`, `AGENTS.md`, CLAUDE.md의 구식 codex "수동 cat" 서술 정리 — line 76)는 별도 plan.
---
## Self-Review (작성자 체크)
- **Spec coverage**: 설계 §4 Phase 1(commands → codex skills + antigravity workflows, 생성기 commands 타깃 확장)의 모든 요소가 Task 2~4에 매핑. 설계 §6 리스크의 `.agents/skills/` 충돌은 Task 1/5 경험적 확인으로 처리.
- **Placeholder scan**: 코드 스텝은 실제 코드 포함. Task 1/5는 경험적 절차라 결과가 환경 의존 — 명령 + 기록 표 + "UNVERIFIED 시 가정 명시" 로 결정론화.
- **Type consistency**: `transform_command_body(body, arg_hint)`, `render_codex_skill(name,description,arg_hint,body)`, `render_antigravity_workflow(name,description,arg_hint,body)`, `CommandInputs`, `load_command_inputs(name)`, `generate_command_one(name,check,drift)` — 전 Task 일관. `_write_or_check`/`parse_frontmatter`는 Phase 0 함수 재사용.
- **알려진 한계**: command 본문이 platform-neutral하다는 가정에 의존(실측: `.claude/commands/*.md`는 `Read tool` 류 미사용, shell·서브에이전트명·repo 경로만 참조). 만약 특정 command가 Claude 전용 표기를 쓰면 그 command만 생성 후 hand-review 필요 — Task 4 검증의 `$ARGUMENTS`/`{{`grep으로 1차 포착.