CURSOR AGENT 직접 실습

하나를 바꾸고, 확인하고, 안전하게 되돌리기

훅(Hooks), 규칙(Rules), Skill을 처음 보는 사람도 프로젝트 안의 훅 파일 하나를 직접 고쳐 효과를 확인하고, 실습 설정을 끄거나 복원한 뒤, 필요한 파일만 자기 프로젝트로 옮길 수 있습니다.

먼저 필요한 것Cursor Agent · Python 3 · 실습할 프로젝트 폴더
권장 기본 과정준비 → 기록 → 수정 제한 → 직접 편집 → 복원 · 약 50분
필요한 응용만 선택커밋 30분 · 라우팅 30분 · 기록·세션 분석 16분 · Skill 8분

처음이라면 기본 과정부터

첫 기록부터 직접 수정과 복원까지 따라가 보세요. 한 가지 설정을 바꾸고, 효과를 확인하고, 다시 끄는 방법을 익힙니다.

더 궁금한 주제를 골라보세요

커밋 제한, 라우팅, 세션 분석, Skill은 필요한 것만 선택해도 됩니다. 기본 과정 뒤에는 자기 프로젝트에 설정 하나를 옮기는 안내도 준비했습니다.

진행 막대에 표시할 경로
목차 열기 · 현재 Git

용어와 전체 흐름

먼저 네 가지 부품만 구분합니다

5분

Cursor Agent는 요청을 받고 도구를 골라 실행합니다. 이 실습은 그 앞뒤에 프로젝트 파일을 연결해 동작을 기록하거나 막고, 같은 입력이 어떤 길로 실행됐는지 실제 결과 파일로 확인합니다.

규칙(Rules)

에이전트가 읽고 따르는 프로젝트 지시입니다. 행동을 유도하지만 실행 자체를 강제로 막지는 않습니다.

훅(Hooks)

도구 실행 전이나 후에 자동으로 불리는 로컬 프로그램입니다. 기록하거나 허용·거부를 반환할 수 있습니다.

Skill

사용할 때 불러오는 재사용 지시 묶음입니다. 새 에이전트도, 강한 권한도 아닙니다.

실행 경로(routing)

요청이 직접 파일 읽기로 가는지, 정해진 프로그램을 거치는지 보여 주는 순서입니다.

기록 한 줄을 읽는 법

phase=attempt는 실행 전 시도, outcome=allow는 실행 후 허용, deny는 거부, fail은 실행 실패입니다. reason은 거부 이유입니다.

원본 키트와 활성 복사본

.cursor-harness-kit/files/deny_write.py는 다시 설치할 기준 원본이고, .cursor/hooks/cursor-harness-lab-deny-write.py는 Cursor가 실제 호출하는 활성 복사본입니다. 뒤에서 활성 복사본만 직접 고칩니다.

실습 경계

모든 작업은 열린 프로젝트 안에서만 이뤄집니다. 전역 설정, 네트워크, 서브에이전트, 자동 커밋은 사용하지 않습니다. 각 고정 비교 전에는 새 Agent 대화를 열어 이전 대화의 영향을 줄입니다.

시작 전

이미 열어 둔 루트를 고정합니다

2분
  • Cursor에서 실습할 기존 프로젝트 루트를 열고 Trust 했습니다.
  • README.md는 학습자가 준비했습니다. 키트가 생성하거나 내용을 강제하지 않습니다.
  • 첫 기록·수정 제한·라우팅 실습은 Git이나 SVN 저장소가 없어도 됩니다. 저장소는 S3~S5 커밋 실습에서만 필요합니다.
  • python3가 동작합니다. 전역 Cursor 설정은 바꾸지 않습니다.

현재 터미널이 프로젝트 루트일 때 한 번 실행합니다. 새 터미널을 열면 셸 변수는 이어지지 않으므로 이 초기화를 다시 실행해야 합니다.

Terminal · 실행 위치: 이미 열린 프로젝트 루트 · 변경 파일: 없음
export PROJECT_ROOT="$PWD"
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit

명령 블록의 exportcd는 Bash 계열 문법입니다. macOS의 기본 터미널(zsh), Linux의 Bash, Windows의 Git Bash에서 사용하세요. PowerShell은 이 문법을 지원하지 않으므로 Cursor 터미널 프로필을 먼저 확인해 주세요.

실습 키트 준비

편한 준비 방법 하나를 골라주세요

8분

다운로드와 직접 만들기 중 어느 쪽을 골라도 같은 파일이 만들어집니다. 같은 이름의 파일에 다른 내용이 있으면 덮어쓰지 않고 멈춥니다. 여기서는 파일만 준비하고, Cursor 설정은 첫 실습에서 켜볼 거예요.

1

나중에 사용할 버전 관리 선택

지금은 기본값 Git으로 두어도 됩니다. 이 선택은 나중에 S3~S5 커밋 실습에서 사용할 도구를 정할 뿐, 저장소를 만들거나 검사하지 않습니다. 선택은 lab-results/vcs.txt에 기록됩니다.

버전 관리 선택
2

첫 실습에 필요한 세 곳만 확인

전체 목록은 아직 외우지 않아도 됩니다. 준비 명령이 원본에서 활성 복사본을 만들고, Cursor가 훅 목록을 읽고, 결과는 별도 폴더에 쌓입니다.

첫 실습 구조
PROJECT_ROOT/
├── .cursor-harness-kit/prepare.py       ← 준비 명령
├── .cursor/hooks.json                   ← Cursor가 읽는 훅 목록
└── lab-results/                         ← 보존되는 기록과 비교 결과
3

설치 방법 선택

실습 키트 설치 방법

파일을 받은 뒤 cursor-harness-kit.tar를 실습할 프로젝트 루트에 놓아 주세요. 아래 명령은 그 폴더에서 바로 압축을 풀고 설치합니다. 브라우저의 다운로드 폴더를 자동으로 찾지 않습니다.

터미널 · 프로젝트 루트 · 변경: cursor-harness-kit/ 및 .cursor-harness-kit/
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 -m tarfile -e cursor-harness-kit.tar . || exit
python3 cursor-harness-kit/install.py

다운로드한 cursor-harness-kit.tar를 먼저 프로젝트 루트로 옮겨 주세요. 위 명령은 그 자리에 cursor-harness-kit/을 풀고, 실행용 파일을 .cursor-harness-kit/에 설치합니다. 임시 폴더나 기본 다운로드 경로는 사용하지 않습니다.

프로젝트에 이미 cursor-harness-kit/ 폴더가 있다면 기존 내용을 보존할 수 있도록 이름을 바꿔 둔 뒤 새 압축을 풀어 주세요. 설치된 .cursor-harness-kit/와 실습 결과는 지우지 않습니다.

이전 버전 키트가 설치돼 있거나 설치 충돌이 나온다면

새 압축을 프로젝트 루트에 푼 다음 아래 명령을 실행하세요. 기존 실행용 키트 전체를 lab-results/kit-backups/kit-001/부터 순서대로 보관하고 새 버전을 설치합니다. 직접 수정한 내용과 추가 파일도 백업에 남습니다. 현재 Cursor 설정과 기존 실습 결과는 바꾸지 않습니다.

터미널 · 프로젝트 루트 · 이전 키트 백업 후 갱신
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 cursor-harness-kit/install.py --replace

갱신한 뒤에는 진행하려던 준비 명령을 다시 실행하세요. 예를 들어 첫 단계라면 python3 .cursor-harness-kit/prepare.py s1 git입니다.

선택 사항 · 전체 파일 목록과 파일별 원본 보기

두 설치 방법이 함께 사용하는 정식 파일 목록입니다. 각 원본도 아래에서 따로 펼쳐 복사할 수 있습니다.

키트 경로하는 일언제 실행효과결과

확인

  • .cursor-harness-kit/prepare.py, manage.py, files/가 있습니다.
  • 기존 프로젝트 파일과 이전 lab-results/는 바뀌지 않았습니다.
  • 아직 .cursor/hooks.json과 홈 전역 설정은 바뀌지 않았습니다.

설치 뒤 파일이 보이지 않나요?

첫 동작 기록 · S1

막지 않고 첫 요청을 기록합니다

10분

먼저 비교 기준을 만듭니다. 준비 명령은 이전 실습 훅만 바꾸고 사용자 훅과 규칙은 남긴 채 기록 훅을 활성화합니다.

실행 전과 후pre/before = 시도, post/after = 허용, failure = 실패
같게 유지고정 프롬프트 A · 학습자가 준비한 README

● 새 파일: CURRENT·활성 스크립트↻ 교체: 실습 소유 훅 항목▶ 활성: 기록 훅만

S1 준비 후 파일 구조
프로젝트/
├── README.md                         ← 기존 파일 유지
├── .cursor/
│   ├── hooks.json                    ← 이번 설정으로 변경 (사용자 훅 유지)
│   ├── hooks/
│   │   ├── cursor-harness-lab-observe.py     ← 기록 켜짐
│   │   ├── cursor-harness-lab-deny-write.py  ← 사용하지 않음
│   │   └── cursor-harness-lab-deny-commit.py ← 사용하지 않음
│   └── rules/                        ← 사용자 규칙 유지
└── lab-results/
    ├── CURRENT                       ← s1
    ├── vcs.txt                       ← 선택한 Git 또는 SVN
    ├── snapshot.py / compare.py      ← 결과 정리 도구
    ├── s1/
    │   ├── events.jsonl              ← 실행 기록
    │   └── summary.md                ← 실행 후 요약 명령으로 생성
    └── archive/                      ← 재실행 전 기록 보관
Terminal · PROJECT_ROOT · 변경: 위 S1 트리 · 커밋 없음
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 .cursor-harness-kit/prepare.py s1 git

새 Agent 대화를 열고 다음 입력을 한 글자도 바꾸지 않습니다.

Cursor Agent 입력 · 고정 프롬프트 A
README.md를 읽은 다음, 파일 끝에 아래 한 줄을 추가해 주세요. 커밋은 하지 마세요.

<!-- lab-edit -->
Terminal · PROJECT_ROOT · 변경: lab-results/s1/summary.md
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 lab-results/snapshot.py
실제 결과 파일기대 비교
s1/events.jsonl, s1/summary.mdWrite 또는 StrReplace의 allow, 거부 없음
이벤트 한 줄을 바로 해석해 봅니다

tool=Write는 선택된 도구, phase=attempt는 실행 전 시도입니다. 이어지는 phase=decisionoutcome=allow는 실행 후 허용됐다는 뜻입니다. 실행 도구가 달랐다면 아래 문제 해결에서 확인합니다.

확인

  • lab-results/s1/summary.md에서 수정 도구의 허용을 확인했습니다.
  • 채팅 답변이 아니라 실제 결과 파일로 판정했습니다.

다른 도구가 기록됐나요? · 지금 기록을 끄거나 복원하기

같은 요청 거부 · S2

실행 전에 수정 도구를 거부합니다

12분

S1과 똑같은 요청을 보내되, 이번에는 기록 훅 다음에 수정 거부 훅을 연결합니다. 사용자 훅·규칙과 S1 기록은 그대로 남습니다.

실행 전 순서preToolUse: 시도 기록 → deny-write 거부 결정
같게 유지S1과 같은 프롬프트 A
S2 준비 후 파일 구조
프로젝트/
├── README.md                         ← 기존 파일 유지
├── .cursor/
│   ├── hooks.json                    ← 이번 설정으로 변경 (사용자 훅 유지)
│   ├── hooks/
│   │   ├── cursor-harness-lab-observe.py     ← 기록 켜짐
│   │   ├── cursor-harness-lab-deny-write.py  ← 수정 차단 켜짐
│   │   └── cursor-harness-lab-deny-commit.py ← 사용하지 않음
│   └── rules/                        ← 사용자 규칙 유지
└── lab-results/
    ├── CURRENT                       ← s2
    ├── vcs.txt                       ← 선택한 Git 또는 SVN
    ├── snapshot.py / compare.py      ← 결과 정리 도구
    ├── s2/
    │   ├── events.jsonl              ← 실행 기록
    │   └── summary.md                ← 실행 후 요약 명령으로 생성
    └── archive/                      ← 재실행 전 기록 보관
Terminal · PROJECT_ROOT · 변경: 위 S2 트리 · 커밋 없음
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 .cursor-harness-kit/prepare.py s2 git

새 Agent 대화에서 같은 입력을 보냅니다.

Cursor Agent 입력 · 고정 프롬프트 A
README.md를 읽은 다음, 파일 끝에 아래 한 줄을 추가해 주세요. 커밋은 하지 마세요.

<!-- lab-edit -->
Terminal · PROJECT_ROOT · 변경: summary와 compare-s1-s2.md
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 lab-results/snapshot.py
python3 lab-results/compare.py s1 s2
도구S1S2비교
Write/StrReplace허용거부수정 제한됨
결과 파일의 뜻

outcome=deny는 실행 전 거부, reason=deny-write는 이 실습 훅이 내린 결정입니다. summary.md는 원본 events.jsonl을 읽기 쉽게 센 결과입니다.

확인

  • s2/events.jsonl, s2/summary.md, compare-s1-s2.md를 확인했습니다.
  • 수정 도구가 S1의 허용에서 S2의 거부로 바뀌었습니다.

규칙이 무시된 것과 훅 거부의 차이가 헷갈리나요? · 실습 설정 끄기

직접 편집 실습

Write는 허용하고 StrReplace는 계속 거부합니다

8분

이제 활성 훅의 작은 조건 하나를 직접 고칩니다. Agent가 어떤 도구를 고를지 기다리지 않고, 로컬 점검 프로그램이 두 요청을 똑같이 전달해 결과를 따로 기록합니다.

바꾸는 파일.cursor/hooks/cursor-harness-lab-deny-write.py 한 개
바꾸지 않는 원본.cursor-harness-kit/files/deny_write.py
직접 편집 전 구조
PROJECT_ROOT/
├── .cursor-harness-kit/files/deny_write.py       ← 기준 원본, 그대로 둠
├── .cursor/hooks/cursor-harness-lab-deny-write.py ← 직접 고칠 활성 복사본
└── lab-results/custom/probe.json                 ← 점검 뒤 새 결과

1. S2 상태를 다시 준비합니다

이 명령은 활성 복사본을 기준 원본으로 다시 씁니다. 기존 활성 복사본을 이미 고쳤다면 먼저 lab-results/archive/active-edits-NNN/에 보관합니다.

터미널 · PROJECT_ROOT · S2 기준 상태 준비
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 .cursor-harness-kit/prepare.py s2 git

2. Cursor 편집기에서 활성 복사본을 직접 고칩니다

.cursor/hooks/cursor-harness-lab-deny-write.py를 열고 아래 한 줄만 바꿔 저장합니다. StrReplace, Delete, EditNotebook은 그대로 둡니다.

바꾸기 전바꾼 뒤
{"Write", "StrReplace", "Delete", "EditNotebook"}{"StrReplace", "Delete", "EditNotebook"}

3. 모델 없이 안전하게 점검합니다

이 프로그램은 존재하지 않는 lab-probe-target.txt 경로를 훅에 입력할 뿐 파일을 만들거나 수정하지 않습니다.

터미널 · PROJECT_ROOT · 변경: lab-results/custom/probe.json
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 .cursor-harness-kit/files/probe.py
결과 필드기대값과 뜻
results.Writeallow · 방금 직접 바꾼 효과
results.StrReplacedeny · 남겨 둔 거부 조건
target_createdfalse · 실제 파일 수정 없음

확인

  • lab-results/custom/probe.json이 S1·S2 기록과 분리돼 있습니다.
  • 활성 복사본과 원본 키트의 차이를 설명할 수 있습니다.

준비 뒤 직접 수정이 사라졌나요? · 아래에서 끄고 복원할 수 있습니다.

적용 · 끄기 · 복원

실습 설정을 끄고, 다시 켜보세요

7분

실습을 마쳤거나 평소 작업으로 돌아가고 싶다면 이번에 추가한 설정만 끄면 됩니다. 직접 고친 훅은 백업해 두었다가 다시 켤 수 있어요. 원래 사용하던 파일과 설정, 실험 기록은 남겨둡니다.

관리 대상과 보존 대상
.cursor/hooks/cursor-harness-lab-*.py          ← 실습 소유: 끄기 대상
.cursor/rules/cursor-harness-lab-*.mdc        ← 실습 소유: 끄기 대상
.cursor/skills/lab-document-review/SKILL.md   ← 실습 소유: 끄기 대상
.cursor/hooks.json의 다른 키와 명령            ← 사용자 소유: 보존
lab-results/** 및 프로젝트 파일                ← 항상 보존

현재 상태 확인

터미널 · PROJECT_ROOT · 변경 없음
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 .cursor-harness-kit/manage.py status

실습 설정 끄기

이 명령은 활성 훅 등록을 제거하기 전에 현재 실습 파일과 항목을 lab-results/management-backups/disable-NNN/에 보관합니다. 직접 고친 훅도 이 백업에 남습니다.

터미널 · PROJECT_ROOT · 실습 항목만 비활성화
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 .cursor-harness-kit/manage.py disable
python3 .cursor-harness-kit/manage.py status

두 번째 출력은 enabled: falseregistered_hook_entries: 0을 보여야 합니다.

끄기 직전 상태 복원

복원은 백업 뒤 추가한 사용자 훅과 다른 JSON 키를 유지합니다. 같은 실습 경로 또는 명령에 다른 내용이 있으면 덮어쓰지 않고 복원 충돌로 멈춥니다.

터미널 · PROJECT_ROOT · 최근 미복원 백업 사용
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 .cursor-harness-kit/manage.py restore
기준 원본으로 되돌리고 싶다면

복원은 끄기 직전의 직접 편집본을 돌려놓습니다. 기준 원본으로 바꾸려면 S2 준비 명령을 다시 실행하세요. 그 명령은 직접 편집본을 lab-results/archive/active-edits-NNN/에 보관한 뒤 활성 복사본을 덮어씁니다.

핵심 경로 완료

  • 훅 하나를 직접 고치고 별도 결과로 확인했습니다.
  • manage.py disable 뒤 실습 훅이 더는 등록되지 않음을 확인했습니다.
  • 백업 위치와 충돌을 덮어쓰지 않는 복원 방식을 확인했습니다.
이제 하나를 골라보세요

지금 배운 것을 써보고 싶다면 내 프로젝트에 필요한 설정만 옮기기로 넘어가세요. 결과가 예상과 달랐다면 세션 기록으로 원인 찾기를, 더 연습하고 싶다면 아래 응용 실습을 선택하면 됩니다. 모든 응용을 끝내야 적용할 수 있는 것은 아니에요.

여기부터 선택 실습입니다. 커밋 동작, 기록 읽기, 같은 입력의 실행 경로, Skill 중 필요한 부분만 골라도 됩니다.

커밋 기록 · S3

설정 없이 VCS 커밋 관찰

8분

먼저 차단 없이 커밋을 요청해 볼게요. 준비 명령이 commit-input.txt에 이번 실험용 변경을 만들어주므로 따로 파일을 고칠 필요가 없습니다. 실제 커밋은 뒤에서 에이전트에게 요청합니다.

저장소가 필요한 것은 여기부터입니다

S1·S2와 라우팅 실습은 일반 폴더에서 할 수 있지만, S3~S5는 실제 커밋을 비교하므로 Git 저장소 또는 SVN 작업 복사본이 필요합니다. 아직 준비하지 않았다면 이 응용을 건너뛰어도 됩니다.

커밋 실습 전 작업 공간 확인하기

아래 결과가 true이면 됩니다. .git이 파일인 작업 공간이나 저장소의 하위 폴더도 확인할 수 있습니다.

터미널 · 프로젝트 루트 · 조회만 수행
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
git rev-parse --is-inside-work-tree

아직 저장소가 아니라면 기존 Git 프로젝트를 열거나, 현재 폴더를 새 Git 저장소로 사용할 때만 아래 명령을 실행하세요. 원격 저장소나 GitHub 연결은 필요하지 않습니다.

터미널 · 선택 사항 · 현재 프로젝트에 .git 생성
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
git init
실행 전과 후beforeShellExecution에서 시도 → afterShellExecution에서 허용
활성 훅기록만 · 선택한 버전 관리 1개
S3 준비 후 파일 구조
프로젝트/
├── README.md                         ← 기존 파일 유지
├── .cursor/
│   ├── hooks.json                    ← 이번 설정으로 변경 (사용자 훅 유지)
│   ├── hooks/
│   │   ├── cursor-harness-lab-observe.py     ← 기록 켜짐
│   │   ├── cursor-harness-lab-deny-write.py  ← 사용하지 않음
│   │   └── cursor-harness-lab-deny-commit.py ← 사용하지 않음
│   └── rules/                        ← 사용자 규칙 유지
└── lab-results/
    ├── CURRENT                       ← s3
    ├── vcs.txt                       ← 선택한 Git 또는 SVN
    ├── snapshot.py / compare.py      ← 결과 정리 도구
    ├── commit-input.txt              ← 이번 커밋 실험용 변경
    ├── s3/
    │   ├── events.jsonl              ← 실행 기록
    │   └── summary.md                ← 실행 후 요약 명령으로 생성
    └── archive/                      ← 재실행 전 기록 보관
Terminal · PROJECT_ROOT · 변경: 위 S3 트리 · 로컬 Git만
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 .cursor-harness-kit/prepare.py s3 git

새 Agent 대화에서 선택한 고정 프롬프트 B를 보냅니다.

Cursor Agent 입력 · Git
현재 워크스페이스의 변경사항을 로컬 git으로만 커밋하세요. 원격 저장소는 사용하지 마세요. push 하지 마세요. 커밋 메시지는 정확히 다음을 사용하세요: lab: scenario commit
Terminal · PROJECT_ROOT · 변경: s3/summary.md
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 lab-results/snapshot.py
실제 결과 파일기대 동작S4와 비교할 기준선
s3/events.jsonl, s3/summary.md선택한 VCS commit의 attempt와 allow정책 deny가 없음

확인

  • s3/events.jsonls3/summary.md에서 커밋 시도와 허용을 확인했습니다.
  • commit-input.txt 외의 학습자 파일은 준비가 바꾸지 않았습니다.

커밋 기록이 없나요? · 실습 훅 끄기

커밋 거부 · S4

실행 전에 커밋만 거부합니다

12분

준비 명령이 비교용 변경을 만들고 커밋 거부 훅을 연결합니다. 상태와 차이 조회는 허용하고 커밋만 거부되는지 확인합니다.

실행 전 순서시도 기록 → deny-commit 거부 결정
같게 유지S3과 같은 프롬프트 B
S4 준비 후 파일 구조
프로젝트/
├── README.md                         ← 기존 파일 유지
├── .cursor/
│   ├── hooks.json                    ← 이번 설정으로 변경 (사용자 훅 유지)
│   ├── hooks/
│   │   ├── cursor-harness-lab-observe.py     ← 기록 켜짐
│   │   ├── cursor-harness-lab-deny-write.py  ← 사용하지 않음
│   │   └── cursor-harness-lab-deny-commit.py ← 커밋 차단 켜짐
│   └── rules/                        ← 사용자 규칙 유지
└── lab-results/
    ├── CURRENT                       ← s4
    ├── vcs.txt                       ← 선택한 Git 또는 SVN
    ├── snapshot.py / compare.py      ← 결과 정리 도구
    ├── commit-input.txt              ← 이번 커밋 실험용 변경
    ├── s4/
    │   ├── events.jsonl              ← 실행 기록
    │   └── summary.md                ← 실행 후 요약 명령으로 생성
    └── archive/                      ← 재실행 전 기록 보관
Terminal · PROJECT_ROOT · 변경: 위 S4 트리 · 커밋 없음
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 .cursor-harness-kit/prepare.py s4 git

새 Agent 대화에서 S3과 같은 VCS별 입력을 보냅니다.

Cursor Agent 입력 · Git
현재 워크스페이스의 변경사항을 로컬 git으로만 커밋하세요. 원격 저장소는 사용하지 마세요. push 하지 마세요. 커밋 메시지는 정확히 다음을 사용하세요: lab: scenario commit
Terminal · PROJECT_ROOT · 변경: summary와 compare-s3-s4.md
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 lab-results/snapshot.py
python3 lab-results/compare.py s3 s4
명령s3s4비교
commitallowdeny제한됨
status/diffallow/없음allow/없음조회 허용

확인

  • s4/events.jsonl, s4/summary.md, compare-s3-s4.md에서 커밋 거부와 reason=deny-commit을 확인했습니다.
선택 연습 · 고정 비교를 마친 뒤

추가 또는 메시지 조건을 직접 설계하고 별도 결과 이름을 쓰세요. 본편 프롬프트 B는 사용하지 않습니다.

훅 오류가 났나요? · 실습 훅 끄기

규칙과 훅 대조 · S5

글로 된 규칙과 실행 거부를 구분합니다

10분

커밋 거부 훅 대신 “커밋하지 마세요”라는 규칙(Rule)만 둡니다. 기존 사용자 규칙은 남기고 비교용 변경을 새로 만듭니다.

실행 전과 후기록만 · 거부 결정 없음
규칙(Rule)지시하지만 강제로 막지는 않음
S5 준비 후 파일 구조
프로젝트/
├── README.md                         ← 기존 파일 유지
├── .cursor/
│   ├── hooks.json                    ← 이번 설정으로 변경 (사용자 훅 유지)
│   ├── hooks/
│   │   ├── cursor-harness-lab-observe.py     ← 기록 켜짐
│   │   ├── cursor-harness-lab-deny-write.py  ← 사용하지 않음
│   │   └── cursor-harness-lab-deny-commit.py ← 사용하지 않음
│   └── rules/                        ← 사용자 규칙 유지 + 실습 커밋 금지 규칙 추가
└── lab-results/
    ├── CURRENT                       ← s5
    ├── vcs.txt                       ← 선택한 Git 또는 SVN
    ├── snapshot.py / compare.py      ← 결과 정리 도구
    ├── commit-input.txt              ← 이번 커밋 실험용 변경
    ├── s5/
    │   ├── events.jsonl              ← 실행 기록
    │   └── summary.md                ← 실행 후 요약 명령으로 생성
    └── archive/                      ← 재실행 전 기록 보관
Terminal · PROJECT_ROOT · 변경: 위 S5 트리 · 커밋 없음
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 .cursor-harness-kit/prepare.py s5 git

새 Agent 대화에서 같은 VCS별 프롬프트 B를 보냅니다.

Cursor Agent 입력 · Git
현재 워크스페이스의 변경사항을 로컬 git으로만 커밋하세요. 원격 저장소는 사용하지 마세요. push 하지 마세요. 커밋 메시지는 정확히 다음을 사용하세요: lab: scenario commit
Terminal · PROJECT_ROOT · 변경: summary와 compare-s5-s4.md
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 lab-results/snapshot.py
python3 lab-results/compare.py s5 s4
명령S5 규칙만S4 훅비교
커밋허용 또는 시도 없음거부S4만 강제 거부
S5의 통과 기준은 ‘커밋이 반드시 실패하는 것’이 아닙니다. compare-s5-s4.md에서 S4만 거부가 보장되는지를 봅니다. S5가 허용이면 규칙만으로는 부족하다는 뜻입니다.

확인

  • s5/events.jsonl, s5/summary.md, compare-s5-s4.md가 실제 결과입니다.
  • S5에는 deny-commit 이유가 없고 S4에는 있습니다.
선택 연습 · 고정 비교를 마친 뒤

규칙 문구와 직접 만든 입력을 바꿔 별도 결과로 비교하세요.

규칙이 무시된 것처럼 보이나요? · 실습 규칙 끄기

기록 깊게 읽기 · S6

기존 실행 기록만 읽습니다

8분

S6에는 준비 명령이 없습니다. CURRENT, 훅, 규칙, 결과 폴더를 바꾸거나 새 기록을 만들지 않고 S1~S5 결과만 읽습니다.

S6에서 읽기만 하는 트리
lab-results/s2/events.jsonl              = 읽기 전용
lab-results/s4/events.jsonl              = 읽기 전용
lab-results/compare-*.md                 = 읽기 전용
CURRENT / .cursor/**                     = 변경 없음
Terminal · PROJECT_ROOT · 변경 파일: 없음
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 -c 'import json; p="lab-results/s2/events.jsonl"; [print(line, end="") for line in open(p, encoding="utf-8") if json.loads(line).get("outcome") == "deny"]'
필드비교에서 뜻
phase / outcome실행 전 시도 또는 허용·거부·실패 결정
tool / command도구와 셸 명령
reasondeny-write 또는 deny-commit

확인

  • S2 또는 S4 기존 JSONL에서 거부와 이유를 찾았습니다.
  • S6용 디렉터리나 기록이 생기지 않았습니다.

다른 시나리오 기록이 보이나요? · 현재 실습 설정 끄기

선택 학습 · 기록으로 원인 찾기

예상과 다르게 움직였다면, 세션을 따라가 보세요

8분

마지막 답변만 봐서는 왜 그런 결과가 나왔는지 알기 어렵습니다. 요청부터 도구 호출, 실행 결과까지 순서대로 읽으면 처음 예상에서 벗어난 지점을 찾을 수 있어요. 여기서는 기록을 읽기만 하고 설정이나 파일 내용은 바꾸지 않습니다.

기록무엇을 알 수 있나요?무엇까지는 알 수 없나요?
세션 기록내 요청, 에이전트 답변, 표시된 도구 요청과 결과의 순서대화를 일부만 복사했다면 빠진 도구 호출이 있을 수 있습니다.
events.jsonl훅에 전달된 도구 시도와 허용·거부·실패전체 대화는 아닙니다. allow만으로 파일의 최종 내용까지 증명하지는 못합니다.
결과 파일과 변경 내역실제로 생성된 보고서나 파일 변경결과만으로 어떤 요청과 도구를 거쳤는지 알 수는 없습니다.
1

짧은 예제로 읽는 순서를 익혀보세요

준비 파일에 session-example.mdsession-events.jsonl을 함께 넣었습니다. 둘은 이 설명을 위해 만든 예제이며, 실제 Cursor 내보내기 형식이나 여러분의 실행 결과가 아닙니다.

예제의 실행 순서 · 실행할 명령이 아닙니다
1. 사용자: README 끝에 한 줄을 추가해 주세요.
2. 에이전트: Write로 수정 요청
3. 훅: Write 거부 (deny-write)
4. 에이전트: Shell로 같은 파일 수정 요청
5. 도구 결과: 셸 명령 종료 코드 0
6. 에이전트: 수정했다고 답변

질문: Write를 막았는데 왜 수정했다는 답변이 나왔을까요? 3번에서 멈추지 말고 4번까지 읽어보세요. 수정 도구는 막혔지만 Shell이라는 다른 경로로 다시 시도했습니다. 실제 파일이 바뀌었는지는 파일 내용이나 변경 내역도 함께 봐야 합니다.

Terminal · 프로젝트 루트 · 파일 변경 없음
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 -c 'from pathlib import Path; p=Path(".cursor-harness-kit/files/session-example.md"); print("\n".join(f"{i}: {line}" for i,line in enumerate(p.read_text(encoding="utf-8").splitlines(),1)))'
예제의 훅 기록도 함께 보기

아래 명령은 예제 기록을 읽어 도구와 결정을 순서대로 보여줍니다. 실제 실습 기록과 섞어 세지 않습니다.

Terminal · 프로젝트 루트 · 파일 변경 없음
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 -c 'import json; from pathlib import Path; p=Path(".cursor-harness-kit/files/session-events.jsonl"); rows=[json.loads(line) for line in p.read_text(encoding="utf-8").splitlines() if line.strip()]; print("\n".join("%d: %s / %s / %s / %s" % (i,r["tool"],r["phase"],r["outcome"],r["reason"]) for i,r in enumerate(rows,1)))'
2

이번에 실행한 대화 하나를 로컬 파일로 남기세요

Cursor에서 S2 또는 R2를 진행한 대화를 열고 문서 이름이나 요청 문장을 검색해 보세요. 공식 대화 검색 안내에서는 열린 대화 안에서 Mac은 Cmd+F, Windows/Linux는 Ctrl+F로 찾는 방법을 설명합니다.

해당 요청, 에이전트 답변, 펼쳐진 도구 요청·결과를 복사해 프로젝트의 lab-results/session-review/session.md에 저장하세요. 복사되지 않는 도구 결과는 따로 붙여넣고, 빠진 부분은 “생략”이라고 표시합니다. 로컬 내보내기 기능이 있는 버전에서는 그 파일을 사용해도 됩니다. 공유 링크를 만들거나 기록을 이 웹페이지에 올릴 필요는 없습니다.

기록에 토큰이나 개인 정보가 포함돼 있으면 분석에 필요한 부분만 남겨 주세요. Cursor 내부 저장소의 파일명과 구조는 버전마다 달라질 수 있으므로, 이 실습에서는 원본 데이터베이스를 수정하지 않습니다.

Terminal · 프로젝트 루트 · 기록을 저장할 폴더만 생성
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
mkdir -p lab-results/session-review
분석할 파일의 위치
프로젝트/
├── .cursor-harness-kit/files/
│   ├── session-example.md     ← 설명용 대화 예제
│   ├── session-events.jsonl   ← 예제와 대응하는 훅 기록
│   └── session-note.md        ← 원인을 정리할 빈 양식
└── lab-results/
    ├── s2/events.jsonl        ← 실제 S2 실행의 훅 기록
    └── session-review/
        ├── session.md        ← 직접 저장한 이번 대화
        └── notes.md          ← 빈 양식을 복사해 작성할 분석 메모

R2를 살펴본다면 s2/events.jsonl 대신 r2/events.jsonlr2/route-summary.md를 나란히 열면 됩니다. 로그가 비어 있다면 “아무 일도 없었다”가 아니라 “기록으로 확인할 수 없다”로 구분해 주세요.

3

처음 달라진 지점 하나만 찾아보세요

  1. 요청: 무엇을 부탁했고, 무엇은 하지 말라고 했나요?
  2. 첫 도구: 예상했던 도구나 프로그램을 선택했나요?
  3. 도구 결과: 허용·거부·실패 중 무엇인가요? 답변이 아니라 기록의 줄 번호를 적어보세요.
  4. 다음 행동: 거부 뒤 멈췄나요, 다른 도구로 다시 시도했나요?
  5. 확인할 변경: 지침, 훅 설정, 허용 도구 중 무엇 하나를 바꿔 다시 실행하면 원인을 확인할 수 있을까요?

session-note.md의 내용을 새 notes.md로 복사해 “확인한 사실 / 아직 모르는 것 / 다음에 바꿀 한 가지”를 적어보세요. 한 번에 여러 설정을 바꾸면 무엇이 영향을 줬는지 다시 알기 어려워집니다.

에이전트와 함께 분석하고 싶다면

엄격한 R3 도구 제한은 분석 파일 읽기도 막습니다. 먼저 위의 실습 설정 해제 절차를 진행하고 새 대화에서 사용하세요. 분석 결과의 줄 번호가 원본에 실제로 있는지는 직접 확인합니다.

Cursor Agent 입력 · 분석용 요청 예시
lab-results/session-review/session.md와 lab-results/s2/events.jsonl을 읽고, 요청 → 도구 호출 → 도구 결과 → 다음 행동 순서로 정리해 주세요.
예상과 처음 달라진 지점을 각 파일의 줄 번호와 함께 알려주세요. 직접 확인한 사실과 추측을 구분하고, 기록이 빠져 있으면 판단할 수 없다고 표시해 주세요.
파일과 설정은 수정하지 마세요.

여기까지 확인했나요?

  • session.md의 어느 요청과 어느 도구 결과를 살폈는지 표시했습니다.
  • notes.md에 세션과 실제 훅 기록의 줄 번호를 각각 적었습니다.
  • 확인된 사실과 추측을 구분하고, 다음 실험에서 바꿀 설정 한 가지만 골랐습니다.

직접 검토 · R1

문서를 직접 읽고 검토하기

8분

먼저 에이전트가 문서를 직접 읽고 검토하게 해볼게요. 이 단계에서는 도구 사용을 기록만 하고, 별도 검사 프로그램을 쓰라는 지시는 넣지 않습니다. 다음 단계와 비교할 첫 번째 실행 경로를 남기는 과정입니다.

같게 유지docs/guide.md의 원본 바이트 · 아래 프롬프트
이번 실행 경로Agent → Read 도구 → 문서 → 답변
R1 준비 후 파일 구조와 역할
프로젝트/
├── docs/guide.md                     ← 결함 3종이 있는 고정 입력, 준비 전 충돌 검사
├── .cursor/hooks.json                ← 기록 훅만 활성
├── .cursor/rules/                    ← 경로 지시 없음, 사용자 규칙 보존
└── lab-results/
    ├── review_doc.py                 ← R1에서는 실행하지 않는 비교용 검토 프로그램
    ├── route_summary.py              ← 관찰 결과와 기대 경로 비교
    └── r1/
        ├── document-before.sha256     ← 실행 전 원본 문서 지문
        ├── events.jsonl              ← 직접 Read 근거
        └── route-summary.{json,md}    ← 실행 뒤 생성

Git 또는 SVN 중 위에서 고른 하나만 실행합니다. 준비기는 기존 docs/guide.md가 있으면 어떤 파일도 쓰기 전에 중단하며 덮어쓰지 않습니다.

Terminal · PROJECT_ROOT · R1 독립 준비
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 .cursor-harness-kit/prepare.py r1 git

새 Agent 대화에서 아래 문장만 보냅니다. 커밋·네트워크·서브에이전트는 사용하지 않습니다.

Cursor Agent 입력 · R1~R3 고정 프롬프트
docs/guide.md를 검토하고 문제점을 알려주세요. 파일은 수정하지 마세요.
기대 실행 경로
고정 프롬프트 ──▶ Agent ──Read docs/guide.md──▶ 답변
                           └─ 프로그램 실행 없음
터미널 · 실제 근거와 원본 문서 변경 확인
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 lab-results/route_summary.py r1
원본 전체 보기

준비의 파일별 펼침에서 files/guide.md, files/review_doc.py, files/route_summary.py 전체를 읽을 수 있습니다. R1 판정은 채팅 주장이 아니라 events.jsonl과 원본 문서 지문에서 나옵니다.

확인

  • r1/route-summary.jsondirect_document_readtrue이고 program_shell_executionfalse입니다.
  • document-before.sha256document-after.sha256가 같아 원본 문서가 바뀌지 않았습니다.
  • 고정 문서에서 필수 제목 누락, 중복 제목, 빈 절을 사람이 확인했습니다.

직접 읽기 기록이 없나요? · 실습 훅 끄기

프로그램 경로 지시 · R2

검사 프로그램을 먼저 거치게 하기

10분

이번에는 문서와 요청을 그대로 두고, 검사 프로그램을 먼저 실행하라는 규칙만 추가합니다. 에이전트가 직접 판단하는 대신 프로그램의 결과를 읽고 설명하는지 살펴보세요. 규칙을 따르지 않고 직접 문서를 읽었다면 그것도 결과에 표시됩니다. 지침만으로 실행 경로가 바뀌는지 확인하는 실험이에요.

같게 유지R1과 같은 문서 · 같은 프롬프트
이번 실행 경로규칙으로 지시 · 제한 훅 없음
R2 준비 후 파일 구조와 역할
프로젝트/
├── docs/guide.md                                  ← R1과 바이트가 같은 고정 입력
├── .cursor/
│   ├── hooks.json                                 ← 기록 훅만 활성
│   └── rules/cursor-harness-lab-review-route.mdc  ← 정확한 명령 실행 후 JSON 읽기 지시
└── lab-results/r2/
    ├── document-before.sha256
    ├── events.jsonl                               ← Read와 Shell 경로를 따로 기록
    ├── review-report.json                         ← review_doc.py가 만든 결과와 실행 영수증
    └── route-summary.{json,md}                    ← 기대 경로와 실제 경로 비교
Terminal · PROJECT_ROOT · R2 독립 준비
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 .cursor-harness-kit/prepare.py r2 git

새 Agent 대화에서 R1과 완전히 같은 입력을 보냅니다.

Cursor Agent 입력 · R1~R3 고정 프롬프트
docs/guide.md를 검토하고 문제점을 알려주세요. 파일은 수정하지 마세요.
기대 실행 경로
고정 프롬프트 ──▶ Rule ──▶ Shell: python3 lab-results/review_doc.py docs/guide.md
                              └─▶ Read lab-results/r2/review-report.json ──▶ 답변
직접 docs/guide.md 읽기 ──▶ 허용되지만 instruction-noncompliance로 표시
Terminal · 실제 근거와 기대 경로 비교
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 lab-results/route_summary.py r2
관찰 결과요약의 판정
정확한 Shell 실행 + 프로그램 보고서 + 보고서 Read, 직접 문서 Read 없음route-matched
직접 문서 Read, 명령 누락, 프로그램 보고서 누락 중 하나instruction-noncompliance
프로그램 근거와 원본

review-report.jsonfindingsroute_receipt는 공개된 files/review_doc.py가 씁니다. 준비에서 표준 라이브러리만 쓰는 프로그램 전체를 읽을 수 있습니다. 채팅이나 별도 파일의 “실행했다”는 주장은 근거로 받지 않습니다.

확인

  • r2/route-summary.json에서 셸 실행, 프로그램 보고서, 보고서 읽기가 각각 구분됩니다.
  • 규칙을 따르지 않았다면 result=instruction-noncompliance이며 이것도 실제 관찰 결과입니다.
  • 세 발견 항목과 실행 영수증, 원본 문서 변경 없음까지 확인했습니다.

규칙과 거부가 헷갈리나요? · 실습 규칙과 훅 끄기

프로그램 경로 강제 · R3

다른 도구 경로는 막아보기

12분

이번에는 같은 규칙에 도구 제한을 더합니다. 검사 프로그램 실행과 그 결과 파일 읽기만 허용하고, 문서를 직접 읽거나 검색·수정하는 시도는 막아요. “이 경로로 해주세요”라고 요청하는 것과 다른 경로를 실제로 차단하는 것이 어떻게 다른지 비교해 보세요.

같게 유지R1·R2와 같은 문서·프롬프트, R2와 같은 규칙
이번 실행 전 제한preToolUse + beforeShellExecution
R3 준비 후 파일 구조와 역할
프로젝트/
├── docs/guide.md                                  ← 직접 Read/search/glob 차단
├── .cursor/
│   ├── hooks.json                                 ← 기록 다음 route-policy, failClosed=true
│   ├── hooks/cursor-harness-lab-route-policy.py   ← 정확한 명령·보고서만 허용
│   └── rules/cursor-harness-lab-review-route.mdc  ← R2와 같은 실행 지시
└── lab-results/r3/
    ├── events.jsonl                               ← allow/deny와 세부 이유
    ├── review-report.json                         ← 허용된 프로그램만 만드는 결과
    ├── document-{before,after}.sha256
    └── route-summary.{json,md}
Terminal · PROJECT_ROOT · R3 독립 준비
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 .cursor-harness-kit/prepare.py r3 git

새 Agent 대화에서 다시 같은 입력만 보냅니다.

Cursor Agent 입력 · R1~R3 고정 프롬프트
docs/guide.md를 검토하고 문제점을 알려주세요. 파일은 수정하지 마세요.
강제되는 실행 경로
                         ┌─ Read/search/glob docs ── deny + 정책 로그
고정 프롬프트 ──▶ Agent ├─ 다른 Shell·체인·리다이렉션 ── deny + 정책 로그
                         └─ 정확한 review_doc 명령 ── allow
                              └─ 정확한 r3 보고서 Read ── allow ──▶ 답변

Agent 실행 뒤 아래 자체 점검은 금지된 직접 Read 요청을 정책 스크립트에 한 번 전달합니다. 정책이 직접 남긴 deny라서 에이전트가 만든 주장을 대신 받지 않습니다. 이어서 경로 요약을 만듭니다.

Terminal · 정책 deny 자체 점검 + 실제 경로 요약
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 -c 'import json,subprocess; payload={"workspace_roots":[],"hook_event_name":"preToolUse","tool_name":"Read","tool_input":{"file_path":"docs/guide.md"}}; subprocess.run(["python3",".cursor/hooks/cursor-harness-lab-route-policy.py"],input=json.dumps(payload),text=True,check=True)'
python3 lab-results/route_summary.py r3
이 제한의 경계

이것은 정해진 랩에서 Cursor 도구 경로를 제한하는 연습이며 OS 샌드박스나 모든 가능한 도구에 대한 보장이 아닙니다. 기존 사용자 훅은 제거하지 않으므로 정확한 프로그램 명령도 사용자 훅의 영향을 받을 수 있습니다. 정책 오류는 failClosed: true로 닫힙니다.

전체 정책 원본

준비에서 files/route_policy.py 전문을 확인하세요. file_pathpath를 프로젝트 절대 경로로 맞춘 뒤, 정확한 review-report.json 읽기와 정확한 프로그램 명령 외에는 거부합니다. 명령 연결, 출력 전환, 인터프리터 조각, cat/grep류와 쓰기·삭제·편집 도구는 허용하지 않습니다.

확인

  • r3/route-summary.json에서 정확한 프로그램 셸 실행과 프로그램 보고서가 구분되어 있습니다.
  • events.jsonl에 자체 점검의 outcome=deny, reason=route-policy가 있고 정확한 명령의 허용과 따로 집계됩니다.
  • 원본 문서가 바뀌지 않았고 보고서의 발견 항목은 R2 프로그램 결과와 같습니다.

경로 훅이 실패했나요? · 엄격한 R3 설정 끄기

선택 · 문서 검토 Skill

필요할 때만 검토 절차를 불러옵니다

8분

프로젝트 Skill은 재사용 지시입니다. 새 에이전트나 강제 권한이 아니며, disable-model-invocation: true라서 사용자가 슬래시 명령을 직접 입력해야 시작됩니다.

먼저 필요한 상태R2 또는 R3 준비 완료 · docs/guide.md 존재
활성 파일.cursor/skills/lab-document-review/SKILL.md
터미널 · PROJECT_ROOT · R2와 Skill 준비
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 .cursor-harness-kit/prepare.py r2 git
Skill이 사용하는 기존 흐름
/lab-document-review
  └─ python3 lab-results/review_doc.py docs/guide.md
      └─ lab-results/<r2|r3>/review-report.json

R2 또는 R3를 준비하면 정식 목록의 Skill 원본이 활성 위치에 바이트 그대로 복사됩니다. 소스는 준비의 전체 파일 목록에서 언제든 확인할 수 있습니다.

Cursor Agent 입력 · 사용자가 직접 호출
/lab-document-review
실제 근거확인할 값
review-report.jsonroute_receipt.producercursor-harness-review-doc
findings[].codemissing-required-heading, duplicate-heading, empty-section
공식 동작 범위

프로젝트 Skill 위치와 슬래시 호출은 Cursor Skills 문서를 따릅니다. 전역 Skill 설치나 네트워크 호출은 하지 않습니다.

Skill이 자동으로 실행되지 않나요? · Skill까지 포함해 실습 설정 끄기

내 프로젝트에 적용

원하는 동작 하나만 옮깁니다

10분

예시는 파일 수정 거부 하나입니다. 엄격한 R3 전체 설정은 일상 프로젝트에 그대로 복사하지 않습니다. 먼저 실습에서 S2 준비를 다시 실행해 기준 원본 상태를 만든 뒤 활성 스크립트 하나만 가져갑니다.

1. 옮길 파일 한 개

실습 프로젝트의 .cursor/hooks/cursor-harness-lab-deny-write.py 내용을 새 프로젝트의 같은 경로에 저장합니다. .cursor-harness-kit/, lab-results/, R3 경로 정책은 복사하지 않습니다.

2. 기존 hooks.json에 항목 하나 합치기

파일 전체를 바꾸지 말고 기존 키와 훅을 남긴 채 preToolUse 배열에 아래 실습 항목만 추가합니다.

추가 전 예시추가 뒤 예시
{
  "version": 1,
  "owner": "my-project",
  "hooks": {
    "preToolUse": [
      {"command": "python3 user-hook.py",
       "failClosed": false}
    ]
  }
}
{
  "version": 1,
  "owner": "my-project",
  "hooks": {
    "preToolUse": [
      {"command": "python3 user-hook.py",
       "failClosed": false},
      {"command": "python3 .cursor/hooks/cursor-harness-lab-deny-write.py",
       "failClosed": true}
    ]
  }
}

3. 한 번 확인하고 끄기

아래 로컬 점검은 실제 파일을 만들지 않고 활성 훅에 Write와 Read를 한 번씩 전달합니다. Write deny, Read allow가 나와야 합니다.

터미널 · 새 PROJECT_ROOT · 변경 파일 없음
cd "${PROJECT_ROOT:?먼저 프로젝트 경로를 설정해 주세요}" || exit
python3 -c 'import json,subprocess; p=".cursor/hooks/cursor-harness-lab-deny-write.py"; base={"workspace_roots":[],"hook_event_name":"preToolUse"}; [(lambda r: print(t, json.loads(r.stdout)["permission"]))(subprocess.run(["python3",p],input=json.dumps({**base,"tool_name":t,"tool_input":{"file_path":"hook-check.txt"}}),text=True,capture_output=True,check=True)) for t in ("Write","Read")]'

끄려면 방금 추가한 정확한 명령의 항목 하나만 hooks.json에서 제거합니다. 다른 훅과 스크립트는 건드리지 않습니다.

버전 관리 선택은 그대로

커밋 실습을 골랐다면 Git은 로컬 저장소만, SVN은 기존 작업 복사본만 사용합니다. 원격 사용은 필요하지 않습니다.

문제 해결

증상에서 바로 확인할 파일로 갑니다

이벤트가 없음python3 .cursor-harness-kit/manage.py status에서 enabled를 보고, .cursor/hooks.json에 실습 명령이 등록됐는지 확인합니다. 기대 파일은 lab-results/<CURRENT>/events.jsonl입니다.
CURRENT 또는 루트가 다름PROJECT_ROOT를 열린 프로젝트 루트로 다시 설정하고 lab-results/CURRENT가 실행할 시나리오인지 확인한 뒤 해당 준비 명령을 다시 실행합니다.
훅 스크립트 오류터미널에서 해당 준비 명령을 다시 실행합니다. 직접 편집본은 lab-results/archive/active-edits-NNN/에 남고 활성 파일은 기준 원본으로 복구됩니다.
Agent가 다른 도구를 고름events.jsonltool을 실제 결과로 인정합니다. 직접 편집 확인은 모델 선택에 기대지 말고 files/probe.py를 실행합니다.
규칙이 무시됨 / 훅이 거부함규칙은 지시라서 무시될 수 있습니다. 훅 거부는 outcome=denyreason을 남깁니다. S5와 S4 결과를 대조합니다.
준비 뒤 직접 수정이 사라짐prepare.py s2 <git|svn>는 활성 파일을 다시 씁니다. 보관본은 lab-results/archive/active-edits-NNN/.cursor/hooks/에서 찾습니다.

마무리

필요한 동작만 남기고 끝냅니다

하려는 일담당 파일강제로 막는가
실행 전후 기록cursor-harness-lab-observe.py아니요
파일 수정 거부cursor-harness-lab-deny-write.py
커밋 거부cursor-harness-lab-deny-commit.py
커밋하지 말라는 지시cursor-harness-lab-no-commit.mdc아니요
문서 검토 절차 재사용lab-document-review/SKILL.md아니요
정해진 검토 경로 강제cursor-harness-lab-route-policy.py예 · 실습 범위만

규칙을 따르지 않은 결과는 관찰 대상이고, 실제 거부는 훅이 담당합니다.

끝내기 전 확인

  • 하나의 동작을 직접 바꾸고 probe.json 또는 해당 결과 파일로 확인했습니다.
  • 자기 프로젝트에는 원하는 동작의 스크립트와 최소 훅 항목만 옮겼습니다.
  • manage.py disable 뒤 실습 훅 등록이 0인지 확인했거나, 필요한 설정만 의도적으로 남겼습니다.
  • 복원 백업은 lab-results/management-backups/에 있고 기록과 사용자 파일은 그대로입니다.

R3는 정의된 Cursor 도구 경로를 제한하는 학습용 설정이지 운영체제 샌드박스가 아닙니다. 프로그램 보고서도 임의의 파일 변경 전체를 막는 보안 장치는 아닙니다.