From crucible
dogfood 로그 요약·제안 (한·영) / Manual dogfood-log digest — read-only aggregator that distills crucible dogfood JSONL (local + global mirror) into a 3-section Markdown proposal report covering threshold calibration, skill-protocol improvements, and /compound promotion candidates. Use whenever you want to turn accumulated /crucible:dogfood events into a human-reviewable proposal, not to mutate any skill, memory, plugin.json, or threshold directly. Run it manually — there is no auto trigger. 트리거: "dogfood digest", "도그푸드 다이제스트", "도그푸드 리포트", "dogfood report", "/crucible:dogfood-digest", "로그 집계 제안", "dogfood summary", "피드백 요약".
How this skill is triggered — by the user, by Claude, or both
Slash command
/crucible:dogfood-digestThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> crucible `dogfood` JSONL을 window 플래그로 집계해 **제안 리포트 1건**만 `.claude/plans/` 에 남기는 read-only 스킬. 임계값·SKILL.md·메모리·plugin.json 은 손대지 않는다. 실행 판단은 전적으로 사용자 몫.
crucible
dogfoodJSONL을 window 플래그로 집계해 제안 리포트 1건만.claude/plans/에 남기는 read-only 스킬. 임계값·SKILL.md·메모리·plugin.json 은 손대지 않는다. 실행 판단은 전적으로 사용자 몫.
6-axis activation: this skill emits hint-level signals on axis 1 (Structure — 산출물 경로 규약) and axis 2 (Context — 읽기 소스 나열). HARD-GATE 없음 — 제안 생성 전용이므로
/plan·/verify처럼 축 통과를 강제하지 않는다.using-harness/SKILL.md§5 의 힌트 수준 분류.
/crucible:dogfood-digest, "dogfood digest", "도그푸드 리포트", "로그 집계 제안" 등으로 명시 호출할 때./crucible:dogfood 로그가 일정 수준 누적된 뒤, 관찰된 이벤트를 바탕으로 임계값 재조정 · 스킬 프로토콜 개선 · /compound 승격 후보를 사람이 판단 가능한 제안으로 뽑고 싶을 때.{window} 구간이 달라져 기존 리포트를 덮지 않는다.Do not use when:
dogfood JSONL 에 한정.파일 변경을 제안으로만 남기는 이유는 신뢰다. 임계값과 SKILL.md 본문은 세션 간 영향력이 크고, 자동 적용 시 한 번의 노이즈가 다음 세션 전체를 오염시킨다. 리포트는 사람이 읽고 재-/plan 또는 수동 편집 경로로 들어가는 큐로 동작하고, 스킬 자신은 .claude/plans/ 한 곳에만 쓴다. 이 경계는 프로젝트 가드레일(.claude/rules/project-guardrails.md §4 · §7)과 /compound 의 promotion 게이트(§2)와 같은 원칙을 따른다.
각 Phase는 목표 / 입력 / 동작 / 출력 / 실패 시 fallback 5 섹션 고정.
목표: 사용자 플래그와 기본값을 확정하고 window/scope 레이블을 만든다.
입력: 슬래시 커맨드 인자.
동작:
--last N / --since DATE|Nd / --all / --scope local|global|both.--last 10 · --scope both.--last 와 --since 동시 지정 시 오류 반환 (mutually exclusive). --all 는 둘 다 override.--last N → last{N}--since 2026-04-15 → since-2026-04-15--since 7d → since-7d--all → all출력: 메모리 상 { window_label, scope, cli_args }.
실패 시 fallback: 알 수 없는 플래그는 scripts/dogfood-digest.sh --help 안내 후 exit 2.
목표: 로컬 + 글로벌 mirror JSONL 을 window 에 맞춰 필터하고, 각 이벤트에 back-reference (_source_path, _line) 를 주입한 스트림을 만든다.
입력: Phase 1 {window, scope}.
동작:
bash scripts/dogfood-digest.sh <flags> 를 호출한다.scope 에 따라 다음 소스들을 읽는다 (모두 append-only, 원본 mutate 금지):
${PROJECT_ROOT}/.claude/dogfood/log.jsonl~/.claude/dogfood/crucible/{slug}-{hash}/log.jsonl (여러 프로젝트 가능)jq input_line_number 로 보강해 {_source_path, _line} 를 주입한다.ts 기준 오름차순 정렬 후 window 필터 적용:
--since → ts >= cutoff select--last → tail N--all → no-op출력: filtered JSONL stream on stdout.
실패 시 fallback: 소스 0개 → 빈 stream (exit 0). 파싱 실패 이벤트는 조용히 skip (schema drift 대비).
목표: filtered stream 을 3섹션 Markdown 으로 변환한다. 빈 섹션은 명시적 no signal 문구로 대체해 "섹션 누락"으로 오해되지 않게 한다.
입력: Phase 2 stream + {window, scope}.
동작:
bash scripts/dogfood-digest-render.sh --window {window} --scope {scope}) 가 Phase 2 의 filtered JSONL 을 stdin 으로 읽어 변환한다. 호출형(직결 파이프 vs wrapper-via-tempfile) 은 Phase 3 의 책임이 아니라 Phase 4 가 정의한다 — 둘 다 renderer 입장에서는 동일한 stdin 입력이다..type == "skill_call" && .skill == "/crucible:dogfood-digest" (앵커 regex ^/?crucible:dogfood-digest$, 대소문자 무시) 는 ingestion 단계에서 drop. 자기 호출이 Protocol/Promotion 섹션을 오염시키지 않도록 한다. 앵커가 있어 crucible:dogfood-digest-v2 같은 미래 형제 스킬 호출은 보존된다. .skill 이 string 이 아닌 malformed 행은 self-call 로 단정할 수 없으므로 통과 처리(schema-drift tolerance).--threshold-n N(기본 3, 양의 정수) 로 조정 가능:
qa_judge 중 .score 가 [0,1] 범위의 number 인 행만 카운트한다 (n=numeric-and-in-range). n≥threshold-n 이면 p50/p95 + verdict 분포. 문자열·중첩 객체·범위 밖 score 는 통계 오염 방지를 위해 ingestion 단계에서 drop 되며 total_events 에는 남고 qa_judge n 에서는 빠진다 (issue #12 + 추가 hardening). axis_skip n≥threshold-n 이면 축별 histogram. 둘 다 관측수 미만이면 no signal in window (qa_judge n=X, axis_skip n=Y, threshold-n=N).note 중 category ∈ {pain, ambiguous} 를 text 내 첫 /crucible:* 토큰 기준 그룹핑 (미매치는 general) + axis_skip.reason 동일 키 ≥ 2. 상위 5건만.note 중 category ∈ {request, good} 을 같은 방식으로 그룹핑 + promotion_gate.response == "y" 빈도 ≥ 2.- **{key}** ({cats}, n={count}) — {sample}\n - 근거: \{path}:{line}` …` 형식. 최소 1건의 back-reference 를 반드시 포함.generated_at · window · scope · total_events · source_counts · date 기재.출력: Markdown 문자열 (stdout).
--format json 을 사용하는 경우 stdout 은 단일 JSON 객체다. 최상위 구조는 {schema_version, frontmatter, sections[]} 이고, 섹션 순서는 Threshold Calibration → Protocol Improvements → Promotion Candidates 로 고정된다. 각 section 은 {title, items[]} 이며, note 필드는 items 가 비어 있을 때만 반드시 존재하고, items 가 1건 이상이면 반드시 부재한다 — 이 불변식은 __tests__/integration/test-dogfood-digest.sh ISSUE-19 블록이 강제하고 있다.
schema_version비교 주의:schema_version은 JSON STRING 이다 ("1", 숫자1아님). 반드시.schema_version == "1"(문자열 비교) 로 확인해야 하며,.schema_version == 1(정수 비교) 는 항상false를 반환해 wrapper 가 잘못된 fallback 경로로 흘러간다.
각 item 은 type discriminator 를 들고 있다. 아래는 type 별 보장 필드 목록이다 (이 contract 를 깨는 변경은 schema_version bump 를 요구한다):
| type | 보장 필드 |
|---|---|
qa_distribution | n (int) · p50 (number|null) · p95 (number|null) · verdicts.promote / .retry / .reject (int) · refs (array of "path:line") |
axis_skip_freq | n (int) · histogram (array of {axis, n}) · refs |
pain_group | key (string) · n (int) · cats (string) · sample (string) · refs |
skip_reason | reason (string) · n (int) · refs |
promo_group | key (string) · n (int) · cats (string) · sample (string) · refs |
promotion_gate | n (int) · refs |
refs 는 "<source_path>:<line>" 문자열 배열로 직렬화된다 (최대 3건). 향후 객체 배열([{path,line}]) 로 변경될 경우 schema_version bump 대상이다.
실패 시 fallback: 섹션 휴리스틱이 모든 관측수 하한 미만 → 빈 섹션 대신 명시적 안내. jq 파이프 실패 → stderr 경고 후 섹션을 > no signal in window 로 채워 리포트 완결.
목표: Phase 3 Markdown 을 .claude/plans/{date}-dogfood-digest-{window}.md 경로로 단 1건만 저장. 스킬 자체는 쉘 스크립트 2개 (aggregator · renderer) 로만 구성돼 있고 이들은 stdout 으로 출력만 한다. 파일로 남기는 주체는 호출자(에이전트) 이다 — 호출자가 redirect (> path) 또는 Write 도구로 최종 파일을 남긴다.
입력: Phase 3 Markdown (stdout) + Phase 1 {window}.
호출자(에이전트) 책임:
date = $(date -u +%Y-%m-%d) 계산..claude/plans/${date}-dogfood-digest-${window_label}.md. slug dogfood-digest 는 고정 문자열이라 별도 sanitize 불필요 — {window_label} 만 [a-zA-Z0-9_-] 화이트리스트 내에 있는지 확인..claude/plans/ 디렉토리 부재 시 mkdir -p.{window}-v2 / {window}-v3 … 처럼 suffix 를 바꿔 재호출할 것. 재조회가 필요하면 Phase 1 부터 다시 돈다. (스크립트에 --out / --force flag 는 의도적으로 두지 않음 — 충돌 처리는 호출자 문맥에서 판단.)jq sort / mktemp 등으로 실패해도 renderer 는 EOF 까지 읽고 깨끗한 "no signal in window" 리포트를 exit 0 으로 뱉어 "성공처럼 보이는 잘못된 결과(success but wrong answer)" 실패를 만든다(issue #11). 두 가지 호출형 모두 aggregator 실패가 호출자 exit code 로 surface 되도록 보호장치를 따로 둬야 한다:
mktemp 임시파일로 받고 renderer 에 stdin 으로 주입한다. set -e 또는 aggregator 호출 직후 if ! ... ; then exit 1; fi 명시 rc 체크가 필수 — 둘 중 하나라도 없으면 aggregator 가 exit 2 로 죽어도 renderer 가 빈 입력으로 정상 리포트를 만들어 issue #11 회귀가 된다. 단계별 exit code 를 독립 검사할 수 있는 게 추가 이점.set -o pipefail 을 호출 전에 켠다. aggregator 실패가 전체 exit code 로 전파된다(테스트는 ADV-007 참조). 단, 단계별 디버깅이 어렵다.출력: 디스크 상의 리포트 파일 1건.
실패 시 fallback: 파일 쓰기 실패 → 에러 원문을 사용자에게 노출하고 중단. 부분 쓰기 잔해 제거. 스크립트 자체의 exit code 는 출력 섹션 참조 (0/1/2).
예시 호출 (bash, wrapper-via-tempfile):
set -e # aggregator 실패가 빈 리포트로 가려지지 않도록 (issue #11).
# set -o pipefail 은 이 형태에서 파이프가 없어 무효 — set -e 가 핵심.
win=last10
date=$(date -u +%Y-%m-%d)
mkdir -p .claude/plans
# wrapper-via-tempfile: aggregator → tempfile → renderer.
# 각 단계 exit code 를 독립 검사 가능. 위 `set -e` 가 없으면 aggregator
# 가 exit 2 로 죽어도 다음 줄의 renderer 가 빈 입력으로 정상 리포트를
# 저장한다.
tmp_raw="$(mktemp -t dogfood-digest-raw.XXXXXX)"
trap 'rm -f "$tmp_raw"' EXIT INT TERM HUP
bash scripts/dogfood-digest.sh --last 10 --scope both > "$tmp_raw"
# --threshold-n 은 renderer 에만 — aggregator 에 패스하면 exit 2.
bash scripts/dogfood-digest-render.sh --window "$win" --scope both --threshold-n 5 \
< "$tmp_raw" \
> ".claude/plans/${date}-dogfood-digest-${win}.md"
대체 호출 (direct pipe, ADV-007 검증 형태):
set -o pipefail # 직결 파이프에서 aggregator 실패를 전체 exit code 로 전파.
# --threshold-n 은 파이프 오른쪽(renderer) 에만 둔다.
bash scripts/dogfood-digest.sh --last 10 --scope both \
| bash scripts/dogfood-digest-render.sh --window last10 --scope both --threshold-n 5 \
> ".claude/plans/${date}-dogfood-digest-last10.md"
/crucible:dogfood 가 append 한 JSONL (.claude/dogfood/log.jsonl + opt-in 글로벌 mirror)..claude/plans/YYYY-MM-DD-dogfood-digest-{window}.md (Markdown + YAML frontmatter)./crucible:plan 으로 실제 변경안을 계획하거나 /crucible:compound 로 승격 후보를 통과시킨다.{PROJECT_ROOT}/
├── .claude/
│ ├── dogfood/
│ │ └── log.jsonl # read-only 입력 (dogfood 가 append)
│ └── plans/
│ └── 2026-04-22-dogfood-digest-last10.md # 이 스킬의 유일한 산출물
~/.claude/dogfood/crucible/
├── {slug}-{hash}/
│ └── log.jsonl # opt-in 글로벌 mirror 입력
파일명 예시:
2026-04-22-dogfood-digest-last10.md (기본값)2026-04-22-dogfood-digest-since-2026-04-15.md2026-04-22-dogfood-digest-since-7d.md2026-04-22-dogfood-digest-all.md/crucible:dogfood-digest --since 7d --scope both
# → .claude/plans/2026-04-22-dogfood-digest-since-7d.md 생성
리포트 본문 발췌 (pain note 5건·request 2건 관측):
## Threshold Calibration
> no signal in window (qa_judge n=2, axis_skip n=0, threshold-n=3)
## Protocol Improvements
- **general** (pain, n=5) — 영어 추상어 혼동으로 재설명 루프 2회 …
- 근거: `~/.claude/dogfood/crucible/windly-10fbfe8c/log.jsonl:1` …
## Promotion Candidates
- **general** (request, n=2) — 한국어 풀어쓰기 기본화 — bilingual UX 확장
- 근거: `~/.claude/dogfood/crucible/windly-10fbfe8c/log.jsonl:5` …
.claude/memory/ 수정은 사용자 intent 를 거친 별도 경로를 따라야 한다._source_path, _line)에 한정./crucible:* 토큰 + general 버킷에 한정. 더 정교한 NLP 추출은 향후 버전 범위 밖.--all --scope both 에서 글로벌 미러 로그가 기가바이트급이면 jq 스트리밍 비용이 커진다. 구체적 벤치는 본 버전 범위 밖.Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
npx claudepluginhub tothefullest08/crucible --plugin crucible