실제로 확인한 범위
프롬프트를 보내기 전에 경계 정하기
- 01
확인된 런타임에서 시작
0.1.3-alpha.1과 고정 소스 커밋을 사용하는 Alpha 빠른 시작을 따르세요. Settings → Models에서 설정한 모델을 선택합니다. 인증 정보는 공급자 설정에 두고 프롬프트나 테스트 파일에 넣지 않습니다.
- 02
프로젝트와 런타임 분리
연습은 별도 디렉터리에 두고 Web UI에서 해당 경로를 선택하세요. 공식 소스 런타임을 이 웹사이트 내부나 충돌하는 node_modules가 있는 상위 디렉터리 아래에 만들지 않습니다.
- 03
첫 작업의 범위 좁히기
실제 샌드박스·승인 설정을 확인하세요. 임시 작업 공간에서 프롬프트에 필요한 작업만 허용하고 파일 세 개의 문제를 해결하려고 플러그인이나 의존성을 늘리지 않습니다.
실패를 확인할 수 있는 작은 프로젝트 만들기
Node.js 24와 Bash 호환 터미널을 사용해 버려도 되는 새 디렉터리에서 시작하세요. 명령은 macOS/Linux의 Bash 기준이며, Windows에서는 Git Bash 또는 WSL을 사용합니다. harness-lab 디렉터리가 이미 있으면 안 됩니다. 예제에는 npm 의존성, 계정, 비공개 데이터, 운영 파일이 없습니다. CSV에는 따옴표로 감싼 쉼표가 없으며, 이 코드는 범용 CSV 파서가 아닙니다.
create_harness_lab() {
mkdir harness-lab || return
cd harness-lab || return
cat > orders.csv <<'CSV'
id,status,cents
A,paid,1200
B,refunded,700
C,paid,800
D,pending,400
CSV
cat > report.mjs <<'JS'
export function totalPaid(csv) {
const rows = csv.trim().split(/\r?\n/).slice(1);
return rows.map(row => row.split(','))
.filter(([, status]) => status !== 'pending')
.reduce((sum, [, , cents]) => sum + Number(cents), 0);
}
JS
cat > report.test.mjs <<'JS'
const { default: assert } = await import('node:assert/strict');
const { readFileSync } = await import('node:fs');
const { default: test } = await import('node:test');
const { totalPaid } = await import('./report.mjs');
const csv = readFileSync(new URL('./orders.csv', import.meta.url), 'utf8');
test('only paid orders count', () => assert.equal(totalPaid(csv), 2000));
test('refunds alone count as zero', () => assert.equal(totalPaid('id,status,cents\nB,refunded,700\n'), 0));
test('an empty ledger counts as zero', () => assert.equal(totalPaid('id,status,cents\n'), 0));
JS
cp report.mjs report.original.mjs
node --test report.test.mjs
}
create_harness_lab처음에는 검증 두 개가 실패하고 하나가 통과해야 합니다. 잘못된 코드는 환불된 700센트 주문을 포함해 2000 대신 2700을 계산합니다. 규칙은 명확합니다. status가 paid인 행만 합산하고 refunded와 pending은 제외합니다. 금액은 모두 정수 센트입니다.
먼저 재현 가능한 진단 요청하기
orders.csv, report.mjs, report.test.mjs만 살펴보고 아직 파일을 수정하지 마세요. 테스트가 요구하는 집계 규칙과 환불 행을 설명한 뒤 node --test report.test.mjs를 실행하세요. 현재 필터가 왜 2000 대신 2700을 계산하는지 설명하세요. 명령을 실행할 수 없다면 결과를 지어내지 말고 정확한 환경 문제를 보고하세요.유용한 진단은 B 행, status !== 'pending' 필터, 실패한 검증 두 개를 지목합니다. ‘수정하면 통과할 것이다’는 테스트 결과가 아닙니다. 에이전트가 새 CSV 라이브러리나 큰 리팩터링을 제안하면 기존 예제와 통과 기준으로 범위를 다시 좁히세요.
작은 수정을 허용하고 독립적으로 확인하기
이 임시 프로젝트에서 totalPaid가 paid 행만 합산하도록 report.mjs를 수정하세요. 먼저 orders.csv와 report.test.mjs를 읽고 node --test report.test.mjs를 실행하여 초기 실패를 보고하세요. orders.csv, report.test.mjs, report.original.mjs는 수정하지 말고 패키지 설치나 다른 디렉터리 접근도 하지 마세요. 구현을 최소한으로 수정하고 검증 세 개를 모두 다시 실행한 뒤 orders.csv의 합계를 계산하세요. 변경한 파일, 실제 테스트 결과, 합계, 한계를 반환하세요. 명령이 환경 문제로 실패하면 검증 실패와 구분하세요.node --test report.test.mjs
node --input-type=module -e "import {readFileSync} from 'node:fs'; import {totalPaid} from './report.mjs'; console.log(totalPaid(readFileSync('orders.csv','utf8')))"
diff -u report.original.mjs report.mjs테스트 세 개가 통과하고 별도로 계산한 합계가 2000이어야 합니다. 보통 diff에는 필터를 status === 'paid'로 바꾼 내용만 나타납니다. 같은 규칙을 만족하고 테스트를 유지한다면 다른 구현도 가능합니다. 파일이 다를 때 diff의 종료 코드는 1이며, 여기서는 정상적인 차이 표시이지 테스트 실패가 아닙니다. Node 실행 파일 부재나 권한 거부는 환경 문제이며 계산이 틀렸다는 증거가 아닙니다.
.filter(([, status]) => status === 'paid')로컬에서 확인한 참고 수정은 필터만 바꿉니다. 입력과 테스트는 유지합니다. 단위 테스트 출력과 별도 계산한 합계를 함께 보관하세요. 명령과 관련 diff 없이 초록색 터미널 화면만 보고 통과로 받아들이지 마세요.
두 번째 작업: 설정을 바꿔도 이전 캐시 객체가 반환됨
같은 임시 프로젝트에 아래 파일 두 개를 추가하세요. account는 demo로 유지하고 mode만 light에서 dark로 바꿉니다. 캐시는 account만 비교하므로 이전 객체를 잘못 반환합니다. 이 예제로 설정 변경과 이미 생성된 인스턴스의 캐시 갱신이 서로 다른 작업임을 확인합니다.
create_cache_lab() {
test ! -e cache.mjs && test ! -e cache.test.mjs && test ! -e cache.original.mjs || return
cat > cache.mjs <<'JS'
let cached;
export function getSettings(config) {
if (!cached || cached.account !== config.account) cached = { ...config };
return cached;
}
JS
cat > cache.test.mjs <<'JS'
const { default: assert } = await import('node:assert/strict');
const { default: test } = await import('node:test');
const { getSettings } = await import('./cache.mjs');
test('a changed setting refreshes the instance', () => {
const first = getSettings({ account: 'demo', mode: 'light' });
const second = getSettings({ account: 'demo', mode: 'dark' });
assert.notEqual(second, first);
assert.equal(second.mode, 'dark');
assert.equal(getSettings({ account: 'demo', mode: 'dark' }), second);
});
JS
cp cache.mjs cache.original.mjs
node --test cache.test.mjs
}
create_cache_labcache.mjs와 cache.test.mjs를 살펴보세요. 실패를 재현한 뒤 account 또는 mode가 바뀌면 새 인스턴스를 만들고 두 값이 같으면 기존 인스턴스를 재사용하도록 고치세요. 기존 테스트는 유지하고 필요하면 account 변경을 검증하는 별도 검증을 추가하세요. 의존성, 타이머, 전역 캐시 초기화를 도입하지 마세요. node --test cache.test.mjs를 실행하고 인스턴스 동일성을 결정하는 입력을 설명하세요.if (!cached || cached.account !== config.account || cached.mode !== config.mode) cached = { ...config };node --test cache.test.mjs를 실행하세요. 확인한 참고 수정은 통과합니다. mode가 바뀌면 dark를 담은 새 객체를 반환하고, 다음에 같은 값으로 호출하면 그 객체를 재사용합니다. 이 예제의 입력은 account와 mode뿐입니다. 실제 서비스에서는 생성에 쓰이는 모든 입력을 열거하고 읽기 실패 시의 동작을 유지하며 비밀 값을 노출하지 않고 교체를 검증해야 합니다. 이 연습이 운영 캐시나 결제 공급자의 안전성을 인증하는 것은 아닙니다.
이 실습에서 이런 항목을 확인하는 이유
Anthropic의 컨텍스트 엔지니어링 글은 필요한 정보 조회와 구조화한 메모를 다루고, 평가 글은 대화 기록과 최종 결과를 구분합니다. 이 실습에서는 지정 파일부터 읽고 수정 후 다시 확인하며 실제 테스트 출력과 합계를 diff와 함께 남깁니다. HANDOFF.md에 경로, 실행한 명령, 남은 작업을 기록하면 재개한 세션이 현재 파일을 다시 검증할 수 있습니다. 긴 프롬프트나 로그를 품질의 증거로 삼지 않고 컨텍스트, 검증 결과, 인계를 연결하는 방법입니다.
중단한 작업을 쉽게 이어갈 수 있도록 준비하기
report.original.mjs와 cache.original.mjs는 그대로 보관하세요. 새 세션 전에 현재 파일, 마지막으로 실행한 명령, 미해결 작업을 담은 짧은 인계를 요청합니다. 재개할 때는 파일을 읽고 테스트를 다시 실행하세요. 세션 요약은 이전 상태를 설명할 수 있습니다. DSH의 저장된 세션은 기록이며 버전 관리나 파일 백업을 대신하지 않습니다.
이 연습의 HANDOFF.md를 작성하세요. 목표, 변경 파일, 초기 실패, 실제로 실행한 정확한 명령과 결과, 남은 문제, 다음 검증 단계를 포함하세요. 인증 정보를 넣거나 실행하지 않은 검증을 통과했다고 쓰지 마세요. 새 세션이 이 메모와 현재 파일을 읽고 작업을 이어갈 수 있어야 합니다.관측한 실패에 맞게 복구하기
- 01
명령을 실행할 수 없음
터미널의 Node 버전, cwd, 선택한 작업 공간을 확인하세요. 실행 파일 부재나 권한 거부를 코드 수정으로 덮으려 하지 말고 환경을 먼저 바로잡습니다.
- 02
에이전트가 테스트나 다른 파일을 수정함
작업을 중단하고 수정 시도를 보관한 뒤 diff를 검토하세요. 영향을 받은 연습 파일만 확인된 원본에서 복구하고 통과 기준을 다시 명시합니다.
- 03
모델이나 공급자를 사용할 수 없음
로컬 파일과 인계 메모를 보관하세요. 프롬프트 밖에서 공급자 설정을 수정한 뒤 같은 통과 기준으로 세션을 이어가거나 새로 시작합니다. API 실패를 코드 테스트 성공으로 해석하지 마세요.
cp report.mjs report.attempt.mjs
cp report.original.mjs report.mjs
node --test report.test.mjs복구 후에는 원래의 테스트 실패 두 개가 다시 나타나야 합니다. 의도적인 복구 검증입니다. 비교할 수 있도록 report.attempt.mjs를 보관하세요. 실제 저장소에서는 깨끗한 브랜치·작업 트리와 검토한 파일별 복구를 사용하고, 이 예제의 덮어쓰기 명령을 무관한 작업에 적용하지 마세요.
성공한 절차를 작은 재사용 Skill로 정리하기
연습을 완료한 뒤에 검토·재현·수정·테스트·인계 순서를 문서화하세요. DSH의 공식 로컬 검색 경로에는 프로젝트의 .dsh/skills와 .agents/skills가 있으며 이름과 우선순위가 중요합니다. Skill은 작업 절차를 기록할 뿐 시스템 권한을 새로 부여하지 않습니다. 검색되도록 배치하기 전에 내용을 검토하고 명령 범위를 제한하세요. 자동화를 약속한다는 이유만으로 모르는 확장을 로드하지 않습니다.
구체적인 다음 단계
공식 1차 문서 읽기
일반 질문
변경하기 전에
형식, 호환성, 증거 및 롤백에 대한 답변
이 가이드에서는 무엇을 확인하나요?
이 가이드의 범위: 고정 DSH Alpha 소스와 컨텍스트 관리·Agent 평가의 일차 자료, 로컬에서 실행한 두 합성 Node 예제, 참고 수정안과 지정 파일 복구, 모델 비교 벤치마크나 실제 공급자 작업 결과를 주장하지 않음
무엇부터 시작해야 하나요?
주문 합계를 바로잡고 설정 변경을 무시하는 캐시를 고치는 두 작업으로 반복 가능한 습관을 만드세요. 각 작업에는 입력, 확인할 수 있는 실패, 복사할 프롬프트, 독립적인 검증이 있습니다. 중요한 작업에 적용하기 전에 아래 임시 프로젝트부터 시작하세요.
가장 중요한 경계는 무엇인가요?
두 Node 예제를 로컬에서 실행해 초기 실패, 참고 수정, report.mjs 모듈의 원래 내용 복원을 확인했습니다. DSH 절차는 커밋 d347e703908d0406b7a7ef80e3a0e594d86b2215의 0.1.3-alpha.1을 기준으로 합니다. 설정한 모델로 수행할 연습이며 실제 모델 실행 결과를 주장하지 않습니다.
아주 작은 수정도 매번 계획부터 요청해야 하나요?
이 예제에서는 짧은 진단과 명확한 테스트 명령이면 충분합니다. 큰 작업은 각 단계에 검토 가능한 산출물과 검증이 있을 때 단계별 계획이 유용합니다.
에이전트가 완료했다고 한 뒤 무엇을 보관해야 하나요?
파일 diff, 정확한 명령 출력, 기대값, 한계, 원본 백업을 보관하세요. 테스트를 독립적으로 실행해야 하며 설명만으로는 검증이 되지 않습니다.
조심하라는 지시로 샌드박스를 대신할 수 있나요?
아닙니다. 프롬프트는 의도를 표현합니다. 실제 접근 범위는 실행기, 프로세스 권한, 설정된 운영체제 경계가 결정합니다.
학습 계속하기
확인된 증거에서 계속하기
공개된 아티팩트를 비교하거나 설치 문서로 돌아가세요.