@su-record/vibe 3.2.61 → 3.2.64
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-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/CLAUDE.md +32 -5
- package/dist/tools/bench/benchCompare.d.ts +78 -0
- package/dist/tools/bench/benchCompare.d.ts.map +1 -0
- package/dist/tools/bench/benchCompare.js +113 -0
- package/dist/tools/bench/benchCompare.js.map +1 -0
- package/dist/tools/bench/benchDefinition.d.ts +37 -0
- package/dist/tools/bench/benchDefinition.d.ts.map +1 -0
- package/dist/tools/bench/benchDefinition.js +69 -0
- package/dist/tools/bench/benchDefinition.js.map +1 -0
- package/dist/tools/bench/benchReport.d.ts +16 -0
- package/dist/tools/bench/benchReport.d.ts.map +1 -0
- package/dist/tools/bench/benchReport.js +64 -0
- package/dist/tools/bench/benchReport.js.map +1 -0
- package/dist/tools/bench/index.d.ts +10 -0
- package/dist/tools/bench/index.d.ts.map +1 -0
- package/dist/tools/bench/index.js +7 -0
- package/dist/tools/bench/index.js.map +1 -0
- package/dist/tools/contract/agentContract.d.ts +86 -0
- package/dist/tools/contract/agentContract.d.ts.map +1 -0
- package/dist/tools/contract/agentContract.js +140 -0
- package/dist/tools/contract/agentContract.js.map +1 -0
- package/dist/tools/contract/index.d.ts +8 -0
- package/dist/tools/contract/index.d.ts.map +1 -0
- package/dist/tools/contract/index.js +6 -0
- package/dist/tools/contract/index.js.map +1 -0
- package/dist/tools/contract/reverseDrift.d.ts +71 -0
- package/dist/tools/contract/reverseDrift.d.ts.map +1 -0
- package/dist/tools/contract/reverseDrift.js +136 -0
- package/dist/tools/contract/reverseDrift.js.map +1 -0
- package/dist/tools/docs/agentsMd.d.ts +45 -0
- package/dist/tools/docs/agentsMd.d.ts.map +1 -0
- package/dist/tools/docs/agentsMd.js +51 -0
- package/dist/tools/docs/agentsMd.js.map +1 -0
- package/dist/tools/docs/cacheSurface.d.ts +37 -0
- package/dist/tools/docs/cacheSurface.d.ts.map +1 -0
- package/dist/tools/docs/cacheSurface.js +98 -0
- package/dist/tools/docs/cacheSurface.js.map +1 -0
- package/dist/tools/index.d.ts +6 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +6 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/spec/index.d.ts +2 -0
- package/dist/tools/spec/index.d.ts.map +1 -1
- package/dist/tools/spec/index.js +2 -0
- package/dist/tools/spec/index.js.map +1 -1
- package/dist/tools/spec/specLifecycle.d.ts +40 -0
- package/dist/tools/spec/specLifecycle.d.ts.map +1 -0
- package/dist/tools/spec/specLifecycle.js +147 -0
- package/dist/tools/spec/specLifecycle.js.map +1 -0
- package/dist/tools/spec/validateSpecDocument.d.ts.map +1 -1
- package/dist/tools/spec/validateSpecDocument.js +13 -0
- package/dist/tools/spec/validateSpecDocument.js.map +1 -1
- package/hooks/scripts/code-check.js +7 -0
- package/hooks/scripts/lib/ephemeral-lane.js +106 -0
- package/hooks/scripts/lib/iteration-cost.js +178 -0
- package/hooks/scripts/lib/loop-ledger.js +38 -5
- package/hooks/scripts/loop-ledger.js +9 -1
- package/hooks/scripts/pre-tool-guard.js +16 -0
- package/hooks/scripts/step-counter.js +29 -0
- package/package.json +7 -3
- package/skills/vibe.contract/SKILL.md +114 -1
- package/skills/vibe.docs/references/agent.md +4 -0
- package/skills/vibe.loop/SKILL.md +47 -1
- package/skills/vibe.spec/SKILL.md +2 -1
- package/vibe/rules/loop-contract.md +25 -5
- package/vibe/rules/prefix-cache-surface.md +98 -0
- package/vibe/templates/spec-template.md +31 -2
|
@@ -134,7 +134,7 @@ SPEC 승인이 `vibe/rules/loop-contract.md` 가 정의하는 **유일한 의무
|
|
|
134
134
|
/vibe.verify "{feature-name}" # Done Criteria 판정 → run-ledger 기록
|
|
135
135
|
```
|
|
136
136
|
|
|
137
|
-
trace(`/vibe.trace`)·contract(`/vibe.contract`) 는 사용자가 요청하거나 SPEC 에 API Contract 섹션이 있을 때만 체인한다.
|
|
137
|
+
trace(`/vibe.trace`)·contract(`/vibe.contract`) 는 사용자가 요청하거나 SPEC 에 API Contract 섹션이 있을 때만 체인한다. Agent Contract 섹션이 있으면 `/vibe.contract agent` 도 함께 체인한다.
|
|
138
138
|
|
|
139
139
|
---
|
|
140
140
|
|
|
@@ -232,6 +232,7 @@ relevant files, and patterns in under 200 tokens.
|
|
|
232
232
|
- **Constraints** — 구현·보안·호환성 경계. execution packet으로 압축돼도 반드시 보존한다.
|
|
233
233
|
- **Rejected Alternatives (Traps)** — 검토했으나 기각한 설계 접근 + **기계적 기각 사유** 1줄씩 ("확장 안 됨" 같은 라벨이 아니라 "shelve 는 multi-writer 에서 thread-safe 하지 않다" 수준). 루프가 같은 막다른 길을 재방문하지 않기 위한 섹션 — Constraints 처럼 execution packet 압축에도 보존한다. 실질적 설계 선택지가 없었거나 demo/prototype 이면 생략.
|
|
234
234
|
- **API Contract** (해당 시에만) — 엔드포인트/요청/응답 형태. 이 섹션이 있으면 이후 `/vibe.contract` 가 drift 를 검사한다.
|
|
235
|
+
- **Agent Contract** (에이전트를 출하하는 기능만) — 허용/금지 도구, 되돌릴 수 없는 작업, 에스컬레이션 조건. 이 섹션이 있으면 `/vibe.contract agent` 가 **도구 호출 로그**에 대해 계약을 단언한다. 에스컬레이션은 로그로 판정할 수 없어 advisory 로만 나간다 — 판정할 수 없는 것을 게이트로 적지 않는다.
|
|
235
236
|
|
|
236
237
|
이어서 `.vibe/features/{feature-name}.feature` 를 생성한다: 시나리오 섹션을 gherkin 으로 변환 (Done Criteria ↔ Scenario 매핑 유지). `/vibe.run` 이 이 파일을 구현·검증 단위로 사용한다.
|
|
237
238
|
|
|
@@ -71,14 +71,32 @@ node "$HOOKS_DIR/loop-ledger.js" iteration <name> <verified|unverified> # 회
|
|
|
71
71
|
node "$HOOKS_DIR/loop-ledger.js" budget <name> [max] # → {iterations, verified, remaining, exhausted}
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
**세 축을 따로 센다:**
|
|
75
75
|
|
|
76
|
-
| 축 | 의미 | 쓰임 |
|
|
76
|
+
| 축 | 의미 | 쓰임 | 성격 |
|
|
77
|
+
|---|---|---|---|
|
|
78
|
+
| `iterations` | 모든 회전 | `max_iterations` 와 비교하는 **폭주 방어** | 판정 |
|
|
79
|
+
| `verified` | JUDGE 결정론 게이트를 통과한 회전만 | 실제로 **전진한 양** | 판정 |
|
|
80
|
+
| `cost` | 회전당 경과 시간 · 도구 호출 수 · 서브에이전트 수 | 그 전진이 **얼마짜리였나** | **계측** |
|
|
81
|
+
|
|
82
|
+
앞의 둘을 하나로 뭉치면 "10회를 썼다" 는 알아도 "그중 8회가 헛돌았다" 는 모른다 — 헛도는 루프와 원래 큰 작업을 구분할 수 없다. `exhausted: true` 면 잔여를 인박스로 이월하고 종료한다.
|
|
83
|
+
|
|
84
|
+
#### `cost` 는 계측이지 판정이 아니다
|
|
85
|
+
|
|
86
|
+
예산 소진·stuck·시운전 어디에도 영향을 주지 않는다. 축을 늘리는 것이 목적이 아니라, **지금 vibe 가 효율에 대해 아무 말도 할 수 없다**는 상태를 푸는 것이 목적이다 (constitution §3.5 — 측정하지 않은 수치는 쓰지 않는다).
|
|
87
|
+
|
|
88
|
+
**수치의 출처는 코드다.** 모델이 "도구를 12번 썼다" 고 보고하는 형태였다면 그건 이 문서가 처음부터 배제하는 자기보고이고, 그 위에 쌓인 데이터로는 아무것도 주장할 수 없다. `step-counter.js`(PostToolUse)가 이미 액션 툴콜을 `current-run.jsonl` 에 적고 있으므로, 회전 창(직전 회전 ~ 이번 회전)에 드는 줄을 세는 것으로 끝난다 — 모델은 아무것도 넘기지 않는다.
|
|
89
|
+
|
|
90
|
+
**재지 못한 것을 0 으로 적지 않는다.** 두 상태를 값과 구분해 남긴다:
|
|
91
|
+
|
|
92
|
+
| 상태 | 뜻 | 합계 |
|
|
77
93
|
|---|---|---|
|
|
78
|
-
| `
|
|
79
|
-
| `
|
|
94
|
+
| `measured: false` | 훅 미설치·첫 실행이라 **재지 못했다** | 제외 |
|
|
95
|
+
| `truncated: true` | 툴 로그가 회전해 창 앞부분이 사라졌다 — 그 값은 **하한** | 제외 |
|
|
80
96
|
|
|
81
|
-
|
|
97
|
+
`readBudget` 은 합계와 함께 `cost.measuredIterations`(분모)를 낸다. 분모를 모르면 합계는 거짓말이 된다 — "5회전에 도구 20회" 인지 "그중 2회전만 잰 20회" 인지 구분되지 않는다. 훅은 프로젝트 로컬이라 미설치가 흔하고, 그 환경에서 0 을 채우면 "회전당 도구 0회" 라는 거짓 데이터가 쌓인다.
|
|
98
|
+
|
|
99
|
+
> ⛔ **이 수치로 "N% 절감"·"몇 배 빠름" 을 쓰지 않는다.** 비교 데이터가 쌓이기 전의 배수·퍼센트는 §3.5 가 금지하는 바로 그것이다. 지금 하는 일은 **쌓는 것**이고, 비교는 `/vibe.test bench` 가 자기 대조로 할 일이다.
|
|
82
100
|
|
|
83
101
|
- **실행 실패(error)는 회전을 소비하지 않는다** — 위 실행 실패 절대로 루프가 즉시 종료되므로 예산을 갉아먹지 않는다. 재시도가 예산을 태우는 형태를 만들지 않는다.
|
|
84
102
|
- 계수는 직전 `start` 이후만 센다 — 새 실행은 예산도 새로 시작한다.
|
|
@@ -221,6 +239,8 @@ JUDGE는 이번 feature의 **신규 생성 파일** 기준으로 검증 코드
|
|
|
221
239
|
|
|
222
240
|
**어느 쪽이 결과가 나은지는 vibe 가 측정한 바 없다.** 컨텍스트 누적이 품질을 떨어뜨린다는 주장은 널리 퍼져 있지만 이 저장소에는 비교 데이터가 없다(수치 출처 규율 §3.5). 그래서 기본값을 바꾸지 않고 **축만 열어둔다** — 긴 무인 운전에서 컨텍스트 상한이 걱정되면 `per-iteration`, 회전 간 연속성이 중요하면 `continuous`.
|
|
223
241
|
|
|
242
|
+
재려면 `/vibe.loop bench` 로 조건만 바꿔 돌린 실행을 대조한다 — 표본이 부족하거나 관측 범위가 겹치면 그 도구가 `inconclusive` 를 내고 차이를 지어내지 않는다. 이 문장이 지워지는 시점은 벤치가 `difference-observed` 를 낸 뒤다.
|
|
243
|
+
|
|
224
244
|
전제 하나는 반드시 지킨다: `per-iteration` 에서 **넘길 것을 파일에 적기 전에 끝내지 않는다.** 맥락이 파일로만 넘어가는 구조이므로, 안 적으면 이월이 아니라 유실이다.
|
|
225
245
|
|
|
226
246
|
### 시운전 (처음 거는 루프)
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# 프리픽스 캐시 표면
|
|
2
|
+
|
|
3
|
+
> 매 요청의 **앞부분에 항상 실리는 자산**이 무엇이고, 그것을 건드리면 무엇이 깨지는지.
|
|
4
|
+
> 검증: `npm run validate:cache-surface` (CI `test` job).
|
|
5
|
+
|
|
6
|
+
## 왜 이 문서가 있는가
|
|
7
|
+
|
|
8
|
+
컨텍스트 정책(85% 룰, `/new` 가 KV 프리픽스 캐시를 전량 폐기한다)은 `CLAUDE.md` 에 한 줄로
|
|
9
|
+
적혀 있었다. 그 한 줄은 **어떤 파일을 고치면 캐시가 깨지는지**를 말해주지 않는다 — 그래서
|
|
10
|
+
"상시 로드 자산에 문단 하나 추가" 같은 변경이 리뷰에서 그냥 통과한다. 비용은 그 PR 이
|
|
11
|
+
아니라 이후 모든 세션의 첫 토큰에서 나온다.
|
|
12
|
+
|
|
13
|
+
여기서 고정하는 것은 두 가지다: **모델이 이 자산을 어떻게 경험하는가**(Model Experience)와
|
|
14
|
+
**이 자산을 바꾸면 캐시가 어떻게 되는가**(KV Cache effect). 자산이 늘거나 사라지면 게이트가 막는다.
|
|
15
|
+
|
|
16
|
+
## 무효화의 규칙 (모든 표면 공통)
|
|
17
|
+
|
|
18
|
+
프리픽스 캐시는 **접두사 일치**로 재사용된다 — 앞에서 한 바이트가 달라지면 그 뒤는 전부
|
|
19
|
+
다시 계산된다. 따라서 비용은 "얼마나 고쳤나" 가 아니라 **"얼마나 앞에서 고쳤나"** 로 정해진다.
|
|
20
|
+
표면을 아래 순서대로 읽는다: 위쪽일수록 한 글자의 대가가 크다.
|
|
21
|
+
|
|
22
|
+
<!-- surface: always-loaded-docs -->
|
|
23
|
+
## 표면 1 — 루트 지침 문서 (`CLAUDE.md` · `AGENTS.md`)
|
|
24
|
+
|
|
25
|
+
- **Model Experience**: 세션 시작 시 **전문이** 시스템 프롬프트에 들어간다. 모델은 이 문서를
|
|
26
|
+
"검색해서 찾는 문서" 가 아니라 **이미 알고 있는 규칙**으로 경험한다 — 그래서 여기 적힌 것은
|
|
27
|
+
탐색 없이 즉시 적용되고, 여기 없는 것은 존재를 모른다.
|
|
28
|
+
- **KV Cache effect**: 프리픽스의 가장 앞쪽에 가깝다. **한 줄만 고쳐도 그 아래 전체가 무효화**되고,
|
|
29
|
+
이후 모든 세션이 첫 요청에서 전문을 다시 계산한다. 문단 추가는 상시 비용이므로, 상세는
|
|
30
|
+
`vibe/rules/**` 로 내리고 루트에는 **포인터만** 남긴다.
|
|
31
|
+
|
|
32
|
+
| 자산 | 비고 |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `CLAUDE.md` | content SSOT |
|
|
35
|
+
| `AGENTS.md` | `CLAUDE.md` 에서 생성 (`npm run gen:agents-md`) |
|
|
36
|
+
|
|
37
|
+
<!-- surface: prefix-hooks -->
|
|
38
|
+
## 표면 2 — 프리픽스에 stdout 을 얹는 훅
|
|
39
|
+
|
|
40
|
+
훅 전체가 아니라 **턴 앞단에서 도는 두 이벤트**만 해당한다. `PreToolUse`/`PostToolUse`/`Stop` 은
|
|
41
|
+
턴 중간에 끼어들어 이미 만들어진 프리픽스를 바꾸지 않는다.
|
|
42
|
+
|
|
43
|
+
- **Model Experience**: 이 훅의 stdout 은 모델에게 **사용자가 말하지 않은 지시문**으로 보인다.
|
|
44
|
+
출처 표시가 없으면 사용자 발화와 구분되지 않으므로, 출력은 짧고 라벨이 붙어야 한다.
|
|
45
|
+
- **KV Cache effect**: `SessionStart` 출력은 세션 프리픽스에 **한 번** 박힌다 — 길이가 그대로
|
|
46
|
+
상시 비용이다. `UserPromptSubmit` 출력은 **매 턴** 프리픽스 끝에 붙는다. 출력이 턴마다
|
|
47
|
+
달라지면(시각·카운터·랜덤 순서) 그 지점부터 재사용이 끊기므로, **불변 텍스트를 앞에, 가변
|
|
48
|
+
텍스트를 뒤에** 둔다.
|
|
49
|
+
|
|
50
|
+
| 이벤트 | 스크립트 |
|
|
51
|
+
|---|---|
|
|
52
|
+
| SessionStart | `hooks/scripts/session-start.js` |
|
|
53
|
+
| UserPromptSubmit | `hooks/scripts/prompt-dispatcher.js` |
|
|
54
|
+
|
|
55
|
+
<!-- surface: agents -->
|
|
56
|
+
## 표면 3 — 에이전트 frontmatter `description`
|
|
57
|
+
|
|
58
|
+
- **Model Experience**: 에이전트 **본문은 로드되지 않는다.** 모델이 항상 보는 것은 이름과
|
|
59
|
+
`description` 한 줄뿐이고, 위임 여부는 전적으로 그 한 줄로 결정된다. description 이 비면
|
|
60
|
+
에이전트는 설치돼 있어도 **없는 것과 같다** (실측: frontmatter 가 YAML 파싱에 실패해 통째로
|
|
61
|
+
버려진 설치본이 11개 중 4개였다 — `CLAUDE.md` Gotchas).
|
|
62
|
+
- **KV Cache effect**: 에이전트 목록 전체가 프리픽스에 실린다. 에이전트를 **추가·삭제**하면
|
|
63
|
+
목록이 바뀌어 그 뒤가 무효화되고, description 을 한 글자 고쳐도 같다. 본문을 아무리 늘려도
|
|
64
|
+
프리픽스는 커지지 않는다 — **길이는 본문으로, 신호는 description 으로**.
|
|
65
|
+
|
|
66
|
+
| 에이전트 |
|
|
67
|
+
|---|
|
|
68
|
+
| `agents/architect.md` |
|
|
69
|
+
| `agents/build-error-resolver.md` |
|
|
70
|
+
| `agents/code-reviewer.md` |
|
|
71
|
+
| `agents/e2e-tester.md` |
|
|
72
|
+
| `agents/implementer.md` |
|
|
73
|
+
| `agents/security-reviewer.md` |
|
|
74
|
+
| `agents/tester.md` |
|
|
75
|
+
| `agents/event/event-ops.md` |
|
|
76
|
+
| `agents/event/event-planner.md` |
|
|
77
|
+
| `agents/ui/design-reviewer.md` |
|
|
78
|
+
| `agents/ui/design-system-gen.md` |
|
|
79
|
+
|
|
80
|
+
<!-- surface: skills -->
|
|
81
|
+
## 표면 4 — 스킬 frontmatter `description` (집계)
|
|
82
|
+
|
|
83
|
+
- **Model Experience**: 에이전트와 같다 — **본문은 호출될 때만** 로드되고, 상시 실리는 것은
|
|
84
|
+
`name` + `description` 이다. 따라서 스킬 본문의 길이는 라우팅 정확도에 기여하지 않는다.
|
|
85
|
+
라우팅은 description 이 한다.
|
|
86
|
+
- **KV Cache effect**: 스킬 **개수**가 프리픽스 길이를 좌우한다. 스킬을 하나 추가하면 목록이
|
|
87
|
+
길어져 그 뒤가 무효화된다. 그래서 스택·capability 로 갈라 설치하는 것이다 — 아무 프로젝트에나
|
|
88
|
+
실릴 이유가 없는 스킬은 내려둔다 (`GLOBAL_SKILLS_*` / `STACK_TO_SKILLS` / `CAPABILITY_SKILLS`).
|
|
89
|
+
- **개수 검증은 여기서 하지 않는다** — `npm run validate:counts` 가 이미 그 사실의 집이다.
|
|
90
|
+
같은 사실을 두 곳에서 세면 그 순간 두 벌이 된다.
|
|
91
|
+
|
|
92
|
+
## 새 표면을 추가할 때
|
|
93
|
+
|
|
94
|
+
1. 위 형식으로 절을 만든다 — `<!-- surface: {id} -->` 마커 + `Model Experience` + `KV Cache effect`.
|
|
95
|
+
2. 자산을 나열한다면 표의 백틱 경로가 실물과 **정확히 일치**해야 한다. 게이트가 양방향으로 본다:
|
|
96
|
+
문서에 없는 실물도, 실물이 없는 문서 항목도 실패다.
|
|
97
|
+
3. 집계로 충분하면 나열하지 않는다. 나열은 그 자체가 유지보수 비용이고, 다른 게이트가 이미
|
|
98
|
+
세고 있다면 여기서 또 세지 않는다.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# SPEC: {Feature Name}
|
|
2
2
|
|
|
3
3
|
- **Created**: {YYYY-MM-DD}
|
|
4
|
-
- **Status**: DRAFT | APPROVED
|
|
4
|
+
- **Status**: DRAFT | APPROVED | VERIFIED | SUPERSEDED | REJECTED (닫힌 집합 — `npm run validate:spec-lifecycle`)
|
|
5
|
+
- **Class**: feature | bug-fix | simplification | architecture | process | testing
|
|
5
6
|
- **Stakes**: demo | prototype | production — {판정 근거 1구} (SSOT: vibe/rules/loop-contract.md)
|
|
6
7
|
- **Tech Stack**: {Project tech stack summary}
|
|
7
8
|
|
|
@@ -146,10 +147,38 @@ Response: 201 {...}
|
|
|
146
147
|
|
|
147
148
|
---
|
|
148
149
|
|
|
149
|
-
## 7.
|
|
150
|
+
## 7. Agent Contract (only if the feature ships an agent)
|
|
151
|
+
|
|
152
|
+
> Presence of this section enables `/vibe.contract agent` — 에이전트 실행이 남긴 **도구 호출
|
|
153
|
+
> 로그**에 대해 계약을 단언한다. LLM 이 에이전트 응답을 채점하는 것이 아니다: 그건 Model Judge 라
|
|
154
|
+
> 완료 권한이 없다 (`vibe/rules/loop-contract.md`). 판정 대상이 로그이므로 위반은 차단한다.
|
|
155
|
+
|
|
156
|
+
- **Allowed tools**: `{tool_a}`, `{tool_b}` — 비워 두면 allowlist 미선언(미등재 호출을 검사하지 않는다)
|
|
157
|
+
- **Forbidden tools**: `{tool_x}`
|
|
158
|
+
- **Irreversible**: `{tool_y}` — 호출에 승인 기록(`approved: true`)이 있어야 한다
|
|
159
|
+
- **Escalate**: {조건 1문장} — **선언만 받는다.** 조건 충족 여부가 도구 로그에 없어 게이트가 되지 못하고,
|
|
160
|
+
advisory 로 사람에게 넘어간다. 판정할 수 없는 것을 게이트에 넣으면 통과 의식이 된다
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 8. Verification
|
|
150
165
|
|
|
151
166
|
- `/vibe.run "{feature}"` implements scenario-by-scenario, verifying each immediately.
|
|
152
167
|
- `/vibe.verify "{feature}"` judges the Done Criteria and sets `verifyPassed` in the run-ledger.
|
|
153
168
|
- Verification writes `.vibe/runs/{run-id}/evidence.json`; only deterministic Judge results can complete the loop.
|
|
154
169
|
- Model Judge findings are advisory-only. Human Taste is release-only.
|
|
155
170
|
- Gate = all Done Criteria pass (exit codes / observed behavior) — loop continues until gates pass, stuck, or max iterations.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Anchors
|
|
175
|
+
|
|
176
|
+
> **Class 가 feature · bug-fix · architecture 이고 Status 를 VERIFIED 로 올릴 때 필수.**
|
|
177
|
+
> 그 외에는 이 절을 통째로 지운다 — 고정할 코드 경로가 없는 SPEC 에 억지로 요구하면 통과 의식이 된다.
|
|
178
|
+
|
|
179
|
+
이 SPEC 이 안착한 경로를 나열한다. 여기 적힌 경로가 사라지면 `npm run validate:spec-lifecycle`
|
|
180
|
+
이 실패한다 — 그것이 "코드가 움직였는데 SPEC 이 따라오지 않았다" 를 잡는 유일한 신호다.
|
|
181
|
+
lifecycle 표기만으로는 못 잡는다: 문서는 Status 를 바꾸지 않은 채 늙기 때문이다.
|
|
182
|
+
|
|
183
|
+
- `{src/auth/session.ts}`
|
|
184
|
+
- `{src/auth/session.test.ts}`
|