Skip to content
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ modified: 2026-09-13

## [Unreleased]

### Added
- **프로젝트에 적용된 하네스 버전 기록·표시** (task `harness-version-stamp`). `init`이 `.harness/render-state.json`에
실행 중인 하네스의 `package.json` version을 `harnessVersion`으로 남기고(타임스탬프 없음 — 같은 버전 재실행은 diff 없음),
`doctor`가 `harness version: project applied X · CLI Y · plugin Z` 한 줄과 `--json` `versions` 필드로 보여 준다.
적용 버전 < 실행 중 CLI면 `harness-team init --yes`를 처방하는 경고, 적용 버전 > CLI면 관리 절 퇴행 위험 경고를 낸다(차단 없음).
필드가 없거나 형식이 틀린 기존 설치본은 `unknown (기록 이전 설치)`로 보고 경고하지 않는다.

## [0.44.5] - 2026-09-28

### Fixed
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ All checks passed.

심볼: `✓` 정상, `✗` 실패(exit 1), `-` 선택 항목 없음(정상).
소비자 프로젝트에서는 PATH의 `harness-team`이 `session-context`·`handoff`·`boundary`를 지원하는지도 경고로 점검합니다. 플러그인 소스 저장소는 소비자 훅을 설치하지 않으므로 이 항목이 n/a로 건너뛰어집니다.
마지막 줄 근처의 `harness version: project applied … · CLI … · plugin …`은 이 프로젝트에 마지막으로 `init`을 적용한 하네스 버전(`.harness/render-state.json`의 `harnessVersion`), doctor를 실행 중인 CLI 버전, 설치된 플러그인 버전을 나란히 보여 줍니다(`--json`은 `versions` 필드). 기록이 없는 설치본은 `unknown (기록 이전 설치)`로 표시되고 경고하지 않습니다 — 다음 `init`부터 기록됩니다. 적용 버전이 실행 중인 CLI보다 낮으면 `harness-team init --yes`를 처방하는 경고를, 높으면 구버전 CLI로 `init`하면 관리 절이 퇴행할 수 있다는 경고를 냅니다(경고만 — `init`을 막지는 않습니다).
관측 로그의 트립와이어가 발화한 상태면 `observe trip wires` 경고 1건(wire id·수치·`harness-team observe` 안내·루프백 nudge)을 냅니다 — warn 수준이라 exit code는 그대로이고, 로그가 없거나 발화가 없으면 항목 자체가 없습니다.

### `/harness-observe` — 관측 로그 스코어카드 · 트립와이어
Expand Down Expand Up @@ -755,7 +756,7 @@ cd ~/work/project-a

## 설치 결과물

설치되는 파일과 task 계약은 scaffold 되는 `AGENTS.md`의 **작업 프로토콜** 및 `templates/`를 확인합니다. 개인 상태 파일은 `.harness/active.json`에 보관됩니다. 반면 백업 클론 폴더 경로를 기억하는 `.harness/backup.json`은 팀이 공유하는 설정이므로 commit을 권장합니다. 관리 절의 마지막 렌더 해시를 담는 `.harness/render-state.json`도 **팀 상태이므로 반드시 commit 합니다** — 커밋하지 않으면 팀원이 clone한 뒤 첫 `init`에서 판정 근거가 없어 관리 절의 사용자 편집을 한 번 덮어씁니다.
설치되는 파일과 task 계약은 scaffold 되는 `AGENTS.md`의 **작업 프로토콜** 및 `templates/`를 확인합니다. 개인 상태 파일은 `.harness/active.json`에 보관됩니다. 반면 백업 클론 폴더 경로를 기억하는 `.harness/backup.json`은 팀이 공유하는 설정이므로 commit을 권장합니다. 관리 절의 마지막 렌더 해시를 담는 `.harness/render-state.json`도 **팀 상태이므로 반드시 commit 합니다** — 커밋하지 않으면 팀원이 clone한 뒤 첫 `init`에서 판정 근거가 없어 관리 절의 사용자 편집을 한 번 덮어씁니다. 이 파일의 `harnessVersion`은 마지막으로 `init`을 적용한 하네스 버전이고(`version`은 파일 스키마 버전), `doctor`가 실행 중인 CLI와 비교합니다. 타임스탬프는 남기지 않으므로 같은 버전으로 `init`을 다시 돌려도 diff가 생기지 않습니다.

자동으로 `.gitignore`에 추가되는 항목(`.harness/`를 통째로 무시하지 않습니다 — `backup.json`·`cursor-mirror.json`·`render-state.json`은 팀 상태):
- `.claude/settings.local.json` (개인 권한 오버라이드)
Expand Down
32 changes: 32 additions & 0 deletions docs/hslee/harness-version-stamp/harness-version-stamp-artifact.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# harness-version-stamp — Artifact

*최종 결과물과 학습 내용을 기록한다.*

## 결과

- 다이어그램: 미실행 — orchestrator 위임 — 소규모 변경 (2026-10-03)
- 2026-10-03: `init`이 `.harness/render-state.json`에 `harnessVersion`(실행 중 하네스 package.json version)을 기록한다
(`src/harness.mjs` planChanges — init 저장 경로 재사용이라 `src/commands/init.mjs`는 무수정).
`loadRenderState`는 semver 형식만 통과(#113 `stack` 선례). doctor는 `harness version: project applied X · CLI Y · plugin Z`
check와 `--json` `versions`를 낸다. 적용 < CLI → warning + `harness-team init --yes`, 적용 > CLI → warning + CLI 갱신 명령
(`cliDriftAction` 재사용). 기록 없음은 `unknown (기록 이전 설치)` · 경고 없음, plugin-dev는 `n/a`.
- src 수정 파일 3개(render-state·harness·doctor). 테스트: render-state 2·doctor 4 추가. README·CHANGELOG [Unreleased] 갱신.
- 검증: `npm run test` 1078 pass / 0 fail / 1 skip (+perf 1 pass), `npm run docs:check` 최신,
임시 소비자 프로젝트에서 init→doctor 실측(일치 pass, 0.40.0으로 낮추면 warning + `init --yes`).
- 후속 후보: SessionStart 훅 nudge(적용 < CLI일 때 한 줄) — 이번 범위 밖.
- PR: https://github.com/bd-makers/team-harness/pull/118 (2026-10-03, 머지 전)

## Reviews
*Codex 등 리뷰 실행 시 결과(요약·발견·조치)를 날짜와 함께 남긴다. 남기지 않은 리뷰는 "안 한 것"으로 간주.*
*기계 판독용 마커를 함께 남긴다: `<!-- harness:review kind=codex scope=worktree tip=<sha|none> at=<ISO8601> -->`*

### 2026-10-03 — codex read-only (`codex exec --sandbox read-only`, origin/main...c9b7cc6)
<!-- harness:review kind=codex scope=branch tip=c9b7cc6 at=2026-10-03T14:10:00+09:00 -->
- 요약: 결함 1건(P2).
- **P2** `src/render-state.mjs` SEMVER 정규식이 prerelease와 build metadata를 함께 쓴 유효 semver(`0.44.5-rc.1+build.7`)를
거부 → 그런 CLI는 `harnessVersion`을 기록 못 하고 doctor가 unknown으로 보며 비교 경고를 놓친다.
- 조치: 재현 확인 후 `(?:-…)?(?:\+…)?`로 분리, render-state 테스트에 동시 사용 케이스 추가.


## Learnings
- `codex exec`는 stdin이 열려 있으면 "Reading additional input from stdin..."에서 무한 대기한다 — 비대화형 호출은 `< /dev/null`.
23 changes: 23 additions & 0 deletions docs/hslee/harness-version-stamp/harness-version-stamp-context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# harness-version-stamp — Context Card
<!-- working set only; UTF-8 <= 6 KiB, nonblank lines <= 100 -->

## Now
- Goal: init이 render-state에 harnessVersion을 기록하고 doctor가 project·CLI·plugin 버전을 보여 주며 방향별 경고.
- Current atomic step: PR #118 생성 완료 — 리뷰·CI 대기. 머지·release·done·summary --write는 하지 않는다.
- Stop / human-decision condition: src 수정 파일 5개 초과 또는 설계 변경 필요 시.

## Constraints and settled decisions
- 타임스탬프 없음(재실행 diff 방지). init 차단 없음 — 경고만. 새 의존성 금지.
- plugin-dev 저장소는 project `n/a`·경고 없음. 적용 > CLI 경고 next_action은 `cliDriftAction` 재사용.

## JIT retrieval map
- Identifiers / symbols: readHarnessVersion, harnessVersion, compareVersions, harnessVersionReport, readInstalledHarnessVersion
- Narrow globs: src/render-state.mjs, src/harness.mjs, src/commands/doctor.mjs
- Read next: tests/render-state.test.mjs, tests/doctor.test.mjs (말미)
- Verification command: npm run test && npm run docs:check

## Failure capsules (max 3 unresolved)
- (none)

## Resume checklist
- codex 리뷰 P2 반영 완료 → artifact ## Reviews 참조.
35 changes: 35 additions & 0 deletions docs/hslee/harness-version-stamp/harness-version-stamp-handoff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# harness-version-stamp — Handoff

(세션 종료 시 post-commit hook이 자동 갱신합니다)

## 2026-10-03T04:46:20.649Z — c9b7cc6 feat(doctor): 프로젝트에 적용된 하네스 버전을 기록하고 doctor에서 보여 준다
CHANGELOG.md | 7 ++
README.md | 3 +-
.../harness-version-stamp-artifact.md | 14 ++++
.../harness-version-stamp-context.md | 27 ++++++++
.../harness-version-stamp-handoff.md | 3 +
.../harness-version-stamp-meta.json | 11 ++++
.../harness-version-stamp-plan.md | 24 +++++++
.../harness-version-stamp-spec.md | 74 ++++++++++++++++++++++
src/commands/doctor.mjs | 62 ++++++++++++++++--
src/harness.mjs | 11 +++-
src/render-state.mjs | 18 +++++-
tests/doctor.test.mjs | 57 ++++++++++++++++-
tests/render-state.test.mjs | 19 +++++-
13 files changed, 317 insertions(+), 13 deletions(-)

## 2026-10-03T04:58:30.448Z — 72dab4b fix(render-state): prerelease와 build metadata를 함께 쓴 semver도 harnessVersion으로 인정한다
.../harness-version-stamp-artifact.md | 17 ++++++++++++++
.../harness-version-stamp-context.md | 26 +++++++++-------------
.../harness-version-stamp-handoff.md | 16 +++++++++++++
.../harness-version-stamp-plan.md | 2 +-
src/render-state.mjs | 2 +-
tests/render-state.test.mjs | 2 ++
6 files changed, 48 insertions(+), 17 deletions(-)

## 2026-10-03T04:58:59.467Z — 26595f5 chore(task): harness-version-stamp ship — plan·artifact·handoff 갱신 (PR #118)
.../harness-version-stamp/harness-version-stamp-artifact.md | 1 +
.../hslee/harness-version-stamp/harness-version-stamp-context.md | 2 +-
.../hslee/harness-version-stamp/harness-version-stamp-handoff.md | 9 +++++++++
docs/hslee/harness-version-stamp/harness-version-stamp-plan.md | 2 +-
4 files changed, 12 insertions(+), 2 deletions(-)
11 changes: 11 additions & 0 deletions docs/hslee/harness-version-stamp/harness-version-stamp-meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"user": "hslee",
"task": "harness-version-stamp",
"created": "2026-10-03",
"firstActivatedAt": "2026-10-03T04:42:01.968Z",
"status": "open",
"closedAt": null,
"forcedAt": null,
"forcedIssues": null,
"reviews": []
}
24 changes: 24 additions & 0 deletions docs/hslee/harness-version-stamp/harness-version-stamp-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# harness-version-stamp — Plan

## 목표
init이 render-state에 적용 하네스 버전(`harnessVersion`)을 기록하고, doctor가 project·CLI·plugin 버전을
한 줄로 보여 주며 project ≠ CLI면 방향별 경고를 낸다.

## 단계
- [x] spec/plan 다이어그램 — 미실행(orchestrator 위임 — 소규모 변경)
- [x] render-state: `readHarnessVersion` + `loadRenderState`의 `harnessVersion` semver 필터
- [x] planChanges: renderState에 `harnessVersion` 기록 (init 저장 경로 재사용)
- [x] doctor: `compareVersions`·`harnessVersionReport`·`readInstalledHarnessVersion` + 출력/JSON/next_actions
- [x] 테스트: init 후 기록 / 필드 없음 unknown / 경고 작음·같음·큼 / 잘못된 형식 폐기
- [x] README: render-state 설명·doctor 절 갱신, `npm run docs:check`
- [x] `npm run test` 통과
- [x] codex read-only 리뷰 → artifact ## Reviews 기록·반영
- [x] ship: spec·plan·artifact 최종 갱신, push, PR 생성

## Ontology 변경 로그
*개념이 새로 정의되거나 의미가 바뀌면 한 줄로 기록. spec.md의 Ontology 섹션을 갱신할 트리거가 된다.*

- 2026-10-03: applied version(`harnessVersion`) 신설 — render-state 스키마 `version`과 구분.

## 참고
- 후속 후보: SessionStart 훅 nudge(기록 < CLI일 때 한 줄) — 이번 범위 밖.
74 changes: 74 additions & 0 deletions docs/hslee/harness-version-stamp/harness-version-stamp-spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# harness-version-stamp — Spec

## 목적 / 요구사항
*문제(오늘 무엇이 안 되는가) → 영향받는 사용자·시스템 → 기대 결과 → 제약 순으로 쓴다.
답 없는 질문은 요구가 아니다 — `## 참고` 절에 `- (open) …`으로 남긴다.*

- **문제**: 소비자 프로젝트에 "마지막으로 init을 돌린 하네스 버전"이 기록되지 않는다. 확인 수단은
`harness-team --version`(PATH CLI)과 doctor의 `cliDriftWarning`(PATH CLI vs 설치 플러그인, 불일치일
때만 경고)뿐이고, 둘 다 머신 상태지 프로젝트 상태가 아니다. `.harness/render-state.json`의
`"version": 1`은 스키마 버전이다.
- **영향**: 소비자 프로젝트 팀원 — 프로젝트가 낡은 관리 절로 남았는지, 반대로 더 새 하네스로 적용된
프로젝트에 구버전 CLI로 init 하려는지 알 수 없다.
- **기대 결과**:
1. `init`이 render-state를 저장할 때 실행 중인 하네스의 `package.json` version을 `harnessVersion`으로 쓴다.
2. `doctor`(사람용 + `--json`)가 `project applied X · CLI Y · plugin Z` 한 줄을 보여 준다.
기록 없음은 `unknown (기록 이전 설치)`.
3. 기록 < 실행 중 CLI → warning + next_actions `harness-team init --yes`.
기록 > 실행 중 CLI → warning(구버전 CLI init은 관리 절 퇴행 위험).
- **제약**: 새 의존성 금지. 타임스탬프(`appliedAt`)를 넣지 않는다(매 init diff 유발). init 차단은 범위 밖 —
경고만. SessionStart 훅 nudge는 범위 밖(후속 후보). src/ 수정 파일 5개 이하.

## 설계 / 접근

- `src/render-state.mjs`
- `readHarnessVersion(root)` — `<root>/package.json`의 version(semver 형식일 때만, 아니면 null).
- `loadRenderState`는 `harnessVersion`을 #113 `stack` 선례처럼 **semver 형식일 때만** 통과시킨다.
형식이 틀리거나 없으면 필드를 빼서 "기록 이전 설치"와 같게 본다.
- `src/harness.mjs` `planChanges` — renderState 구성에 `harnessVersion`(= `readHarnessVersion(ctx.root)`)을 넣는다.
init은 이 renderState를 Apply 뒤 저장하므로 `src/commands/init.mjs`는 수정이 필요 없다(저장 경로 그대로).
- `src/commands/doctor.mjs`
- `compareVersions(a, b)` — major.minor.patch 3-way(-1/0/1), 형식이 아니면 null. `isAtLeast`와 같은 파일.
- `harnessVersionReport({ applied, cli, plugin, pluginDev })` — 순수 함수. `{ line, warning, action }`.
- `checkCliDrift`의 installed_plugins.json 읽기를 `readInstalledHarnessVersion(env)`로 떼어 재사용한다.
- 출력: check `harness version`(일치·unknown은 pass, 불일치는 warning) + JSON `extra.versions`
`{ project, cli, plugin }`(모르면 null).
- plugin-dev 저장소는 init 대상이 아니므로 project를 `n/a (plugin-dev repo)`로 표시하고 경고하지 않는다.
- 기록 > CLI 경고의 next_action은 기존 CLI 갱신 명령(`cliDriftAction`)을 재사용한다.

## Ontology
*이 task가 다루는 핵심 개념의 정의. "X가 정확히 뭔가?"에 답한다.*

- **applied version (`harnessVersion`)**: 이 프로젝트에 마지막으로 init(Apply까지 완료)을 실행한 하네스의
`package.json` version. render-state.json에 저장. 스키마 버전 `version`과 별개.
- **CLI version**: doctor를 실행 중인 하네스 코드(`ctx.root/package.json`)의 version. PATH CLI와 다를 수 있다
(그 불일치는 기존 `global CLI version drift`가 담당).
- **plugin version**: `installed_plugins.json`의 harness 레코드 version(`installedHarnessVersion`).
- **기록 이전 설치**: render-state에 `harnessVersion`이 없거나 형식이 틀린 설치본 — unknown, 경고 없음.
- 게이트 근거: 목표·제약·성공기준·영향 파일이 사용자 승인 계획으로 확정됨(2026-10-03 orchestrator 위임).

## Ambiguity 자가진단
*각 항목이 명확하면 체크. 3개 이상 미체크면 구현 진입 금지 — 인터뷰/브레인스토밍으로 복귀해
모호성을 제거한다. 게이트를 통과하면 그 근거를 위 Ontology 섹션에 한 줄로 남긴다.*

- [x] **Goal 명확도** (40%) — 목표가 한 문장으로 구체화되었는가?
- [x] **Constraint 명확도** (30%) — 기술/시간/범위 제약이 명시되었는가?
- [x] **Success 기준** (30%) — 완료를 어떻게 측정하는가?
- [x] **Context 명확도** (brownfield 한정) — 영향 받는 기존 코드/파일을 식별했는가?
- [x] **Ambiguity ≤ 0.2** — 위 항목 가중합 ≥ 0.8

<!-- 선택 선언. 아래 주석을 벗기면 done 가드가 검사한다.
미선언 기본값: "tests": "required" (소스가 바뀌면 테스트 파일 변경을 요구), "review": "optional",
"verify": "optional" ("required"면 검증 프레이밍 kind 마커 — -adversarial 등 — 를 요구). -->
## Done evidence
```json
{ "version": 1, "review": "required", "tests": "required" }
```

## 참고
*코드 기반 참조가 산문 설계보다 정밀하다 — 테스트 스위트·Boundary contract(JSON Schema)·
다이어그램·기존 코드 경로를 우선 링크하고, 산문은 코드로 표현 못 하는 의도만 담는다.*

- `src/render-state.mjs` `loadRenderState` — `stack` 필드 선례(#113)
- `src/commands/doctor.mjs` `isAtLeast`·`cliDriftWarning`·`installedHarnessVersion`
- 테스트: `tests/render-state.test.mjs`, `tests/doctor.test.mjs`, `tests/cli-drift.test.mjs`
Loading
Loading