with one click
emberdeck
// Emberdeck `ed` CLI 로 카드 기반 설계 지식 관리. emberdeck 가 설정된 프로젝트(`./.emberdeck/`)에서 코드 작성/수정/리팩토링 시 트리거.
// Emberdeck `ed` CLI 로 카드 기반 설계 지식 관리. emberdeck 가 설정된 프로젝트(`./.emberdeck/`)에서 코드 작성/수정/리팩토링 시 트리거.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | emberdeck |
| description | Emberdeck `ed` CLI 로 카드 기반 설계 지식 관리. emberdeck 가 설정된 프로젝트(`./.emberdeck/`)에서 코드 작성/수정/리팩토링 시 트리거. |
| 신호 | 워크플로 |
|---|---|
.emberdeck/ 없음 또는 카드 0 | onboarding |
카드 ≥1 + glossary.yaml 비어있음 | glossary-backfill |
| 코드 변경 (production 소스) | feature |
| 코드 변경 없음 (deps/CI/lint/docs) | 카드 워크플로 스킵 |
| 수정 의도 없음 | 카드 읽기만 |
<glossary_rules> glossary 추가 기준 — 4 모두 충족 시:
카드 glossary 필드: 그 카드의 주요 토픽만. 본문 단어 색인 X. 같은 용어 여러 카드 선언 OK.
</glossary_rules>
| 명령 | 시점 | 사용자 확인 |
|---|---|---|
ed glossary define WORD=DEF [--from f.yaml] | 새 도메인 개념. 1회 ≤50개. all-or-nothing. | 예 |
ed glossary lookup [WORD] | 조회 | X |
ed glossary remove WORD --yes | 제거. 참조 카드 drifted. | 예 |
ed glossary rename OLD NEW [--def TEXT] | 리네임. glossary + 카드 glossary 필드 자동. | 예 |
ed reset --yes | 파괴적: 모든 카드 + glossary 삭제 | 예 |
ed card create KEY --type T --summary S [--parent P] [--from f.yaml] [--glossary W] | 생성 | 예 |
ed card update KEY [--field name=value] [--patch f.yaml] [--body f.md] [--glossary W] | 수정. 스칼라(summary/status/parent/type)는 --field. namespace 는 --patch. | 예 (자명한 변경 외) |
ed card get KEY [--history] | 조회 | X |
ed card delete KEY [--force] --yes | 파괴적. --force: 자식 cascade + cross_domain_dep 자동 제거. | 예 |
ed card rename OLD NEW | FK CASCADE + 파일 이동 + 본문/cross_domain_dep 재작성 | 예 |
ed card export KEY [--out FILE|--in-place] | DB→파일/STDOUT 렌더 | X |
ed card set-status KEY {draft|active|drifted|retired} [--reason TEXT] | active 시 activation guard | 예 |
ed card list [--type T] [--status S] [--parent P] [--tag T] [--symbol N] [--file F] [--glossary W] | --symbol/--glossary 는 --tag 와 상호배타 | X |
ed card search "<query>" | FTS5. 잘못된 쿼리 → FTS_SYNTAX_ERROR (exit 2) | X |
ed card tree KEY [--depth N] | parent-child 계층 | X |
ed card context KEY [--depth N] | relations + parent BFS | X |
ed card relations KEY | 직접 forward+reverse | X |
ed validate cards | 정합성 (계층/orphan/glossary/chain 등). partial → exit 2 | X |
ed validate links [KEY] | codeLinks resolve 검증 | X |
ed validate | cards + links 종합 | X |
ed check drift [KEY] [--max-depth N] [--no-auto-transition] | 6종 drift 다중 검출. 기본 active→drifted 자동 전이. CI 는 --no-auto-transition. | 예 (status 변경) |
ed check coverage <KEY> 또는 ed check coverage --uncovered [--include-internal]|--suggest | KEY 위치인자 또는 모드 플래그 둘 중 하나 필수. --uncovered 는 기본 exported-only (internal/private 제외). --include-internal 로 전체 surface 포함 | X |
ed check impact <files...> [--symbol N] | 변경 전 영향 분석 | X |
ed check regression <files...> | drifted 비율 vs threshold. fail 시 exit 2 | X |
ed check interactions <keys...> | shared symbol/file/import + 충돌 | X |
ed spec annotate [KEY] [--prune] | 기본 additive — DB codeLink → source @spec JSDoc 추가만. --prune 명시 시 orphan(매칭 codeLink 사라진 어노테이션) 제거 | 예 (--prune 시) |
ed spec sync | 소스 @spec → DB codeLinks 재구성 | X |
ed spec sync-symbols [--since TS] | renamed/moved 심볼 적용 | X |
ed bulk create --from FILE | YAML/JSON 배열 일괄 생성. partial → exit 2 | 예 |
ed bulk sync [PATH] | 카드 파일 → DB. partial → exit 2 | X |
ed analyze | health/coverage/drift/glossary 종합 | X |
출력은 항상 JSON 봉투 {schemaVersion, status, data, warnings, errors, error?}. --quiet 만 stdout 을 결과 key 로 축약 (diagnostics → stderr).
exit: 0=ok, 1=generic, 2=validation/usage, 3=not_found, 4=conflict, 5=permission/IO, 6=config_missing, 7=transient, 130=SIGINT.
<card_fields>
| 필드 | 필수 | 설명 |
|---|---|---|
key type: principle status summary | ✓ | |
principle.statement | ✓ | MUST/SHALL/SHOULD/MAY 한 문장 |
principle.rationale | ✓ | 배경 |
principle.applies_to | ✓ | "*" 또는 카드 키/glob 배열 |
principle.enforcement | ✓ | blocking|warning|advisory |
principle.metric | [{name, threshold, unit, comparator, kind?: threshold|budget, window_kind?, distributable?}] | |
principle.exemptions | [{target, reason}] | |
principle.references | [{title, url}] | |
parent | ✗ | 금지 (root only) |
| 필드 | 필수 | 설명 |
|---|---|---|
key type: domain status summary | ✓ | |
domain.overview | ✓ | 비-empty 산문 |
domain.scope | ✓ | 비-empty 산문, IN/OUT 명시 |
domain.cross_domain_dependencies | [{domain: <다른-domain-키>, relationship}]. 타깃 type 반드시 domain | |
parent | ✗ | 금지 |
| 필드 | 필수 | 설명 |
|---|---|---|
key type: brief parent status summary | ✓ | parent 는 domain |
brief.context | ✓ | {problem, impact: [{statement, metric?}]} |
brief.scope.goals | ✓ | [{id: G-001, statement}], ≥1, 모두 ≥1 flow 가 covers |
brief.scope.non_goals | ✓ | [{id: NG-001, statement}] |
brief.scope.assumptions | ✓ | [{id: A-001, statement, verification?, reevaluate_when?}] |
brief.flow | ✓ | [{id: S-H-01|S-F-01, kind: happy|failure, given, when, then, covers: [G-id]}], ≥1 happy + ≥1 failure |
brief.design | ✓ | {overview, components: [{name, responsibility, interacts_with: []}], data_flow: [{from, to, payload, trigger}], invariants: [{id: DI-001, statement}]}. interacts_with/data_flow 는 빈 배열 OK |
brief.policy | ✓ | [{id: R-001, subject, keyword: MUST|SHALL|.., predicate, governs: [S-id]}] |
brief.external | ✓ | [{id: C-001, statement, reference: {title, locator}}] |
brief.compatibility | ✓ | {guarantees: [{subject, version_range, breaks_if}], migration_path?}. guarantees 빈 배열 OK |
brief.limits | ✓ | [{id: KL-001, statement}] |
brief.criteria | ✓ | [{id: SC-001, type, measure, verifies: [S-id]}]. measure 는 type 별 다른 객체: numeric → {predicate, value, comparator, unit, reference?}, binary → {predicate, method?, reference?}, verification → {method, reference, predicate?, unit?}. 모두 flow 가 verifies |
brief.rationale | ✓ | {alternatives: [≥2개 {option, pros: [], cons: []}], chosen: {option, reasoning}, trade_off?, addresses: []}. addresses 빈 배열이라도 키는 필수 |
cross-ref 자동 검증: flow.covers→goals, policy.governs→flow, criteria.verifies→flow, rationale.addresses→external\|limits. 모든 goal 은 flow 가 cover, 모든 flow 는 policy/criteria 양쪽에 매핑.
| 필드 | 필수 | 설명 |
|---|---|---|
key type: spec parent status summary | ✓ | parent 는 brief|spec |
codeLinks | ✓ | [{kind, file, symbol}], ≥1, active 시 모두 resolve |
spec.preconditions | ✓ | [{id: PRE-001, condition, binds: [{file, symbol}], derives: "brief-key#item-id"}], ≥1 |
spec.postconditions | ✓ | [{id: POST-001, guarantee, keyword: MUST|SHALL, binds, derives}], ≥1 |
spec.invariants | ✓ | [{id: INV-001, statement, binds, always_holds: per-call|cross-call|cross-process}], ≥1 |
spec.failures | ✓ | [{violation, behavior, exception: {class, file}}], ≥1. 비-throwing failure (return null / error code) 는 exception: {class: "none", file: ""} |
spec.state_transitions | [{from, trigger, to, binds}] | |
spec.code_patterns | [{id: PAT-001, pattern: "ast-grep", rule: forbidden|required, description?}]. boundary 안에서만 매칭. mass-flip 주의 — N 카드에 같은 패턴 추가 시 N 카드 일괄 drifted 자동 전이 | |
boundary | ["src/auth/**"] glob 배열 | |
relations | brief 키 배열. parent 가 이미 brief 면 불필요 |
cross-ref 자동: 모든 binds 는 카드 codeLinks 에 존재, 모든 derives 는 "brief-key#item-id" 형식 + 실제 brief 항목.
</card_fields>
<card_splitting> 분리 트리거 (하나라도 true):
합침 조건 (모두 true):
brief 분해 신호 (sibling brief 분리, 같은 domain 아래):
domain 분해 신호:
cross_domain_dependencies 양방향 동등
</card_splitting><self_review> 모든 카드 생성/갱신 전. 한 항목이라도 실패 → 수정.
전체 공통:
domain:
brief:
spec:
code_patterns 추가
</self_review><card_analysis> 카드 생성/갱신 전 사용자에게:
### Card analysis: {key}
- 타입: principle | domain | brief | spec
- 부모: {parent 키 또는 "root"}
- Glossary: [{주요 도메인 개념}]
- 보장: {이 카드가 보장하는 것}
- 제외: {의도적으로 스코프 밖}
- 위반 시: {구체적 결과}
</card_analysis>
<glossary_proposal>
ed glossary define 호출 전:
### Glossary 제안
| 용어 | 정의 | Evidence (≥1 파일 또는 카드) |
|------|------|------------------------------|
| ... | 한 줄 도메인 의미 | src/foo.ts:42 / brief 'order-payment' |
</glossary_proposal>
<error_recovery>
ed validate cards warnings:
| 타입 | 해결 |
|---|---|
| orphan-card | ed card update KEY --field parent=<올바른> |
| broken-parent | ed card update KEY --field parent=<존재> 또는 parent 생성 |
| type-hierarchy-violation | 4-tier 에 맞게 parent 재지정 |
| broken-relation | ed card update KEY --patch 로 dead reference 제거 |
| broken-cross-domain-dep | 타깃 domain 생성 또는 entry 제거 |
| glossary-broken | ed glossary define 또는 --glossary <새 목록> |
| broken-chain | spec 의 parent=brief 또는 relations=[brief-key] |
| empty-tree | 자식 카드 추가 또는 draft 강등 |
| stale-db-row | ed bulk sync 또는 ed card delete KEY |
| orphan-file | ed bulk sync PATH |
| key-mismatch | 파일 이름 변경 또는 frontmatter 갱신 |
ed validate links broken:
ed spec sync-symbolsed check drift driftType 별:
| driftType | 해결 |
|---|---|
| broken_link | ed spec sync-symbols 또는 --patch 로 codeLink 갱신 |
| boundary_inactive | boundary 패턴 수정 또는 카드 retired |
| symbol_changed | (symbolChanges[]) 검토 → 카드 갱신 또는 set-status active 로 updatedAt 갱신 |
| heritage_uncovered | (uncoveredSubclasses[]) 서브클래스 spec 생성 또는 부모 codeLinks 추가 |
| pattern_violation | (patternViolations[]) 코드 수정 또는 패턴 조정 |
| glossary_broken | ed glossary define 또는 --glossary <새 목록> |
patternErrors[] (drift 아님): ast-grep 패턴 문법 오류 → 패턴 수정.
</error_recovery>
<response_shapes>
ed check drift:
{"data":{
"health":{"total":N,"active":N,"drifted":N,"draft":N},
"cards":[{
"key":"...",
"driftType":"...", // 조건부: drift 시 primary
"driftTypes":["...",...],// 조건부: 전체
"brokenLinks":N,"totalLinks":N,
"patternViolations":[{"id":"...","rule":"forbidden|required","matches":N}],
"patternErrors":[{"id":"...","message":"..."}],
"uncoveredSubclasses":[{"file":"...","symbol":"..."}],
"symbolChanges":[...]
}]
}}
ed check impact:
{"data":{
"risk_level":"low|medium|high|critical",
"affected_count":N,
"affected_cards":[{"key":"...","linkType":"direct|boundary|transitive","affectedLinks":N,"linkStatus":{"valid":N,"broken":N}}],
"new_uncovered_files":[...],
"suggested_actions":[...],
"max_fan_in":N // 조건부: > 0
}}
ed validate links:
{"data":{
"declared":N,"resolved":N,"broken":N,"unresolved":N,
"internal_links":N, // 조건부: > 0 (비-export 심볼 링크)
"internal_details":[{"key":"...","file":"...","symbol":"..."}]
}}
ed card list:
{"data":{
"items":[{"key":"...","type":"...","status":"...","summary":"...","parent":"..."|null}],
"total":N,
"page":{"limit":N,"offset":N,"has_more":bool}
}}
ed check coverage <key>:
{"data":{
"key":"...","total_symbols":N,"covered_symbols":N,"coverage_ratio":0~1|null,
"uncovered":[{"file":"...","symbol":"...","kind":"..."}]
}}
ed check coverage --suggest:
{"data":{
"suggestions":[{"key":"...","type":"domain|spec","files":N,"symbols":N,"reason":"...","suggested_glossary":[]}],
"total":N
}}
ed analyze:
{"data":{
"health":{"total":N,"active":N,"drifted":N,"draft":N,"brokenLinks":N,"staleBoundary":N,
"codeStats":{"files":N,"symbols":N}, // 조건부: gildash 활성
"codeCycles":{"count":N,"samples":[["a.ts","b.ts"]]} // 조건부
},
"coverage":{"totalSymbols":N,"covered":N,"ratio": 0~1 | null}, // null = 인덱스 0
"drifted":{"cards":[...],"total":N},
"glossary":{"totalWords":N,"unusedWords":[...],"entries":[...]},
"unlinked_symbols":[{"file":"...","symbol":"...","kind":"..."}]
}}
</response_shapes>
gildash 발견한 모든 sub-project 자동 집계 (모든 gildash 쿼리에 라우팅 적용). `--project-root` 는 모노레포 루트 지정. codeLinks `file` 은 모노레포 루트 기준 상대 경로 (예: `packages/common/...`). 파일/심볼 자동 dedup. 1. 코드 수정 전 카드 읽기. 수정 후 `ed validate links`. 항상. 2. 카드 생성/갱신 전 ``. 예외 없음. 3. single-file 테스트. 4. 4-tier strict. 5. `ed` 직접 호출 — 서브에이전트 사용 시 카드 컨텍스트 손실.