@su-record/vibe 2.10.0 → 2.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +10 -7
- package/README.en.md +2 -3
- package/README.md +2 -3
- package/dist/cli/auth.d.ts +0 -1
- package/dist/cli/auth.d.ts.map +1 -1
- package/dist/cli/auth.js +1 -18
- package/dist/cli/auth.js.map +1 -1
- package/dist/cli/collaborator.d.ts +3 -3
- package/dist/cli/collaborator.js +4 -4
- package/dist/cli/collaborator.js.map +1 -1
- package/dist/cli/commands/info.d.ts.map +1 -1
- package/dist/cli/commands/info.js +0 -1
- package/dist/cli/commands/info.js.map +1 -1
- package/dist/cli/commands/init.d.ts +3 -4
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +15 -20
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/remove.d.ts.map +1 -1
- package/dist/cli/commands/remove.js +2 -7
- package/dist/cli/commands/remove.js.map +1 -1
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +10 -10
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/index.js +1 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/postinstall/main.d.ts.map +1 -1
- package/dist/cli/postinstall/main.js +7 -14
- package/dist/cli/postinstall/main.js.map +1 -1
- package/dist/cli/setup/LegacyMigration.d.ts +3 -3
- package/dist/cli/setup/LegacyMigration.d.ts.map +1 -1
- package/dist/cli/setup/LegacyMigration.js +3 -5
- package/dist/cli/setup/LegacyMigration.js.map +1 -1
- package/dist/cli/setup/ProjectSetup.d.ts +18 -8
- package/dist/cli/setup/ProjectSetup.d.ts.map +1 -1
- package/dist/cli/setup/ProjectSetup.js +70 -19
- package/dist/cli/setup/ProjectSetup.js.map +1 -1
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +1 -1
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/utils/cli-detector.d.ts +0 -7
- package/dist/cli/utils/cli-detector.d.ts.map +1 -1
- package/dist/cli/utils/cli-detector.js +0 -95
- package/dist/cli/utils/cli-detector.js.map +1 -1
- package/dist/cli/utils.d.ts +1 -1
- package/dist/cli/utils.d.ts.map +1 -1
- package/dist/cli/utils.js +1 -2
- package/dist/cli/utils.js.map +1 -1
- package/dist/infra/lib/memory/MemoryStorage.d.ts +1 -1
- package/dist/infra/lib/memory/MemoryStorage.d.ts.map +1 -1
- package/dist/infra/lib/memory/MemoryStorage.js +2 -3
- package/dist/infra/lib/memory/MemoryStorage.js.map +1 -1
- package/hooks/scripts/__tests__/pre-tool-guard.test.js +1 -1
- package/hooks/scripts/codex-notify.js +49 -0
- package/hooks/scripts/command-log.js +1 -1
- package/hooks/scripts/lib/dispatcher.js +2 -3
- package/hooks/scripts/lib/scope-from-spec.js +2 -4
- package/hooks/scripts/llm-orchestrate.js +2 -7
- package/hooks/scripts/prompt-dispatcher.js +3 -3
- package/hooks/scripts/utils.js +5 -10
- package/package.json +1 -1
- package/skills/docs/SKILL.md +3 -3
- package/skills/test/SKILL.md +8 -8
- package/skills/vibe/SKILL.md +24 -2
- package/skills/vibe.run/SKILL.md +2 -0
- package/skills/vibe.test/SKILL.md +4 -4
- package/vibe/rules/principles/dual-harness-doctrine.md +50 -0
|
@@ -112,7 +112,6 @@ function resolveModel(providerName, config) {
|
|
|
112
112
|
*
|
|
113
113
|
* true인 경우:
|
|
114
114
|
* - vibe-codex: ANTHROPIC_BASE_URL이 localhost (프록시 모드)
|
|
115
|
-
* - coco: ~/.coco/ 존재 또는 COCO_HOME 설정
|
|
116
115
|
* - 명시적: VIBE_SECONDARY_LLM=claude
|
|
117
116
|
*/
|
|
118
117
|
function useClaudeAsSecondary() {
|
|
@@ -121,10 +120,6 @@ function useClaudeAsSecondary() {
|
|
|
121
120
|
// 2. vibe-codex 프록시 모드
|
|
122
121
|
const baseUrl = process.env.ANTHROPIC_BASE_URL || '';
|
|
123
122
|
if (baseUrl.includes('localhost') || baseUrl.includes('127.0.0.1')) return true;
|
|
124
|
-
// 3. coco 환경
|
|
125
|
-
if (process.env.COCO_HOME) return true;
|
|
126
|
-
const cocoDir = path.join(os.homedir(), '.coco');
|
|
127
|
-
if (fs.existsSync(cocoDir)) return true;
|
|
128
123
|
return false;
|
|
129
124
|
}
|
|
130
125
|
|
|
@@ -601,10 +596,10 @@ async function main() {
|
|
|
601
596
|
// 명시적 claude 호출
|
|
602
597
|
providerChain = ['claude', 'gemini'];
|
|
603
598
|
} else if (isGpt) {
|
|
604
|
-
// GPT 주관 → claude fallback (vibe-codex
|
|
599
|
+
// GPT 주관 → claude fallback (vibe-codex), gemini fallback (직접 모드)
|
|
605
600
|
providerChain = claudeSecondary ? [provider, 'claude'] : [provider, 'gemini'];
|
|
606
601
|
} else {
|
|
607
|
-
// gemini 주관 → claude fallback (vibe-codex
|
|
602
|
+
// gemini 주관 → claude fallback (vibe-codex), gpt fallback (직접 모드)
|
|
608
603
|
providerChain = claudeSecondary ? ['gemini', 'claude'] : ['gemini', 'gpt'];
|
|
609
604
|
}
|
|
610
605
|
|
|
@@ -42,11 +42,11 @@ try {
|
|
|
42
42
|
|
|
43
43
|
if (!prompt) process.exit(0);
|
|
44
44
|
|
|
45
|
-
// 레거시 SSOT 통합 — `/vibe.*` 진입 시 `.claude/vibe
|
|
45
|
+
// 레거시 SSOT 통합 — `/vibe.*` 진입 시 `.claude/vibe/` → `.vibe/` 자동 이동.
|
|
46
46
|
// `vibe init`/`update` 와 동일한 `consolidateLegacyVibe` (dist/cli/setup/LegacyMigration.js) 를 직접 재사용. Idempotent.
|
|
47
47
|
if (/^\s*\/vibe\b/i.test(prompt)) {
|
|
48
48
|
try {
|
|
49
|
-
const projectDir = process.env.CLAUDE_PROJECT_DIR || process.
|
|
49
|
+
const projectDir = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
50
50
|
const utils = await import('./utils.js');
|
|
51
51
|
const CLI_BASE = utils.getCliBaseUrl();
|
|
52
52
|
const { consolidateLegacyVibe } = await import(`${CLI_BASE}setup/LegacyMigration.js`);
|
|
@@ -183,7 +183,7 @@ if (!matched) {
|
|
|
183
183
|
setImmediate(async () => {
|
|
184
184
|
try {
|
|
185
185
|
const utils = await import('./utils.js');
|
|
186
|
-
const projectDir = process.env.CLAUDE_PROJECT_DIR ||
|
|
186
|
+
const projectDir = process.env.CLAUDE_PROJECT_DIR || '.';
|
|
187
187
|
const configPath = utils.projectVibePath(projectDir, 'config.json');
|
|
188
188
|
let gapEnabled = true;
|
|
189
189
|
try {
|
package/hooks/scripts/utils.js
CHANGED
|
@@ -17,7 +17,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
17
17
|
const DETECTED_VIBE_PATH = path.resolve(__dirname, '..', '..');
|
|
18
18
|
|
|
19
19
|
export const VIBE_PATH = process.env.VIBE_PATH || DETECTED_VIBE_PATH;
|
|
20
|
-
export const PROJECT_DIR = process.env.CLAUDE_PROJECT_DIR ||
|
|
20
|
+
export const PROJECT_DIR = process.env.CLAUDE_PROJECT_DIR || '.';
|
|
21
21
|
|
|
22
22
|
// ~/.vibe/ 디렉토리 경로
|
|
23
23
|
const VIBE_HOME_DIR = path.join(os.homedir(), '.vibe');
|
|
@@ -25,16 +25,14 @@ const VIBE_HOME_DIR = path.join(os.homedir(), '.vibe');
|
|
|
25
25
|
/**
|
|
26
26
|
* 프로젝트 내 Vibe 에셋 루트 해석.
|
|
27
27
|
*
|
|
28
|
-
* 신규 SSOT: `<project>/.vibe/` — CLI(Claude/
|
|
28
|
+
* 신규 SSOT: `<project>/.vibe/` — CLI(Claude/Codex)와 무관한 공용 디렉토리.
|
|
29
29
|
* Legacy fallback:
|
|
30
30
|
* - `<project>/.claude/vibe/` (Claude Code 프로젝트 초기화 흔적)
|
|
31
|
-
* - `<project>/.coco/vibe/` (coco 프로젝트 초기화 흔적)
|
|
32
31
|
*
|
|
33
32
|
* 해석 규칙 — **읽기**(lookup) 시:
|
|
34
33
|
* 1) `.vibe/` 가 존재하면 그 경로
|
|
35
34
|
* 2) `.claude/vibe/` 가 존재하면 그 경로
|
|
36
|
-
* 3) `.
|
|
37
|
-
* 4) 아무것도 없으면 기본값 `.vibe/` (생성 대상)
|
|
35
|
+
* 3) 아무것도 없으면 기본값 `.vibe/` (생성 대상)
|
|
38
36
|
*
|
|
39
37
|
* **쓰기**(write) 시에는 항상 새 SSOT 인 `.vibe/` 로 수렴시키는 것이 원칙이지만,
|
|
40
38
|
* 기존 프로젝트의 legacy 파일이 있으면 해당 위치에 쓰는 것이 덜 파괴적이다.
|
|
@@ -48,8 +46,6 @@ export function projectVibeRoot(projectDir = PROJECT_DIR) {
|
|
|
48
46
|
if (fs.existsSync(vibeRoot)) return vibeRoot;
|
|
49
47
|
const claudeVibe = path.join(projectDir, '.claude', 'vibe');
|
|
50
48
|
if (fs.existsSync(claudeVibe)) return claudeVibe;
|
|
51
|
-
const cocoVibe = path.join(projectDir, '.coco', 'vibe');
|
|
52
|
-
if (fs.existsSync(cocoVibe)) return cocoVibe;
|
|
53
49
|
} catch { /* ignore */ }
|
|
54
50
|
return path.join(projectDir, '.vibe');
|
|
55
51
|
}
|
|
@@ -66,14 +62,13 @@ export function projectVibePath(projectDir = PROJECT_DIR, ...sub) {
|
|
|
66
62
|
|
|
67
63
|
/**
|
|
68
64
|
* 프로젝트 메모리 DB 디렉토리 해석.
|
|
69
|
-
* `.vibe/memories/` (신규) → `.claude/memories/` (legacy Claude) →
|
|
65
|
+
* `.vibe/memories/` (신규) → `.claude/memories/` (legacy Claude) → 기본 `.vibe/memories/`
|
|
70
66
|
*/
|
|
71
67
|
export function projectMemoryDir(projectDir = PROJECT_DIR) {
|
|
72
68
|
try {
|
|
73
69
|
const candidates = [
|
|
74
70
|
path.join(projectDir, '.vibe', 'memories'),
|
|
75
71
|
path.join(projectDir, '.claude', 'memories'),
|
|
76
|
-
path.join(projectDir, '.coco', 'memories'),
|
|
77
72
|
];
|
|
78
73
|
for (const c of candidates) if (fs.existsSync(c)) return c;
|
|
79
74
|
} catch { /* ignore */ }
|
|
@@ -95,7 +90,7 @@ export function readVibeConfig() {
|
|
|
95
90
|
}
|
|
96
91
|
|
|
97
92
|
/**
|
|
98
|
-
* 프로젝트 설정(.vibe/config.json) 읽기 — legacy `.claude/vibe
|
|
93
|
+
* 프로젝트 설정(.vibe/config.json) 읽기 — legacy `.claude/vibe/` fallback 포함
|
|
99
94
|
* @returns {object} 파싱된 config 또는 빈 객체
|
|
100
95
|
*/
|
|
101
96
|
export function readProjectConfig() {
|
package/package.json
CHANGED
package/skills/docs/SKILL.md
CHANGED
|
@@ -106,9 +106,9 @@ graph TD
|
|
|
106
106
|
| CLI | File | Support |
|
|
107
107
|
|---|---|---|
|
|
108
108
|
| Claude Code | `CLAUDE.md` | 100% (Primary) |
|
|
109
|
-
|
|
|
109
|
+
| Codex | `AGENTS.md` | 100% (Primary) |
|
|
110
110
|
|
|
111
|
-
Gemini CLI /
|
|
111
|
+
Gemini CLI / Cursor are not supported — do not generate or check `GEMINI.md`.
|
|
112
112
|
|
|
113
113
|
**Source of truth:**
|
|
114
114
|
- **`CLAUDE.md` is the content SSOT.** Always edit it first; `AGENTS.md` is a regenerated derivative.
|
|
@@ -120,7 +120,7 @@ Gemini CLI / Codex CLI / Cursor are not supported — do not generate or check `
|
|
|
120
120
|
2. **For `AGENTS.md`**:
|
|
121
121
|
- **If missing** → create by cloning `CLAUDE.md` + applying CLI substitution (below).
|
|
122
122
|
- **If exists** → regenerate from current `CLAUDE.md` + substitution, preserving user-specific additions outside the VIBE block.
|
|
123
|
-
3. **CLI substitution for `AGENTS.md`** (
|
|
123
|
+
3. **CLI substitution for `AGENTS.md`** (Codex): `Claude Code` → `Codex` · `~/.claude/` → `~/.codex/` · `.claude/` → `.codex/` · `CLAUDE.md` → `AGENTS.md`. `CLAUDE.md` itself gets no substitution.
|
|
124
124
|
4. **Validate every touched file (whether newly created or modified)** via the `claude-md-guide` → `agents-md` skill chain — see validation block below. **Never write or save without running this step.**
|
|
125
125
|
5. Report per file: created / updated / skipped / validation warnings.
|
|
126
126
|
|
package/skills/test/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: test
|
|
3
|
-
description: vibe 자가검진 본체 — 대상 harness(~/.claude/~/.
|
|
3
|
+
description: vibe 자가검진 본체 — 대상 harness(~/.claude/~/.codex)의 모든 command/skill/hook/agent 프로빙 → pass/fail 리포트 → ~/.vibe/test-reports/.
|
|
4
4
|
when_to_use: /vibe.test 진입점에서 체인 호출. 직접 호출 금지.
|
|
5
5
|
user-invocable: false
|
|
6
6
|
tier: core
|
|
@@ -12,7 +12,7 @@ Probe every shipped vibe surface in one install dir and emit a pass/fail report.
|
|
|
12
12
|
|
|
13
13
|
## Why this exists
|
|
14
14
|
|
|
15
|
-
When vibe ships new commands, skills, hooks, or agents, one side (CC or
|
|
15
|
+
When vibe ships new commands, skills, hooks, or agents, one side (CC or Codex) can end up out of sync with the other, frontmatter can drift, and hook tests can silently break. `/vibe.test` is the single mechanical check: does every surface in the target install actually load and pass its own tests?
|
|
16
16
|
|
|
17
17
|
## Target harness
|
|
18
18
|
|
|
@@ -20,15 +20,15 @@ The argument selects which install dir to probe:
|
|
|
20
20
|
|
|
21
21
|
| Arg | Probed dir |
|
|
22
22
|
|---|---|
|
|
23
|
-
| (empty) | current harness — CC: `~/.claude/`,
|
|
23
|
+
| (empty) | current harness — CC: `~/.claude/`, Codex: `~/.codex/` |
|
|
24
24
|
| `cc` | `~/.claude/` |
|
|
25
|
-
| `
|
|
25
|
+
| `codex` | `~/.codex/` |
|
|
26
26
|
|
|
27
27
|
If the target dir does not exist, print a clear message and exit with guidance (not an error). Example:
|
|
28
28
|
|
|
29
29
|
```
|
|
30
|
-
~/.
|
|
31
|
-
To install:
|
|
30
|
+
~/.codex/ not found — Codex isn't installed on this machine.
|
|
31
|
+
To install: npm i -g @openai/codex
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
## Probes
|
|
@@ -118,8 +118,8 @@ If `failed` is empty, replace the Failures section with `_All probes passed._`.
|
|
|
118
118
|
|
|
119
119
|
## Steps
|
|
120
120
|
|
|
121
|
-
1. **Resolve target**: argument (`cc` / `
|
|
122
|
-
2. **Resolve install dir**: `cc` → `~/.claude`, `
|
|
121
|
+
1. **Resolve target**: argument (`cc` / `codex` / empty). Empty → detect current harness (`$CLAUDE_PROJECT_DIR` set → `cc`; else fall back to `cc`).
|
|
122
|
+
2. **Resolve install dir**: `cc` → `~/.claude`, `codex` → `~/.codex`. If missing → print guidance + exit.
|
|
123
123
|
3. **Read `vibe_version`** from `package.json` in the current repo.
|
|
124
124
|
4. **Walk each category**, run its check, append `{ name, status, error? }` to `probes.<category>`.
|
|
125
125
|
5. **Compute** `summary` counts and the flat `failed[]` list.
|
package/skills/vibe/SKILL.md
CHANGED
|
@@ -26,6 +26,8 @@ user-invocable: true
|
|
|
26
26
|
|
|
27
27
|
- **단일 슬래시 진입점**: `/vibe` 하나로 모든 워크플로 시작. 다른 `/vibe.*` 도 그대로 존재하지만 power user 가 명시적으로 phase 호출하고 싶을 때 쓰는 advanced 경로.
|
|
28
28
|
- **동적 파이프라인**: 의도/입력 종류에 따라 매번 다른 스킬 체인 구성. 미리 정해진 고정 흐름 아님.
|
|
29
|
+
- **무제한 라우팅**: 라우팅 표는 빠른 경로일 뿐 닫힌 화이트리스트가 아니다. 설치된 모든 `vibe.*` 스킬이 라우팅 후보이며, 표에 없는 요구사항도 description 기반 의미 매칭으로 처리한다 (Catch-all).
|
|
30
|
+
- **하네스 정규화 (추론 앞단)**: vibe는 CC(추론)·Codex(직역) 어느 하네스의 암묵적 동작에도 의존하지 않는다. `/vibe`가 모호한 NL을 **명시적·직역 가능한 지시로 먼저 전개**하고, 하위 skill은 모호한 입력을 받지 않는다. 이로써 모든 하네스에서 동일 결과 + CC급 편의를 제공한다. 전문: `vibe/rules/principles/dual-harness-doctrine.md`.
|
|
29
31
|
- **Smart Resume**: `.vibe/{interviews,plans,specs,features}/` 감지하여 "이어서 진행?" 자동 제안.
|
|
30
32
|
- **1회 승인 게이트**: 파이프라인을 설계해서 사용자에게 보여주고 OK 받은 뒤 실행. `ultrawork` 키워드 있으면 skip.
|
|
31
33
|
- **위임자 역할**: `/vibe` 본인은 코드를 직접 쓰지 않는다. 라우팅·설계·실행 위임만 한다.
|
|
@@ -61,12 +63,26 @@ user-invocable: true
|
|
|
61
63
|
| **scaffold** | "프로젝트 만들기", "셋업", "초기 구조" | scaffold |
|
|
62
64
|
| **docs sync** | "문서 갱신", "README", "AGENTS.md" | docs |
|
|
63
65
|
| **analyze** | "분석", "조사", "이건 뭐야" + 파일/URL | analyze |
|
|
66
|
+
| **reason** | "추론", "깊게 생각", "트레이드오프", "어떻게 접근" 등 복잡한 사고 요청 | reason |
|
|
67
|
+
| **event** | "이벤트", "커뮤니티", "D-Day", "행사 자동화" | event |
|
|
64
68
|
| **harness check** | "하네스", "환경 점검" | harness |
|
|
65
|
-
| **test self** | "vibe 테스트", "CC ↔
|
|
69
|
+
| **test self** | "vibe 테스트", "CC ↔ Codex 비교" | test |
|
|
66
70
|
| **utils** | "이어서", "메모리", "체크포인트" | utils |
|
|
67
71
|
|
|
68
72
|
복수 의도면 우선순위: resume > figma-driven > new feature > 기타.
|
|
69
73
|
|
|
74
|
+
> **⚠️ 위 표는 닫힌 화이트리스트가 아니라 "흔한 케이스 빠른 경로"다.** 표에 없는 요구사항이라도 막지 말고 **Catch-all 라우팅**(아래)으로 처리한다.
|
|
75
|
+
|
|
76
|
+
### Catch-all 라우팅 (표에 없는 의도)
|
|
77
|
+
|
|
78
|
+
입력이 위 표 어느 행과도 명확히 매칭되지 않으면:
|
|
79
|
+
|
|
80
|
+
1. **의미 매칭**: 사용 가능한 모든 `vibe.*` 스킬의 `description` 을 읽어 요구사항과 의미적으로 가장 가까운 스킬을 고른다. (표는 참고용일 뿐, 실제 라우팅 후보는 설치된 전체 `vibe.*`)
|
|
81
|
+
2. **복합 설계**: 단일 스킬로 안 되면 여러 스킬을 조합한 파이프라인을 동적으로 설계한다.
|
|
82
|
+
3. **되묻기는 최후**: 어떤 스킬과도 매칭이 안 될 때만 사용자에게 "어떤 작업인지" 명확화 질문을 한다.
|
|
83
|
+
|
|
84
|
+
> 새 `vibe.*` 스킬이 추가되어 위 표에 행이 없더라도, Catch-all 이 description 기반으로 자동 라우팅하므로 기능이 막히지 않는다. 표 누락 = 기능 제한이 되어선 안 된다.
|
|
85
|
+
|
|
70
86
|
### Phase 2: Smart Resume 감지
|
|
71
87
|
|
|
72
88
|
```
|
|
@@ -91,7 +107,13 @@ user-invocable: true
|
|
|
91
107
|
|
|
92
108
|
### Phase 3: 파이프라인 설계
|
|
93
109
|
|
|
94
|
-
|
|
110
|
+
**먼저 입력을 정규화한다 (하네스 무관 명시화):**
|
|
111
|
+
|
|
112
|
+
- **예시·placeholder 표기**: 사용자가 설명용으로 던진 예시 텍스트를 실데이터로 넘기지 않는다. `<예시>`, `[채워넣을 값]` 로 명시. (직역 하네스가 그대로 데이터로 쓰는 것 방지)
|
|
113
|
+
- **research 명시**: 조사가 필요하면 파이프라인에 명시적 탐색 단계를 넣는다. planning mode 같은 하네스 스위치에 의존하지 않는다.
|
|
114
|
+
- **도메인 지식 흡수**: 사용자가 준 라이브러리·함수·파일 위치를 SPEC 입력으로 전달한다.
|
|
115
|
+
|
|
116
|
+
이어서 분류된 의도 + resume 상태 + magic keyword 를 종합해 실행 계획 작성:
|
|
95
117
|
|
|
96
118
|
```
|
|
97
119
|
📋 Pipeline Plan
|
package/skills/vibe.run/SKILL.md
CHANGED
|
@@ -124,6 +124,8 @@ Scenario 3 → Implement → Verify ❌ → Fix → ✅
|
|
|
124
124
|
All pass = Quality guaranteed
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
+
> **하네스-안전 증분 (Dual-Harness Doctrine)**: 시나리오는 **가장 작은 검증 단위**다. 한 시나리오 구현 → 즉시 검증 → 다음. 여러 시나리오를 묶어 빅뱅으로 구현하지 않는다 — Codex(직역) 에서 성공률이 급락하고 CC 에서도 디버깅 비용만 늘린다. `ultrawork` 모드라도 이 단위는 무너뜨리지 않는다 (병렬은 시나리오 간, 검증은 시나리오별). 전문: `vibe/rules/principles/dual-harness-doctrine.md`.
|
|
128
|
+
|
|
127
129
|
### Automated Verification (Closed Loop)
|
|
128
130
|
|
|
129
131
|
**자율적 AI 코딩 = 구현 + 검증 + 반복. 검증을 AI에게 맡기는 순간 루프가 닫힌다.**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: vibe.test
|
|
3
3
|
description: Self-test vibe — probe every command/skill/hook/agent in the target harness install dir and write a pass/fail report
|
|
4
|
-
argument-hint: "[cc|
|
|
4
|
+
argument-hint: "[cc|codex] (empty = current harness)"
|
|
5
5
|
user-invocable: true
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -14,10 +14,10 @@ user-invocable: true
|
|
|
14
14
|
```
|
|
15
15
|
/vibe.test # Test current harness (auto-detect)
|
|
16
16
|
/vibe.test cc # Force-test ~/.claude/
|
|
17
|
-
/vibe.test
|
|
17
|
+
/vibe.test codex # Force-test ~/.codex/
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
No subcommands. No CC-vs-
|
|
20
|
+
No subcommands. No CC-vs-Codex comparison semantics. One command, one report.
|
|
21
21
|
|
|
22
22
|
## Report
|
|
23
23
|
|
|
@@ -34,7 +34,7 @@ Markdown summary is also printed to the console when the run finishes.
|
|
|
34
34
|
|
|
35
35
|
Load skill `test` with target harness: `$ARGUMENTS`
|
|
36
36
|
|
|
37
|
-
- If `$ARGUMENTS` is empty, detect the current harness (CC vs
|
|
37
|
+
- If `$ARGUMENTS` is empty, detect the current harness (CC vs Codex) and use that.
|
|
38
38
|
- If the target install dir is missing, exit cleanly with guidance (not an error).
|
|
39
39
|
|
|
40
40
|
See `skills/test/SKILL.md` for the probe spec and the report template.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Dual-Harness Doctrine
|
|
2
|
+
|
|
3
|
+
> vibe는 여러 하네스(Claude Code, Codex, Gemini) 위에서 동작한다.
|
|
4
|
+
> 차이는 경로·파일명 같은 **인프라**가 아니라 **인지 방식**에 있다.
|
|
5
|
+
|
|
6
|
+
## 비대칭의 본질
|
|
7
|
+
|
|
8
|
+
| | Claude Code | Codex |
|
|
9
|
+
|---|---|---|
|
|
10
|
+
| 모호한 요청 | 의도를 **추론**해 알아서 채움 | **직역** — 지시한 그대로만, 예시 텍스트도 실데이터로 |
|
|
11
|
+
| research 트리거 | planning mode를 켜야 시작 | 모드 없이 **자발적** 탐색 |
|
|
12
|
+
| 작업 단위 | 한 번에 working solution → 끝에 QA | **작게 순차** + 단계별 검증이 성공률 높음 |
|
|
13
|
+
| 도메인 지식 | 탐색을 맡겨도 됨 | 직접 주입할수록(라이브러리·함수·위치) 정확도↑ |
|
|
14
|
+
|
|
15
|
+
## Core Principle
|
|
16
|
+
|
|
17
|
+
> **vibe는 어떤 하네스의 *암묵적 동작*에도 의존하지 않는다.**
|
|
18
|
+
> **추론은 `/vibe` 디스패처가 앞단에서 한 번 하고, skill 본문은 모든 것을 명시적으로 쓴다.**
|
|
19
|
+
|
|
20
|
+
= **"명시성 공통분모 + 추론 앞단"** 모델
|
|
21
|
+
|
|
22
|
+
- **skill 본문 = 낮은 공통분모**: 명시적·직역-안전. Codex에서 안전하고 CC에서도 여전히 정확.
|
|
23
|
+
- **`/vibe` 디스패처 = 추론 레이어**: 모호한 자연어를 명시적 지시로 *먼저* 펼쳐, 모든 하네스에서 CC급 편의를 제공.
|
|
24
|
+
|
|
25
|
+
## Operating Rules
|
|
26
|
+
|
|
27
|
+
1. **추론은 앞단에서 단 한 번.** `/vibe`가 모호한 NL → 명시적·직역 가능한 지시로 전개한다. 하위 skill은 모호한 입력을 받지 않는다.
|
|
28
|
+
2. **예시·placeholder는 명시 표기.** 직역 하네스가 실데이터로 넣을 수 있는 예시 텍스트를 무표기로 쓰지 않는다. `<예시>`, `[채워넣을 값]`, `{{placeholder}}` 사용. (Codex는 무표기 예시를 그대로 테스트 데이터에 넣는다.)
|
|
29
|
+
3. **research는 명시적으로 트리거.** "planning mode" 스위치에 의존하지 않는다. 조사·탐색이 필요한 단계는 skill이 말로 지시한다.
|
|
30
|
+
4. **가장 작은 검증 단위로 분해.** 구현 → 검증 → 다음. 여러 단위를 묶지 않는다. (`vibe.run`의 시나리오 루프가 이미 이 방식 — ultrawork가 빅뱅으로 무너뜨리지 않게 유지.)
|
|
31
|
+
5. **도메인 지식은 SPEC에 주입.** SPEC/plan은 구체적 라이브러리명·함수명·파일 위치를 담는다. 선택이 아닌 **의무 출력** — Codex 정확도가 여기에 비례한다.
|
|
32
|
+
|
|
33
|
+
## Hooks Across Harnesses
|
|
34
|
+
|
|
35
|
+
CC의 풍부한 hook 모델(PreToolUse/PostToolUse/UserPromptSubmit/Stop)에는 Codex에 완전한 등가물이 없다. hook의 **의도**별로 하네스에 맞는 메커니즘에 매핑한다.
|
|
36
|
+
|
|
37
|
+
| hook 의도 | Claude Code | Codex |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| 라이프사이클 (turn 완료, 세션 시작/종료) | `Stop` / `SessionStart` hook | `config.toml`의 `notify` 프로그램 (agent-turn-complete 시 JSON 발화) |
|
|
40
|
+
| pre-edit / scope guard | `PreToolUse` (동기 deny) | ❌ 동기 인터셉트 없음 → AGENTS.md 운영 규칙 + notify 기반 사후 검증 |
|
|
41
|
+
| 키워드 디스패치 (ralph/ultrawork) | `UserPromptSubmit` | AGENTS.md 지시 (Codex가 직역 실행) |
|
|
42
|
+
| 금지 패턴 차단 | `PreToolUse` | AGENTS.md 규칙 + 에이전트에게 실행하라 지시한 check 명령 |
|
|
43
|
+
|
|
44
|
+
**핵심 통찰: Codex의 직역 성향이 AGENTS.md "soft hook"을 신뢰성 있게 만든다.** CC는 soft 지시를 가끔 무시해 hard hook이 필요하지만, Codex는 적힌 대로 실행한다. 따라서:
|
|
45
|
+
|
|
46
|
+
- **하드 라이프사이클 이벤트** → Codex `config.toml notify` (실제·결정적). `stop-dispatcher` 로직(auto-commit, devlog, review gate) 재사용 가능.
|
|
47
|
+
- **행동 가드** → AGENTS.md 운영 규칙. 직역이라 *오히려* 신뢰성 있음.
|
|
48
|
+
- **진짜 동기 pre-edit 차단은 Codex에서 불가** — 사후 검증을 완화책으로 수용한다.
|
|
49
|
+
|
|
50
|
+
> **Action item (미구현):** `.codex/settings.local.json`에 죽은 hook을 쓰는 것을 중단하고, 대신 `.codex/config.toml`에 `notify` 핸들러를 생성해 `stop-dispatcher` 로직을 재사용하며, 가드 규칙은 AGENTS.md로 방출한다.
|