@su-record/vibe 3.2.18 → 3.2.19

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.
Files changed (38) hide show
  1. package/CLAUDE.md +1 -0
  2. package/dist/cli/commands/remove.d.ts.map +1 -1
  3. package/dist/cli/commands/remove.js +15 -6
  4. package/dist/cli/commands/remove.js.map +1 -1
  5. package/dist/tools/dispatch/costGate.d.ts +59 -0
  6. package/dist/tools/dispatch/costGate.d.ts.map +1 -0
  7. package/dist/tools/dispatch/costGate.js +85 -0
  8. package/dist/tools/dispatch/costGate.js.map +1 -0
  9. package/dist/tools/dispatch/deterministicSignals.d.ts +61 -0
  10. package/dist/tools/dispatch/deterministicSignals.d.ts.map +1 -0
  11. package/dist/tools/dispatch/deterministicSignals.js +131 -0
  12. package/dist/tools/dispatch/deterministicSignals.js.map +1 -0
  13. package/dist/tools/dispatch/index.d.ts +5 -0
  14. package/dist/tools/dispatch/index.d.ts.map +1 -0
  15. package/dist/tools/dispatch/index.js +3 -0
  16. package/dist/tools/dispatch/index.js.map +1 -0
  17. package/dist/tools/index.d.ts +5 -0
  18. package/dist/tools/index.d.ts.map +1 -1
  19. package/dist/tools/index.js +4 -0
  20. package/dist/tools/index.js.map +1 -1
  21. package/dist/tools/spec/index.d.ts +2 -0
  22. package/dist/tools/spec/index.d.ts.map +1 -1
  23. package/dist/tools/spec/index.js +2 -0
  24. package/dist/tools/spec/index.js.map +1 -1
  25. package/dist/tools/spec/validateSpecDocument.d.ts +30 -0
  26. package/dist/tools/spec/validateSpecDocument.d.ts.map +1 -0
  27. package/dist/tools/spec/validateSpecDocument.js +201 -0
  28. package/dist/tools/spec/validateSpecDocument.js.map +1 -0
  29. package/package.json +1 -1
  30. package/skills/vibe/SKILL.md +18 -5
  31. package/skills/vibe.image/SKILL.md +8 -0
  32. package/skills/vibe.review/SKILL.md +8 -0
  33. package/skills/vibe.spec/SKILL.md +21 -0
  34. package/vibe/rules/loop-contract.md +31 -0
  35. package/dist/infra/lib/OrchestrateWorkflow.d.ts +0 -88
  36. package/dist/infra/lib/OrchestrateWorkflow.d.ts.map +0 -1
  37. package/dist/infra/lib/OrchestrateWorkflow.js +0 -259
  38. package/dist/infra/lib/OrchestrateWorkflow.js.map +0 -1
@@ -0,0 +1,201 @@
1
+ /**
2
+ * SPEC 문서 Code Guard — `vibe.spec` 산출물이 하류로 넘어가기 전에 검사한다.
3
+ *
4
+ * 배경: vibe 의 결정론 게이트는 전부 파이프라인 **끝**(JUDGE — run-ledger·테스트·RTM)에
5
+ * 몰려 있었다. 중간 노드에는 가드가 없어, 게이트로 쓸 수 없는 SPEC 이 run 까지
6
+ * 흘러간 뒤 verify 단계에서야 걸렸다. 실패를 늦게 발견할수록 비싸다.
7
+ *
8
+ * 여기서 검사하는 것은 취향이 아니라 **하류가 실제로 요구하는 것**이다:
9
+ * - RTM 은 `REQ-{feature}-NNN` 이 없으면 `status: 'empty'` 를 내고, 그건 통과가 아니라
10
+ * 판정불가다 (traceabilityMatrix.ts). 커버리지 게이트가 통째로 죽는다.
11
+ * - `Stakes:` 는 디스패처가 파이프라인 깊이를 정하는 입력이다.
12
+ * - Done Criteria 는 JUDGE 의 입력이다 — 없으면 판정할 것이 없다.
13
+ * - 채워지지 않은 placeholder 는 직역 하네스가 실데이터로 넣는다
14
+ * (dual-harness-doctrine 운영 규칙 2).
15
+ */
16
+ import path from 'path';
17
+ const REQ_ID = /\bREQ-([a-z0-9-]+)-(\d{3})\b/g;
18
+ const STAKES_LINE = /^\s*[-*]?\s*\*{0,2}Stakes\*{0,2}\s*[::]\s*(.+)$/im;
19
+ const VALID_STAKES = ['demo', 'prototype', 'production'];
20
+ /**
21
+ * 코드 구간(펜스 + 인라인 코드)을 공백으로 지운다 — 줄 번호는 보존한다.
22
+ *
23
+ * SPEC 은 경로 패턴(`styles/{feature}/`), 데이터 모양(`{r,g,b,a}`), 셸 brace
24
+ * expansion(`hooks/{a,b}.js`)을 인라인 코드로 정상적으로 쓴다. 원문을 그대로 훑으면
25
+ * 그것들이 전부 미치환 placeholder 로 잡힌다 (실측: 오탐 28건).
26
+ */
27
+ function stripCodeSpans(content) {
28
+ const blank = (block) => block.replace(/[^\n]/g, ' ');
29
+ return content
30
+ .replace(/```[\s\S]*?```/g, blank)
31
+ .replace(/`[^`\n]*`/g, blank);
32
+ }
33
+ function lineOf(content, index) {
34
+ return content.slice(0, index).split('\n').length;
35
+ }
36
+ /** 파일명에서 feature 슬러그를 뽑는다 (분할 SPEC 은 디렉토리명) */
37
+ export function featureSlugFromPath(specPath) {
38
+ const base = path.basename(specPath, '.md');
39
+ return base === '_index' ? path.basename(path.dirname(specPath)) : base;
40
+ }
41
+ function collectRequirementIds(content) {
42
+ const out = [];
43
+ for (const m of content.matchAll(REQ_ID)) {
44
+ out.push({ id: m[0], slug: m[1], index: m.index ?? 0 });
45
+ }
46
+ return out;
47
+ }
48
+ function checkRequirements(content, featureSlug, findings) {
49
+ const found = collectRequirementIds(content);
50
+ if (found.length === 0) {
51
+ findings.push({
52
+ severity: 'P1',
53
+ code: 'no-requirement-ids',
54
+ message: 'REQ-* ID 가 하나도 없다 — RTM 이 status:"empty" 를 내고 커버리지 게이트가 판정불가가 된다. '
55
+ + '모든 기능 요구사항에 REQ-{feature}-NNN 을 붙여라.',
56
+ });
57
+ return [];
58
+ }
59
+ // 파일명과 다른 슬러그는 게이트를 깨지는 않는다 — RTM 은 featureName 을 파일 탐색에만
60
+ // 쓰고 REQ 는 슬러그와 무관하게 전부 파싱한다(traceabilityMatrix.ts extractRequirements).
61
+ // 다만 ID 규약은 REQ-{feature}-NNN 이고(requirementId.ts), 어긋나면 여러 feature 의
62
+ // ID 가 한 문서에서 섞여 추적이 흐려진다 — 그래서 P2 로 알린다.
63
+ if (featureSlug) {
64
+ const mismatched = found.filter(f => f.slug !== featureSlug);
65
+ if (mismatched.length > 0) {
66
+ const slugs = [...new Set(mismatched.map(f => f.slug))];
67
+ findings.push({
68
+ severity: 'P2',
69
+ code: 'requirement-id-slug-mismatch',
70
+ message: `REQ 슬러그(${slugs.join(', ')})가 파일명(${featureSlug})과 다르다 — ${mismatched.length}건. `
71
+ + 'RTM 집계에는 포함되지만 ID 규약(REQ-{feature}-NNN)에서 벗어나 추적이 흐려진다.',
72
+ line: lineOf(content, mismatched[0].index),
73
+ });
74
+ }
75
+ }
76
+ return [...new Set(found.map(f => f.id))];
77
+ }
78
+ function checkStakes(content, findings) {
79
+ const m = content.match(STAKES_LINE);
80
+ if (!m) {
81
+ findings.push({
82
+ severity: 'P1',
83
+ code: 'no-stakes',
84
+ message: 'Stakes 필드가 없다 — 디스패처가 파이프라인 깊이를 정할 입력이 없다 (demo | prototype | production).',
85
+ });
86
+ return;
87
+ }
88
+ const value = m[1].toLowerCase();
89
+ if (!VALID_STAKES.some(s => value.includes(s))) {
90
+ findings.push({
91
+ severity: 'P1',
92
+ code: 'invalid-stakes',
93
+ message: `Stakes 값을 알 수 없다: "${m[1].trim()}" — demo | prototype | production 중 하나여야 한다.`,
94
+ });
95
+ }
96
+ }
97
+ function checkDoneCriteria(content, findings) {
98
+ const heading = content.match(/^#{1,3}\s*\d*\.?\s*Done Criteria.*$/im);
99
+ if (!heading) {
100
+ findings.push({
101
+ severity: 'P1',
102
+ code: 'no-done-criteria',
103
+ message: 'Done Criteria 섹션이 없다 — JUDGE 가 판정할 입력이 없다.',
104
+ });
105
+ return;
106
+ }
107
+ // 섹션 본문에 D1 같은 기준 항목이 실제로 있는지
108
+ const after = content.slice((heading.index ?? 0) + heading[0].length);
109
+ const body = after.split(/^#{1,3}\s/m)[0];
110
+ if (!/\bD\d+\b/.test(body)) {
111
+ findings.push({
112
+ severity: 'P1',
113
+ code: 'empty-done-criteria',
114
+ message: 'Done Criteria 섹션에 기준 항목(D1, D2 …)이 없다 — 제목만 있고 판정 기준이 비었다.',
115
+ line: lineOf(content, heading.index ?? 0),
116
+ });
117
+ }
118
+ }
119
+ /**
120
+ * 템플릿에서 온 미치환 placeholder — 직역 하네스가 실데이터로 넣는다.
121
+ *
122
+ * 좁게 잡는다. 중괄호 하나만으로는 판단할 수 없다 — 경로 패턴·데이터 모양·brace
123
+ * expansion 이 전부 중괄호를 쓴다. 템플릿 placeholder 는 **산문**이라는 점이
124
+ * 구분점이다: `{Observable functional requirement}` 처럼 공백을 포함한다.
125
+ * 반면 `{feature}` · `{token}` · `{r,g,b,a}` 는 공백이 없다.
126
+ *
127
+ * `<예시>` 는 검사하지 않는다 — dual-harness-doctrine 이 **권장하는** 예시 표기이지
128
+ * 채워야 할 자리가 아니다. `<채워넣을 값>` 만 미치환으로 본다.
129
+ */
130
+ function checkPlaceholders(content, findings) {
131
+ const scannable = stripCodeSpans(content);
132
+ const patterns = [
133
+ { re: /\{\{[^}\n]+\}\}/g, code: 'unresolved-template-var', label: '템플릿 변수' },
134
+ { re: /\{[^}\n]*\s[^}\n]*\}/g, code: 'unfilled-placeholder', label: 'placeholder' },
135
+ { re: /<채워넣을 값>/g, code: 'unfilled-placeholder', label: 'placeholder' },
136
+ ];
137
+ const seen = new Set();
138
+ for (const { re, code, label } of patterns) {
139
+ for (const m of scannable.matchAll(re)) {
140
+ const line = lineOf(scannable, m.index ?? 0);
141
+ if (seen.has(line))
142
+ continue;
143
+ seen.add(line);
144
+ findings.push({
145
+ severity: 'P1',
146
+ code,
147
+ message: `미치환 ${label}: ${m[0].slice(0, 60)} — 직역 하네스는 이 텍스트를 실데이터로 넣는다.`,
148
+ line,
149
+ });
150
+ }
151
+ }
152
+ }
153
+ function checkScenarios(content, findings) {
154
+ if (!/^#{1,3}\s*\d*\.?\s*Scenarios/im.test(content)) {
155
+ findings.push({
156
+ severity: 'P2',
157
+ code: 'no-scenarios',
158
+ message: 'Scenarios 섹션이 없다 — vibe.run 의 시나리오 루프가 분해할 단위가 없다.',
159
+ });
160
+ }
161
+ }
162
+ /**
163
+ * SPEC 문서를 검사한다.
164
+ *
165
+ * @param content SPEC 마크다운 원문
166
+ * @param options.specPath 파일 경로 — 주면 REQ 슬러그와 파일명 일치까지 검사한다
167
+ * @returns P1 이 없으면 valid
168
+ */
169
+ export function validateSpecDocument(content, options = {}) {
170
+ const findings = [];
171
+ if (content.trim().length === 0) {
172
+ return {
173
+ valid: false,
174
+ findings: [{ severity: 'P1', code: 'empty-spec', message: 'SPEC 이 비어 있다.' }],
175
+ requirementIds: [],
176
+ };
177
+ }
178
+ const featureSlug = options.specPath ? featureSlugFromPath(options.specPath) : undefined;
179
+ const requirementIds = checkRequirements(content, featureSlug, findings);
180
+ checkStakes(content, findings);
181
+ checkDoneCriteria(content, findings);
182
+ checkPlaceholders(content, findings);
183
+ checkScenarios(content, findings);
184
+ return {
185
+ valid: !findings.some(f => f.severity === 'P1'),
186
+ findings,
187
+ requirementIds,
188
+ };
189
+ }
190
+ /** 사람이 읽는 한 줄 요약 — 스킬이 그대로 출력한다 */
191
+ export function formatSpecValidation(result) {
192
+ if (result.valid && result.findings.length === 0) {
193
+ return `✅ SPEC guard 통과 — REQ ${result.requirementIds.length}건`;
194
+ }
195
+ const lines = result.findings.map(f => ` ${f.severity} ${f.code}${f.line ? ` (line ${f.line})` : ''}: ${f.message}`);
196
+ const head = result.valid
197
+ ? `⚠️ SPEC guard 통과 (P2 ${result.findings.length}건) — REQ ${result.requirementIds.length}건`
198
+ : `❌ SPEC guard 실패 — P1 ${result.findings.filter(f => f.severity === 'P1').length}건`;
199
+ return [head, ...lines].join('\n');
200
+ }
201
+ //# sourceMappingURL=validateSpecDocument.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateSpecDocument.js","sourceRoot":"","sources":["../../../src/tools/spec/validateSpecDocument.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@su-record/vibe",
3
- "version": "3.2.18",
3
+ "version": "3.2.19",
4
4
  "description": "AI Coding Framework for Claude Code — 7+ agents, 52 skills, multi-LLM orchestration",
5
5
  "type": "module",
6
6
  "main": "dist/cli/index.js",
@@ -103,12 +103,25 @@ user-invocable: true
103
103
 
104
104
  ### Phase 2: Smart Resume 감지
105
105
 
106
+ **파일 존재 검사는 눈으로 하지 않는다 — 명령이 확정한다.** Phase 0 의 URL·첨부 분류와
107
+ stakes 의 결정론 신호(config 유무·임시 디렉토리·git 여부)도 이 한 번의 호출로 함께 받는다:
108
+
109
+ ```bash
110
+ node -e "import('{{VIBE_PATH_URL}}/node_modules/@su-record/vibe/dist/tools/index.js').then(t => { console.log(JSON.stringify(t.collectDispatchSignals(process.cwd(), {urls: [], attachments: [], feature: undefined}), null, 2)); })"
106
111
  ```
107
- .vibe/.last-feature 존재 → 직전 feature 이름 추출
108
- .vibe/specs/{feature}/ 또는 .vibe/specs/{feature}.md 존재 → spec 단계 완료
109
- .vibe/features/{feature}/ 또는 .vibe/features/{feature}.feature 존재 → feature 단계 완료
110
- .vibe/plans/{feature}.md · .vibe/interviews/{feature}.md 존재 → 레거시 아티팩트 (구버전) — spec 패스의 입력 컨텍스트로만 사용, 재생성 금지
111
- ```
112
+
113
+ 반환값을 **사실로 받는다**:
114
+
115
+ | 필드 | 의미 |
116
+ |---|---|
117
+ | `resume.resumeFrom` | `run`(SPEC 있음) / `none`(처음부터) |
118
+ | `resume.specPath` · `featurePath` | 실제 경로 (분할 SPEC `_index.md` 포함) |
119
+ | `resume.legacyArtifacts` | 구버전 plans/interviews — **입력 컨텍스트로만** 쓰고 재생성 금지 |
120
+ | `stakes.hasVibeConfig` · `isTempDir` · `isGitRepo` | Phase 1-b 의 결정론 신호 (언어 신호는 모델 판단으로 남는다) |
121
+ | `urls[].kind` | `figma` / `github` / `youtube` / `web` |
122
+ | `attachments[].kind` · `exists` | `spec` / `feature` / `document` / `image` / `code` |
123
+
124
+ > 의도 분류(Phase 1)는 그대로 모델이 한다 — 애매한 판단은 모델, 파일 존재·도메인·확장자는 코드다.
112
125
 
113
126
  감지된 진행 상태가 있으면 사용자에게 명시:
114
127
 
@@ -34,6 +34,14 @@ Generate images using the Antigravity image backend.
34
34
  **Step 0: Script path:**
35
35
  - `[LLM_SCRIPT]` = `{{VIBE_PATH}}/hooks/scripts/llm-orchestrate.js`
36
36
 
37
+ **Step 0-b: 비용 게이트 (생성 전 의무)** — 이미지 생성은 되돌릴 수 없는 지출이다. SSOT: `vibe/rules/loop-contract.md` 비용 게이트 절.
38
+
39
+ ```bash
40
+ node -e "import('{{VIBE_PATH_URL}}/node_modules/@su-record/vibe/dist/tools/index.js').then(t => { const op={kind:'paid-generation',provider:'antigravity',label:'이미지 {N}장 생성'}; console.log(t.formatCostGate(op, t.evaluateCostGate(op))); })"
41
+ ```
42
+
43
+ `ask` 면 생성 전에 무엇을 몇 장 만들지 제시하고 확인받는다. `autonomous` 면 묻지 않고 인박스에 기록한 뒤 진행한다. `.vibe/config.json` 의 `costGate.paidGenerationRequiresApproval: false` 로 끌 수 있다.
44
+
37
45
  **General image generation (Antigravity fast image):**
38
46
  ```bash
39
47
  node "[LLM_SCRIPT]" antigravity image "IMAGE_DESCRIPTION" --output "OUTPUT_PATH"
@@ -124,6 +124,14 @@ Detect project tech stack FIRST before launching reviewers.
124
124
 
125
125
  **Spawn one reviewer per focus, as concurrently as the harness allows** — a `code-reviewer` instance per focus plus `security-reviewer`, each scoped to the changed files.
126
126
 
127
+ **스폰 직전 비용 게이트** (SSOT: `vibe/rules/loop-contract.md` 비용 게이트 절). 위 표대로 정한 리뷰어 수를 그대로 넣는다:
128
+
129
+ ```bash
130
+ node -e "import('{{VIBE_PATH_URL}}/node_modules/@su-record/vibe/dist/tools/index.js').then(t => { const op={kind:'agent-fanout',agentCount:{N},label:'리뷰어 {N}종 병렬'}; console.log(t.formatCostGate(op, t.evaluateCostGate(op))); })"
131
+ ```
132
+
133
+ 기본 임계값(12)에서 demo 2종·prototype 3종·production 8종은 전부 **통과**한다 — 평상시 규모는 멈추지 않는다. `ask` 가 나오면 스폰 전에 사용자에게 확인하고, `record` (autonomous) 면 묻지 않고 인박스에 남긴 뒤 진행한다.
134
+
127
135
  호출 계약(하네스 무관): "에이전트 `{agent}` 를 인자 `Review {FILES} — focus: {focus}` 로 실행한다"
128
136
 
129
137
  ```
@@ -35,6 +35,8 @@ Input 분석 + Smart Resume
35
35
 
36
36
  Execute the bundled implementation below — 단일 패스: 컨텍스트 수집 → (필요시) 인라인 질문 → SPEC + Feature 작성 → 셀프 리뷰 1회
37
37
 
38
+ SPEC Code Guard (아래) — P1 이 있으면 승인으로 가지 않고 SPEC 작성으로 되돌아간다
39
+
38
40
  SPEC 승인 (1회 — automationLevel: autonomous 면 생략)
39
41
 
40
42
  /vibe.run "{feature-name}"
@@ -65,6 +67,25 @@ Legacy `.vibe/interviews/` or `.vibe/plans/` artifacts가 실제로 감지된
65
67
  - 개인 작업 포인터이므로 git 커밋 금지 (`.gitignore` 에 `.vibe/.last-feature`).
66
68
  - 워크플로 완주(verify 통과) 시 삭제.
67
69
 
70
+ ## SPEC Code Guard (승인 전 의무)
71
+
72
+ SPEC 을 쓴 직후, **승인을 요청하기 전에** 실행한다. 셀프 리뷰가 아니라 코드 판정이다:
73
+
74
+ ```bash
75
+ node -e "import('{{VIBE_PATH_URL}}/node_modules/@su-record/vibe/dist/tools/index.js').then(t => { const fs=require('fs'); const p='.vibe/specs/{feature-name}.md'; const r=t.validateSpecDocument(fs.readFileSync(p,'utf-8'),{specPath:p}); console.log(t.formatSpecValidation(r)); process.exitCode = r.valid ? 0 : 1; })"
76
+ ```
77
+
78
+ | 검사 | 심각도 | 왜 하류가 깨지는가 |
79
+ |---|---|---|
80
+ | REQ-* ID 부재 | P1 | RTM 이 `status:"empty"` — 커버리지 게이트가 판정불가가 된다 |
81
+ | Stakes 부재/오값 | P1 | 디스패처가 파이프라인 깊이를 정할 입력이 없다 |
82
+ | Done Criteria 부재/빈 섹션 | P1 | JUDGE 가 판정할 기준이 없다 |
83
+ | 미치환 placeholder | P1 | 직역 하네스가 예시 텍스트를 실데이터로 넣는다 |
84
+ | Scenarios 부재 | P2 | `vibe.run` 시나리오 루프의 분해 단위가 없다 |
85
+ | REQ 슬러그 ≠ 파일명 | P2 | 게이트는 통과하나 ID 규약 이탈로 추적이 흐려진다 |
86
+
87
+ **P1 이 하나라도 있으면 승인 요청으로 넘어가지 않는다** — SPEC 작성으로 되돌아가 고치고 다시 검사한다 (backward edge). 2회 연속 같은 findings 면 stuck 으로 처리한다 (SSOT: `vibe/rules/loop-contract.md`). P2 는 통과를 막지 않고 승인 메시지에 함께 표시한다.
88
+
68
89
  ## 승인과 루프
69
90
 
70
91
  SPEC 승인이 `vibe/rules/loop-contract.md` 가 정의하는 **유일한 의무적 사람 개입**이다. 승인 후에는 ANCHOR→ACT→JUDGE→RECORD 루프가 게이트 통과까지 자동 반복한다 (`/vibe.run` → `/vibe.verify`). 별도의 파이프라인 승인·단계별 stop gate 는 없다.
@@ -62,6 +62,37 @@ node "$HOOKS_DIR/loop-ledger.js" anchor [feature]
62
62
 
63
63
  > `autonomous` 의 "계속" 은 **stuck 난 루프를 더 돌린다는 뜻이 아니다** — 2회 연속 동일 발견은 정의상 재시도가 무의미하다. 같은 목표를 붙잡지 않고 다음 단위로 넘어간다는 뜻이며, 미달은 TODO/인박스에 남는다. 미달 상태를 **완료로 기록하지 않는다.**
64
64
 
65
+ ### 비용 게이트 — 사람은 시작점에만 서지 않는다
66
+
67
+ SPEC 승인은 **유일한 의무 게이트**로 남는다. 다만 승인 이후 max_iterations 까지 무인이라, 그 안의 되돌릴 수 없는 지출과 이상 규모 팬아웃을 아무도 보지 못했다. 비용 게이트는 그 둘만 잡는다 — 평상시 규모는 그대로 통과시킨다.
68
+
69
+ ```bash
70
+ node -e "import('{{VIBE_PATH_URL}}/node_modules/@su-record/vibe/dist/tools/index.js').then(t => { const d=t.evaluateCostGate({kind:'agent-fanout',agentCount:N}); console.log(t.formatCostGate({kind:'agent-fanout',agentCount:N}, d)); })"
71
+ ```
72
+
73
+ | 작업 | 기본 판정 | 근거 |
74
+ |---|---|---|
75
+ | `paid-generation` | **묻는다** | 되돌릴 수 없는 지출 |
76
+ | `agent-fanout` > 12 | **묻는다** | 위임마다 컨텍스트 재주입 — 비용이 개수에 비례 |
77
+ | `agent-fanout` ≤ 12 | 통과 | production 기본 리뷰어 셋(8종)+조건부는 평상시 규모다 |
78
+
79
+ - 임계값을 기본 셋 아래로 두면 매 리뷰가 멈춘다 — **의례가 된 게이트는 무시당한다.** 조정은 `.vibe/config.json` 의 `costGate.{enabled, maxAgentsWithoutApproval, paidGenerationRequiresApproval}`.
80
+ - `autonomous` 는 **묻지 않는다.** 대신 결정을 인박스에 기록한다 (`loop-ledger.js inbox`) — stuck 처리와 같은 원칙: 비대화형이라고 판정을 없애지 않고, 사람이 볼 자리로 옮긴다.
81
+
82
+ ### 노드 가드 — 게이트를 끝에만 두지 않는다
83
+
84
+ 결정론 게이트가 전부 JUDGE(파이프라인 끝)에만 있으면, 쓸 수 없는 산출물이 체인을 끝까지 타고 간 뒤에야 걸린다. 실패는 **만들어진 노드에서** 잡는 것이 싸다.
85
+
86
+ - 산출물을 내는 노드는 그 산출물이 **하류가 요구하는 형태인지** 코드로 검사한다. 취향이 아니라 계약을 검사한다 — "이게 없으면 하류의 무엇이 깨지는가"로 항목을 정한다.
87
+ - 실패하면 다음 노드로 가지 않고 **그 노드로 되돌아간다** (backward edge). 루프 전체를 재시작하지 않는다.
88
+ - 되돌린 뒤에도 같은 findings 가 2회 연속이면 stuck 이다 (위 stuck 절).
89
+
90
+ | 노드 | 가드 | 검사 근거 |
91
+ |---|---|---|
92
+ | `vibe.spec` | `validateSpecDocument` | RTM 이 게이트로 동작할 REQ-* / JUDGE 입력인 Done Criteria / 디스패처 입력인 Stakes / 직역 하네스가 실데이터로 넣는 placeholder |
93
+ | `vibe.run` | 테스트 exit code · run-ledger | 기존 JUDGE |
94
+ | `vibe.clone` · `vibe.figma` | pixelmatch diffRatio · computed CSS delta | 측정된 P1 (위 Judge 권한 경계 표) |
95
+
65
96
  ### 실행 실패 (error) — stuck 과 다른 종료 사유
66
97
 
67
98
  stuck 은 **같은 발견이 반복되는** 상태다. 스킬이 로드되지 않거나, 도구가 없거나, 파일이 없거나, 명령이 비정상 종료하는 것은 stuck 이 아니라 **실행 실패**이며 해시 비교로는 잡히지 않는다. 재시도 대상도 아니다 — 환경이 바뀌지 않는 한 결과가 같다.
@@ -1,88 +0,0 @@
1
- /**
2
- * Orchestrate Workflow Pattern
3
- * Intent Gate → Assessment → Delegation → Verification
4
- */
5
- export type CodebaseMaturity = 'disciplined' | 'transitional' | 'legacy' | 'greenfield';
6
- export interface IntentGateResult {
7
- hasMatchingSkill: boolean;
8
- skillName?: string;
9
- shouldDelegate: boolean;
10
- reason: string;
11
- }
12
- export interface CodebaseAssessment {
13
- maturity: CodebaseMaturity;
14
- patterns: string[];
15
- techStack: string[];
16
- testCoverage: 'high' | 'medium' | 'low' | 'none';
17
- documentationLevel: 'comprehensive' | 'partial' | 'minimal' | 'none';
18
- risks: string[];
19
- }
20
- export interface DelegationPlan {
21
- phases: DelegationPhase[];
22
- totalAgents: number;
23
- estimatedComplexity: 'low' | 'medium' | 'high';
24
- requiredVerifications: string[];
25
- }
26
- export interface DelegationPhase {
27
- name: string;
28
- agents: AgentTask[];
29
- dependencies: string[];
30
- verificationCriteria: string[];
31
- }
32
- export interface AgentTask {
33
- agentType: string;
34
- model: 'haiku' | 'sonnet' | 'opus';
35
- prompt: string;
36
- background: boolean;
37
- timeout?: number;
38
- }
39
- export interface VerificationResult {
40
- passed: boolean;
41
- evidence: Evidence[];
42
- issues: string[];
43
- architectReview?: string;
44
- }
45
- export interface Evidence {
46
- type: 'build' | 'test' | 'lint' | 'typecheck' | 'manual';
47
- command?: string;
48
- exitCode?: number;
49
- output?: string;
50
- passed: boolean;
51
- }
52
- /**
53
- * Phase 0: Intent Gate
54
- * Check if there's a matching skill BEFORE doing any work
55
- */
56
- export declare function checkIntentGate(prompt: string): IntentGateResult;
57
- /**
58
- * Phase 1: Codebase Assessment
59
- * Classify codebase maturity and characteristics
60
- */
61
- export declare function assessCodebase(signals: {
62
- hasTests: boolean;
63
- hasLinting: boolean;
64
- hasTypescript: boolean;
65
- hasCICD: boolean;
66
- hasDocumentation: boolean;
67
- fileCount: number;
68
- techStack: string[];
69
- }): CodebaseAssessment;
70
- /**
71
- * Phase 2: Create Delegation Plan
72
- * Plan how to delegate work to sub-agents
73
- */
74
- export declare function createDelegationPlan(task: string, assessment: CodebaseAssessment, phaseCount?: number): DelegationPlan;
75
- /**
76
- * Phase 3: Verification with Evidence
77
- * Collect evidence of completion
78
- */
79
- export declare function createVerificationChecklist(plan: DelegationPlan): Evidence[];
80
- /**
81
- * Format orchestration status
82
- */
83
- export declare function formatOrchestrationStatus(phase: string, assessment: CodebaseAssessment, plan: DelegationPlan): string;
84
- /**
85
- * Background task rules
86
- */
87
- export declare function shouldRunInBackground(command: string): boolean;
88
- //# sourceMappingURL=OrchestrateWorkflow.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"OrchestrateWorkflow.d.ts","sourceRoot":"","sources":["../../../src/infra/lib/OrchestrateWorkflow.ts"],"names":[],"mappings":"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"}