Skip to content
This repository was archived by the owner on Apr 14, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .dal/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.dal/decisions.md merge=union
.dal/decisions-archive.md merge=union
.dal/*/history.md merge=union
.dal/wisdom.md merge=union
38 changes: 38 additions & 0 deletions .dal/template/dal.spec.cue
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// dal.spec.cue — localdal schema

#Player: "claude" | "codex" | "gemini"
#Role: "leader" | "member" | "ops"

#BranchConfig: {
base?: string | *"main"
}

#SetupConfig: {
packages?: [...string]
commands?: [...string]
timeout?: string | *"5m"
}

#DalProfile: {
uuid!: string & != ""
name!: string & != ""
version!: string
player!: #Player
fallback_player?: #Player
role!: #Role
channel_only?: bool
skills?: [...string]
hooks?: [...string]
model?: string
player_version?: string
auto_task?: string
auto_interval?: string
workspace?: string
branch?: #BranchConfig
setup?: #SetupConfig
git?: {
user?: string
email?: string
github_token?: string
}
}
25 changes: 25 additions & 0 deletions .dal/template/dal/charter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# dal — 문서 관리자

## Role
팀 공유 기억의 유일한 writer + committer. 백그라운드 자동 실행.

## Responsibilities
1. decisions/inbox/ → decisions.md 병합 (중복 제거: By + What 기준)
2. wisdom-inbox/ → wisdom.md 병합
3. history-buffer/{name}.md → .dal/{name}/history.md 병합
4. history.md 12KB 초과 시 Core Context 압축
5. decisions.md 50KB 초과 시 30일+ 항목 → decisions-archive.md
6. README.md / CLAUDE.md 갱신 (ccw tool update_module_claude)
7. 변경 시 git add + commit + push

## Tools
- ccw tool update_module_claude — 모듈 문서 자동 생성
- ccw tool detect_changed_modules — 변경 모듈 탐지
- ccw memory — 컨텍스트 메모리 관리
- dalcli status / report

## Rules
- push 실패 시 재시도만. force push, reset 금지.
- 병합 후 inbox 파일 삭제.
- history에는 최종 결과만. 중간 상태 금지.
- 코드, 리뷰, 테스트 금지 — 문서만 담당.
15 changes: 15 additions & 0 deletions .dal/template/dal/dal.cue
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
uuid: "99ab0934-07fb-423f-84e6-1ce8aef91919"
name: "dal"
version: "1.0.0"
player: "claude"
model: "haiku"
role: "member"
skills: ["skills/inbox-protocol", "skills/history-hygiene"]
hooks: []
auto_task: "1. /workspace/decisions/inbox/ → decisions.md 병합 (중복 제거 후 삭제). 2. /workspace/history-buffer/ → .dal/{name}/history.md 병합. 3. /workspace/wisdom-inbox/ → wisdom.md 병합. 4. history.md 12KB 초과 시 압축. 5. decisions.md 50KB 초과 시 30일+ 아카이브. 6. README.md, CLAUDE.md 갱신 필요 시 ccw tool update_module_claude로 자동 생성. 7. 변경 시 git add + commit + push."
auto_interval: "30m"
git: {
user: "dal-docs"
email: "dal-docs@dalcenter.local"
github_token: "env:GITHUB_TOKEN"
}
28 changes: 28 additions & 0 deletions .dal/template/dalops/charter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# dalops — 운영자

## Role
CCW 기반 오케스트레이터. 코드 구현, 리뷰, 테스트를 워크플로우로 실행한다.

## Tools
- ccw cli --tool codex --mode review — Codex 코드 리뷰
- ccw cli --tool codex --mode analysis — Codex 분석
- ccw cli --tool gemini — Gemini 분석
- dalcli status / ps / report

## Workflows
- workflow-lite-plan — 단일 모듈 기능 구현
- workflow-tdd-plan — 테스트 주도 개발
- workflow-multi-cli-plan — 멀티 CLI 협업 분석/리뷰
- workflow-test-fix — 테스트 생성 및 수정 루프

## Process
1. 이슈/작업 수신
2. CCW 워크플로우 선택 및 실행
3. codex 리뷰 통과 확인
5. 브랜치 → PR 생성
6. dalcli report로 결과 보고

## Rules
- main 직접 커밋 금지
- PR 생성 전 반드시 테스트 통과
- ccw session으로 작업 컨텍스트 유지
13 changes: 13 additions & 0 deletions .dal/template/dalops/dal.cue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
uuid: "c9380496-8203-44e4-9025-6e624e95cb67"
name: "dalops"
version: "1.0.0"
player: "claude"
role: "ops"
channel_only: true
skills: ["skills/git-workflow", "skills/pre-flight"]
hooks: []
git: {
user: "dal-ops"
email: "dal-ops@dalcenter.local"
github_token: "env:GITHUB_TOKEN"
}
3 changes: 3 additions & 0 deletions .dal/template/decisions-archive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Decisions Archive

아카이브된 결정. 읽기 전용 참조.
13 changes: 13 additions & 0 deletions .dal/template/decisions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Decisions

팀 아키텍처 결정 로그. 모든 dal은 작업 전에 이 파일을 읽는다.
scribe dal이 inbox에서 승인된 제안을 병합한다. 직접 수정 금지.

## 포맷

### {날짜}: {주제}
**By:** {dal name}
**What:** {결정 내용}
**Why:** {이유}

---
3 changes: 3 additions & 0 deletions .dal/template/skills/escalation/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Escalation

report: 완료 보고. claim: 진행 불가 에스컬레이션.
3 changes: 3 additions & 0 deletions .dal/template/skills/git-workflow/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Git Workflow

main 직접 커밋 금지. 브랜치 → PR → 리뷰 → 머지.
3 changes: 3 additions & 0 deletions .dal/template/skills/history-hygiene/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# History Hygiene

최종 결과만 기록. 중간 시도 금지. 12KB 제한.
3 changes: 3 additions & 0 deletions .dal/template/skills/inbox-protocol/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Inbox Protocol

decisions.md, wisdom.md 직접 수정 금지. inbox에 드롭.
4 changes: 4 additions & 0 deletions .dal/template/skills/leader-protocol/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Leader Protocol

나는 중개자. 직접 수정 안 함. 소환+읽기+판단+라우팅만.
Write/Edit/commit 금지. dalcli-leader assign으로 멤버에게 위임.
3 changes: 3 additions & 0 deletions .dal/template/skills/pre-flight/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Pre-Flight

작업 전 필수: now.md → decisions.md → wisdom.md → ps.
3 changes: 3 additions & 0 deletions .dal/template/skills/reviewer-protocol/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Reviewer Protocol

작성자 ≠ 리뷰어. 리뷰어 본인 수정 금지.
11 changes: 11 additions & 0 deletions .dal/template/wisdom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Wisdom

팀 공유 교훈. 모든 dal은 작업 전에 이 파일을 읽는다.

## Patterns

검증된 접근 방식.

## Anti-Patterns

피해야 할 것.
5 changes: 4 additions & 1 deletion cmd/dalcli/cmd_history.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import (
// appendHistoryBuffer writes a session record to history-buffer.
// Scribe dal will later merge this into .dal/{name}/history.md.
func appendHistoryBuffer(dalName, task, result, status string) {
bufferDir := "/workspace/history-buffer"
bufferDir := os.Getenv("DALCLI_HISTORY_BUFFER")
if bufferDir == "" {
bufferDir = "/workspace/history-buffer"
}
if _, err := os.Stat(bufferDir); err != nil {
return // history-buffer not mounted, skip silently
}
Expand Down
8 changes: 2 additions & 6 deletions cmd/dalcli/cmd_history_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,8 @@ import (
)

func TestAppendHistoryBuffer_DirectCall(t *testing.T) {
if _, err := os.Stat("/workspace"); err != nil {
t.Skip("not in container environment")
}
bufDir := "/workspace/history-buffer"
os.MkdirAll(bufDir, 0755)
defer os.RemoveAll(bufDir)
bufDir := t.TempDir()
t.Setenv("DALCLI_HISTORY_BUFFER", bufDir)

appendHistoryBuffer("test-dal", "implement feature", "done", "완료")

Expand Down
5 changes: 4 additions & 1 deletion cmd/dalcli/cmd_propose.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ func proposeCmd(dalName string) *cobra.Command {
}

func proposeDecision(dalName, title, body string) error {
inboxDir := "/workspace/decisions/inbox"
inboxDir := os.Getenv("DALCLI_DECISIONS_INBOX")
if inboxDir == "" {
inboxDir = "/workspace/decisions/inbox"
}
if err := os.MkdirAll(inboxDir, 0755); err != nil {
return fmt.Errorf("inbox not available: %w", err)
}
Expand Down
11 changes: 2 additions & 9 deletions cmd/dalcli/cmd_propose_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,8 @@ import (
)

func TestProposeDecision_DirectCall(t *testing.T) {
// proposeDecision writes to /workspace/decisions/inbox
// We can't easily redirect, but we can test it if /workspace exists
// Skip if /workspace doesn't exist (not in container)
inboxDir := "/workspace/decisions/inbox"
if _, err := os.Stat("/workspace"); err != nil {
t.Skip("not in container environment")
}
os.MkdirAll(inboxDir, 0755)
defer os.RemoveAll(inboxDir)
inboxDir := t.TempDir()
t.Setenv("DALCLI_DECISIONS_INBOX", inboxDir)

err := proposeDecision("test-dal", "test title", "test body")
if err != nil {
Expand Down
10 changes: 9 additions & 1 deletion cmd/dalcli/cmd_wisdom.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,17 @@ func wisdomCmd(dalName string) *cobra.Command {
return cmd
}

// wisdomInboxDir returns the inbox directory, allowing override via environment variable.
func wisdomInboxDir() string {
if d := os.Getenv("DALCLI_WISDOM_INBOX"); d != "" {
return d
}
return "/workspace/wisdom-inbox"
}

// proposeWisdom writes a wisdom proposal to wisdom-inbox.
func proposeWisdom(dalName, pattern, context string, isAntiPattern bool) error {
inboxDir := "/workspace/wisdom-inbox"
inboxDir := wisdomInboxDir()
if err := os.MkdirAll(inboxDir, 0755); err != nil {
return fmt.Errorf("wisdom inbox not available: %w", err)
}
Expand Down
16 changes: 4 additions & 12 deletions cmd/dalcli/cmd_wisdom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,8 @@ import (
)

func TestProposeWisdom_DirectCall_Pattern(t *testing.T) {
if _, err := os.Stat("/workspace"); err != nil {
t.Skip("not in container environment")
}
inboxDir := "/workspace/wisdom-inbox"
os.MkdirAll(inboxDir, 0755)
defer os.RemoveAll(inboxDir)
inboxDir := t.TempDir()
t.Setenv("DALCLI_WISDOM_INBOX", inboxDir)

err := proposeWisdom("test-dal", "always test first", "prevents regressions", false)
if err != nil {
Expand All @@ -33,12 +29,8 @@ func TestProposeWisdom_DirectCall_Pattern(t *testing.T) {
}

func TestProposeWisdom_DirectCall_AntiPattern(t *testing.T) {
if _, err := os.Stat("/workspace"); err != nil {
t.Skip("not in container environment")
}
inboxDir := "/workspace/wisdom-inbox"
os.MkdirAll(inboxDir, 0755)
defer os.RemoveAll(inboxDir)
inboxDir := t.TempDir()
t.Setenv("DALCLI_WISDOM_INBOX", inboxDir)

err := proposeWisdom("test-dal", "force push", "destroys history", true)
if err != nil {
Expand Down
Loading