Methodology

/apt-sa

v24

SemanticAnchor — project identity and context bootstrap.

사용법

/apt-sa

Claude Code CLI 또는 연결된 에이전트에서 호출합니다.

상세 설명

APT SA: SemanticAnchor — Project Identity & Context Bootstrap

 

What SA Does

SA answers ONE question: **"이 작업이 정확히 무엇이며, KG에서 어디에 위치하는가?"**

SA는 단순한 이름 붙이기가 아니다. Anthropic의 Initializer Agent 패턴과 동일하게,
후속 Phase가 즉시 이어받을 수 있는 **실행 가능한 환경을 부트스트랩**한다.
SA가 없으면 모든 후속 Phase(SP, ST, SCW)의 기반이 없다 (D9 GenerativeFlowOrdering).

SA = Inform Axis + Routing Pattern

### Inform 축 (Harness Engineering)

하네스 엔지니어링에서 Inform(정보 제공)은 에이전트에게 컨텍스트를 주입하는 축이다.
SA가 정확히 이 역할을 수행한다:

- **프로젝트 정체성**: 이 작업이 무엇인지 (이름, 도메인, 설명)
- **KG 위치**: 기존 지식과의 관계 (INFORMED_BY 링크, 관련 앵커)
- **실행 환경**: apt-progress.md, feature-spans.json, Context Budget

### Routing 패턴 (Anthropic Flow Patterns)

SA는 Anthropic의 **Routing 패턴**에 대응한다:

1. 입력(사용자 요청)을 분류한다
2. 적절한 앵커/브랜치로 라우팅한다
3. 새 앵커 생성 vs 기존 앵커 재사용 vs 기존 앵커에 브랜치 추가를 결정한다

라우팅 결정이 잘못되면 이후 모든 Phase가 잘못된 컨텍스트에서 진행된다.
**KG 탐색이 라우팅의 핵심**이며, 이것이 Step 1이 존재하는 이유다.

---

Step 1: KG 탐색 — 기존 앵커 확인

**절대 새 앵커를 먼저 만들지 말 것.** 이것이 SA의 가장 흔한 실수(E-SA1)이다.
먼저 KG에 이미 관련 앵커가 있는지 확인한다.

### 1-1. 기존 SemanticAnchor 전체 목록

```cypher
-- 모든 활성 앵커 조회
MATCH (sa:SemanticAnchor)
RETURN sa.name, sa.description, sa.domain, sa.status,
       sa.context_budget_total, sa.created_at
ORDER BY sa.name
```

결과를 검토하여 현재 작업과 동일하거나 유사한 앵커가 있는지 확인한다.
이름뿐 아니라 description과 domain도 비교해야 한다.

### 1-2. 키워드로 관련 KG 노드 탐색

```cypher
-- 키워드로 관련 작업/개념 탐색
MATCH (n)
WHERE n.name CONTAINS $keyword
   OR n.description CONTAINS $keyword
RETURN n.name, labels(n), n.description
LIMIT 20
```

키워드를 여러 개 시도한다. 프로젝트명, 도메인 용어, 핵심 기술 등.
관련 노드가 나오면 해당 앵커로 라우팅할 수 있는지 검토한다.

### 1-3. 기존 앵커의 Span 트리 확인

```cypher
-- 특정 앵커의 하위 구조 확인
MATCH (sa:SemanticAnchor {name: $sa_name})-[:HAS_ROOT]->(root)
OPTIONAL MATCH (root)-[:DECOMPOSES_TO*1..3]->(s)

Step 2: 앵커 결정

### 2-A. 새 앵커 생성

KG 탐색 결과 관련 앵커가 없을 때만 실행한다.

```cypher
-- 새 SemanticAnchor 생성 (항상 MERGE로 중복 방지)
MERGE (sa:SemanticAnchor {name: $project_name})
SET sa.description         = $description,
    sa.domain              = $domain,
    sa.status              = 'active',
    sa.context_budget_total = 100000,
    sa.context_budget_per_span = 8000,
    sa.created_at          = datetime(),
    sa.updated_at          = datetime()
RETURN sa
```

앵커 생성 직후 Root Span을 연결한다:

```cypher
-- Root Span 생성 및 연결
MATCH (sa:SemanticAnchor {name: $project_name, status: 'active'})
MERGE (root:AptSpan {name: 'SPAN_' + $project_name + '_ROOT'})
SET root.description   = $root_description,
    root.depth         = 0,
    root.status        = 'open',
    root.context_budget = 50000,
    root.created_at    = datetime()

SA as System Index (D17)

SA는 고립된 정체성 노드가 아니다. **전체 시스템의 인덱스**다.

SA는 생성 시점부터 연결되어야 하고, 나중에 발견한 연결도 **소급 추가**한다.

### 필수 연결

```cypher
// 도메인 지식 연결
MATCH (sa:SemanticAnchor {name: $project})
MERGE (k:KnowledgeNode {name: $knowledge})
MERGE (sa)-[:INFORMED_BY {reason: $why}]->(k)

// 기술 스택 연결
MERGE (lib:KnowledgeNode {name: $library, source: 'library'})
MERGE (sa)-[:USES {reason: $why}]->(lib)

// 다른 프로젝트 연결
MATCH (other:SemanticAnchor {name: $related_project})
MERGE (sa)-[:RELATED_TO {reason: $why}]->(other)

// 인프라 연결
MERGE (infra:KnowledgeNode {name: $service, source: 'infrastructure'})
MERGE (sa)-[:DEPLOYED_ON]->(infra)
```

### 연결 종류

| Relation | 대상 | 예시 |
|----------|------|------|
| INFORMED_BY | 도메인 지식, 디자인 패턴 | SA → "ECS Pattern", "REST API Design" |
| USES | 라이브러리, 프레임워크, 외부 API | SA → "Three.js", "FastAP

Step 3: Progressive Disclosure — 3단계 로딩

Context Rot(토큰 증가 시 n^2으로 주의력 분산) 방지를 위해 컨텍스트를 단계적으로 로드한다.
**절대 KG 전체를 한번에 로드하지 않는다** (E-SA2).

### L1: 메타데이터 (토큰 예산 ~2K)

프로젝트 정체성과 최상위 Span 이름/설명만 로드한다. KG 전체를 읽지 않는다.

```cypher
-- L1: SA + 직계 자식 메타데이터만
MATCH (sa:SemanticAnchor {name: $sa_name})-[:HAS_ROOT]->(root)
OPTIONAL MATCH (root)-[:DECOMPOSES_TO]->(l1)
RETURN sa.name, sa.description, sa.domain, sa.status,
       root.name AS root_span,
       l1.name AS l1_span, l1.description AS l1_desc, l1.depth
ORDER BY l1.name
```

**포함 항목:** SA name, description, domain, status, Root Span, L1 Span 이름/설명
**제외 항목:** Span 트리 구조, Contract, 소스코드, 테스트 결과

### L2: 구조 (토큰 예산 ~5K)

선택된 브랜치의 Span 트리와 Contract 존재 여부를 로드한다. **작업 대상 브랜치만** 로드한다.

```cypher
-- L2: 선택된 브랜치의 Span 트리 + Contract 존재 여부
MATCH (root:AptSpan {name: $branch})-[:DECOMPOSES_TO*1..5]

Step 4: Context Budget 할당

SA에서 전체 프로젝트의 depth별 토큰 예산을 할당한다.
이 예산은 인지과학이 아닌 **공학적 휴리스틱**(C26)이다.

### Depth별 토큰 예산

| Span Depth | 토큰 예산 | 근거 |
|:----------:|:---------:|------|
| 0 (Root)   | 50,000    | 프로젝트 전체 개요. L1 메타 + L2 구조 |
| 1          | 50,000    | 주요 모듈. 넉넉한 컨텍스트 필요 |
| 2          | 20,000    | 서브모듈. 범위가 좁아짐 |
| 3+         | 8,000     | AtomicSpan. 단일 파일 500줄 구현에 적정 |

### 할당 Cypher

```cypher
-- SA에 Context Budget 총량 설정
MATCH (sa:SemanticAnchor {name: $sa_name})
SET sa.context_budget_total    = 100000,
    sa.context_budget_per_span = 8000

-- Span 생성 시 depth 기반 자동 할당
MERGE (child:AptSpan {name: $name})
SET child.context_budget = CASE
  WHEN child.depth = 0 THEN 50000
  WHEN child.depth = 1 THEN 50000
  WHEN child.depth = 2 THEN 20000
  ELSE 8000 END
```

### Budget 초과 시 대응

- depth 0~1에서 50K 초과: L2 로딩 

Step 5: Initializer Bootstrap

SA 완료 시 후속 Phase를 위한 파일을 생성한다.

### 5-1. apt-progress.md 생성

세션 연속성의 핵심 파일. 모든 Phase에서 참조하고 갱신한다.

```markdown
# APT Progress: {project_name}

Anchor: {sa_name}

 

Domain: {domain}

 

Status: active

 

Created: {datetime}

 

Last Updated: {datetime}

 

Context Budget: total={total}K, per_span={per_span}K

---

### Completed Spans
(none yet)

### In Progress
- {current_span}: SA complete, ready for SP

### Blocked
(none)

### KG Stats
- SemanticAnchor: {sa_name}
- L1 Spans: {count}
- INFORMED_BY links: {count}

### Next Steps
1. SP Phase: {first_branch} 분해 시작
2. 각 L1 Span에 INFORMED_BY >= 5 확보

### Session Log
- [{datetime}] SA Phase: anchor {sa_name} created/reused
```

### 5-2. feature-spans.json 생성 (선택)

대규모 프로젝트에서 Span 목록을 구조화된 형태로 관리할 때 사용.

```json
{
  "anchor": "{sa_name}",
  "domain": "{domain}",
  "created_at": "{datetime}",
  "spans": [
    {
      "name": "SPAN_{project}_ROOT",
      "description": "...",
      "status": "open",
      "depth": 0,
      "context_budget": 50000
    }
  ]
}
```

### 5-3. 기존 파일이 있는 경우

기존 앵커를 재사용하는 경우(Step 2-B) apt-progress.md가 이미 존재한다.
이 경우 새로 생성하지 않고

Step 6: Git Commit

SA 결과물을 커밋한다. 이것이 SA의 마지막 단계.

```bash
git add apt-progress.md feature-spans.json
git commit -m "APT SA: Initialize {project_name} anchor

- SemanticAnchor: {sa_name}
- Domain: {domain}
- Context Budget: {total}K total, {per_span}K per span
- L1 Spans: {count}"
```

기존 앵커 재사용 시:

```bash
git add apt-progress.md
git commit -m "APT SA: Resume {project_name} - {branch_description}"
```

---

SA -> SP 핸드오프

SA에서 SP로 전환하기 전 **모든 항목**을 확인한다.

### 핸드오프 체크리스트

| # | 체크 항목 | 검증 방법 |
|---|----------|----------|
| 1 | SemanticAnchor가 KG에 존재 | `MATCH (sa:SemanticAnchor {name: $sa}) RETURN sa` |
| 2 | SA status = 'active' | `sa.status = 'active'` 확인 |
| 3 | Root Span이 SA에 연결됨 | `MATCH (sa)-[:HAS_ROOT]->(root) RETURN root` |
| 4 | Progressive Disclosure L1 로드됨 | apt-progress.md에 L1 Span 목록 기재 확인 |
| 5 | Context Budget 할당됨 | `sa.context_budget_total IS NOT NULL` |
| 6 | apt-progress.md 생성됨 | 파일 존재 확인 |
| 7 | 기존 앵커 중복 없음 | Step 1의 KG 탐색으로 유사 앵커 부재 확인 |
| 8 | Git commit 완료 | `apt-progress.md` 커밋됨 |

### 핸드오프 검증 쿼리

```cypher
-- 핸드오프 준비 상태 종합 확인
MATCH (sa:SemanticAnchor {name: $sa_name, status: 'active'})
MATCH (sa)-[:HAS_ROOT]->(root:AptSpan)
WHERE sa.context_budget_total IS NOT NULL
RETURN sa.name, sa.st

Phase Transition Compaction: SA -> SP

SA 완료 후 SP로 전환할 때 컨텍스트를 압축한다.

### 보존 (SP에 전달)

- 앵커 이름, 설명, 도메인
- L1 Span 목록 (이름 + 설명)
- Context Budget 설정
- apt-progress.md 현재 상태

### 제거 (메모리에서 해제)

- KG 탐색 과정 (어떤 쿼리를 실행했는지)
- 앵커 후보 비교 로그
- 라우팅 의사결정 과정
- L2/L3 로딩 결과 (SP에서 필요할 때 다시 로드)

### 새 컨텍스트 (SP 시작 시 로드)

- SA 결과 압축 요약 (앵커명 + 도메인 + L1 구조 1줄 요약)
- 최근 5개 접근 파일 경로
- SP Phase 시작에 필요한 첫 번째 브랜치 정보

---

Validation Queries

SA 관련 무결성을 검증하는 쿼리들. 문제 발생 시 사용한다.

### V-SA1: 고아 Root Span (SA 미연결)

```cypher
MATCH (root:AptSpan)
WHERE root.depth = 0
  AND NOT ()-[:HAS_ROOT]->(root)
RETURN 'V_SA1_OrphanRoot' AS validation, root.name
```

### V-SA2: SA 중복 (동일 프로젝트 이름)

```cypher
MATCH (sa:SemanticAnchor)
WITH sa.name AS sa_name, count(sa) AS cnt
WHERE cnt > 1
RETURN 'V_SA2_DuplicateAnchor' AS validation, sa_name, cnt
```

### V-SA3: Root Span이 없는 SA

```cypher
MATCH (sa:SemanticAnchor {status: 'active'})
WHERE NOT (sa)-[:HAS_ROOT]->()
RETURN 'V_SA3_NoRoot' AS validation, sa.name
```

### V-SA4: Context Budget 미할당

```cypher
MATCH (sa:SemanticAnchor {status: 'active'})
WHERE sa.context_budget_total IS NULL
RETURN 'V_SA4_NoBudget' AS validation, sa.name
```

---

v21 Rules (SA Phase)

SA는 5대 신기 중 **프로메테우스(지식 선행)**와 **롱기누스(KG 접지)**의 시작점.

| Rule | SA에서의 의미 |
|------|-------------|
| HR11 (증거 필수) | SA 생성 시 KG 조회 증거 필수. "KG에 없었다"도 증거 |
| HR14 (Reflection) | SA 완료 후: "이 앵커의 약점은?" 기록 → SP 진입 시 참조 |

```cypher
-- v21: SA 완료 후 Reflection 기록
MATCH (sa:SemanticAnchor {name: $project})
SET sa.v21_reflection = $weakness,
    sa.v21_reflectedAt = datetime()
```

---

What NOT to Do

| 금지 사항 | 이유 | 해당 Phase |
|----------|------|-----------|
| 코드 작성 | 코드는 SCW(PH5)의 책임 | SCW |
| Span 분해 | 분해는 SP(PH3)의 책임 | SP |
| Contract 정의 | Contract는 ST(PH4)의 책임 | ST |
| KG 탐색 없이 앵커 생성 | 중복 앵커가 가장 흔한 SA 오류(E-SA1) | - |
| 전체 KG 한번에 로드 | Context Rot 발생(E-SA2). Progressive Disclosure 위반 | - |
| apt-progress.md 없이 SP 진입 | 세션 연속성 단절. 다음 에이전트가 컨텍스트를 잃음 | - |
| CREATE 사용 (MERGE 대신) | 중복 노드 생성 위험. 항상 MERGE 사용 | - |

메타데이터

name apt-sa
version 24
description >
# KG ATOM_Skill_apt_sa
Invoke when starting a new project/feature, establishing work identity,
Enforces Anchor identity, Progressive Disclosure, Context Budget, KG-first exploration.
v22 Gate Check enforcement via Claude Code Hook. 5대 신기 기반. SA는 프로메테우스(지식 선행)와 롱기누스(KG 접지)의 시작점.

같은 카테고리