---
name: longinus
description: >
  롱기누스 방법론 — KG 의미 계층을 소스코드까지 관통(貫通)시키는 참조 바인딩.
  Invoke when: ST→SCW 전환 후 코드가 물질화되었을 때, KG 노드와 소스코드 간 추적성 확보가 필요할 때,
  기존 코드베이스를 KG에 역매핑할 때, Contract-Code 정합성 감사(audit) 시.
  Enforces: 이중 ref (sourceId + sourcePath), 양방향 추적, 관통 검증, drift 탐지.
---

# /longinus — 롱기누스 방법론: KG↔SourceCode 관통 바인딩

> **롱기누스의 창이 관절을 관통하듯, KG의 의미 계층 사이사이를 소스코드 참조로 꿰뚫는다.**
> Span → Twin → Contract → SourceCode — 어느 층에서 시작하든 코드까지, 코드에서 어느 층까지든 추적 가능.

---

## 왜 롱기누스인가

APT의 ST(SemanticTwin)는 **의미**를 결정화하고, SCW(SourceCodeWorld)는 **코드**를 물질화한다.
그런데 이 둘 사이에 **참조가 없으면** AI는 맥락을 잃는다:

- "이 Contract가 어떤 코드로 구현됐지?" → 모름
- "이 함수가 어떤 Contract에서 나왔지?" → 모름
- "Contract 변경 시 어떤 파일을 수정해야 하지?" → 추측만 가능

롱기누스 방법론은 이 **단절을 관통**한다. KG 노드마다 두 가지 ref를 꽂아넣어서
**semantic ↔ implementation** 양방향 추적을 보장한다.

---

## 이중 참조 (Dual Ref) 구조

모든 SCW 결과물에 두 가지 ref를 부여한다:

| Ref | 설명 | 예시 |
|-----|------|------|
| **`sourceId`** | 코드 내용의 식별자 — 함수명, 클래스명, 모듈 식별자 | `LoginService.authenticate` |
| **`sourcePath`** | 코드의 물리적 위치 — file:line | `src/auth/login.ts:42` |

```
KG Layer:        [Span] → [Twin] → [Contract] → [SourceCodeNode]
                                                      ↓
Longinus Ref:                              sourceId: "LoginService.authenticate"
                                           sourcePath: "src/auth/login.ts:42"
                                                      ↓
Physical Layer:                            실제 파일의 실제 라인
```

---

## Step 1: 관통 대상 식별

SCW에서 `ContractMaterialized` 후, 또는 기존 코드를 KG에 역매핑할 때 실행.

```cypher
// 아직 롱기누스 ref가 없는 SourceCodeNode 찾기
MATCH (ct:AptContract)-[:MATERIALIZES]->(src:SourceCodeNode)
WHERE src.sourceId IS NULL OR src.sourcePath IS NULL
RETURN ct.name AS contract, src.file_path AS file, ct.status
```

---

## Step 2: sourceId 결정

코드의 **의미적 식별자**를 결정한다. 함수/클래스/모듈 수준에서 가장 구체적인 이름.

**규칙:**
- 함수 단위 구현 → `ModuleName.functionName` (예: `AuthService.login`)
- 클래스 단위 구현 → `ClassName` (예: `UserProfileValidator`)
- 모듈 전체 → `module_name` (예: `auth_middleware`)
- 중첩 → dot notation (예: `OrderProcessor.Validator.check`)

**금지:**
- 파일명 그대로 쓰기 (`login.ts` ← 이건 sourcePath 역할)
- 추상적 이름 (`handler`, `processor`, `service` 단독)

---

## Step 3: sourcePath 결정

코드의 **물리적 위치**. `file_path:start_line` 형식.

**규칙:**
- 프로젝트 루트 기준 상대경로 사용
- 라인 번호는 함수/클래스 **선언 시작 라인**
- 범위가 넓으면 `file_path:start-end` (예: `src/auth/login.ts:42-87`)

```bash
# sourcePath 자동 추출 예시
grep -n "def authenticate\|function authenticate\|authenticate(" src/auth/login.ts
# → src/auth/login.ts:42
```

---

## Step 4: KG에 관통 ref 기록

```cypher
// SourceCodeNode에 이중 ref 설정
MATCH (ct:AptContract {name: $contract_name})-[:MATERIALIZES]->(src:SourceCodeNode)
SET src.sourceId   = $sourceId,       // e.g. "LoginService.authenticate"
    src.sourcePath = $sourcePath,     // e.g. "src/auth/login.ts:42"
    src.pierced_at = datetime()       // 관통 시점
RETURN ct.name, src.sourceId, src.sourcePath
```

**역방향 — 코드에도 KG ref 주석 삽입** (SCW의 FulfillmentGate Check #5와 연동):

```python
# KG: CT_Project_Auth | ST_Project_Auth | TASK_Project_Auth
# LONGINUS: sourceId=AuthService.login, sourcePath=src/auth/login.py:15
def login(email: str, password: str) -> AuthResult:
    ...
```

---

## Step 5: 관통 체인 완성도 검증

Span부터 SourceCode까지 **전체 체인이 끊김 없이 관통**되었는지 검증.

```cypher
// 관통 완성도 체크 — 끊어진 체인 탐지
MATCH (atom:AtomicSpan)-[:CRYSTALLIZES_TO]->(twin:SemanticTwin)
MATCH (twin)-[:HAS_CONTRACT]->(ct:AptContract)
OPTIONAL MATCH (ct)-[:MATERIALIZES]->(src:SourceCodeNode)
WITH atom.name AS span, twin.name AS twin, ct.name AS contract,
     src.sourceId AS sourceId, src.sourcePath AS sourcePath,
     CASE
       WHEN src IS NULL THEN 'NO_SOURCE'
       WHEN src.sourceId IS NULL THEN 'NO_ID'
       WHEN src.sourcePath IS NULL THEN 'NO_PATH'
       ELSE 'PIERCED'
     END AS status
RETURN span, twin, contract, sourceId, sourcePath, status
ORDER BY status DESC
```

**관통 상태 분류:**

| Status | 의미 | 조치 |
|--------|------|------|
| `PIERCED` | 완전 관통 — 양쪽 ref 모두 존재 | 정상 |
| `NO_PATH` | sourceId는 있으나 위치 미지정 | sourcePath 추가 |
| `NO_ID` | 위치는 있으나 의미 식별자 없음 | sourceId 추가 |
| `NO_SOURCE` | SourceCodeNode 자체가 없음 | SCW 미완료 — `/apt-scw` 먼저 |

---

## Step 6: Drift 탐지 (코드 변경 후 KG 동기화)

코드가 변경되면 sourcePath의 라인 번호가 밀린다. 주기적으로 검증.

```bash
# sourcePath 유효성 검증 — 해당 라인에 sourceId가 실제로 존재하는지
grep -n "$sourceId" "$sourcePath_file" | head -1
# 결과가 sourcePath_line과 다르면 → drift 발생
```

```cypher
// Drift 플래그 설정
MATCH (src:SourceCodeNode {name: $src_name})
WHERE src.sourcePath IS NOT NULL
SET src.drift_detected = true,
    src.drift_at = datetime(),
    src.old_sourcePath = src.sourcePath
// 이후 새 위치로 sourcePath 업데이트
```

**Drift 해소:**
1. `grep -rn` 으로 sourceId의 현재 위치 탐색
2. sourcePath 업데이트
3. `drift_detected = false` 리셋

---

## 역매핑 (기존 코드 → KG)

새 프로젝트가 아닌, **기존 코드베이스를 KG에 매핑**할 때의 절차.

```
1. 프로젝트 소스 파일 스캔
2. 함수/클래스 단위로 sourceId 후보 추출
3. 각 후보에 대해:
   a. KG에 SourceCodeNode MERGE
   b. sourceId, sourcePath 설정
   c. 대응되는 Contract가 있으면 MATERIALIZES 연결
   d. Contract가 없으면 → 역으로 Contract 초안 생성 (ST로 에스컬레이션)
```

```cypher
// 역매핑: 코드에서 KG로
MERGE (src:SourceCodeNode {file_path: $file_path})
SET src.sourceId   = $sourceId,
    src.sourcePath = $sourcePath,
    src.pierced_at = datetime(),
    src.reverse_mapped = true   // 역매핑임을 표시
// Contract 연결 (있으면)
WITH src
OPTIONAL MATCH (ct:AptContract {target_file: $file_path})
FOREACH (_ IN CASE WHEN ct IS NOT NULL THEN [1] ELSE [] END |
  MERGE (ct)-[:MATERIALIZES]->(src)
)
RETURN src.sourceId, src.sourcePath, ct.name AS linked_contract
```

---

## 관통 통계 대시보드

```cypher
// 프로젝트별 관통률
MATCH (ct:AptContract)
OPTIONAL MATCH (ct)-[:MATERIALIZES]->(src:SourceCodeNode)
WITH ct.name AS contract,
     CASE WHEN src.sourceId IS NOT NULL AND src.sourcePath IS NOT NULL
          THEN 1 ELSE 0 END AS pierced
RETURN count(*) AS total_contracts,
       sum(pierced) AS pierced_count,
       toFloat(sum(pierced)) / count(*) * 100 AS pierce_rate_pct
```

---

## What NOT To Do

| 금지 | 이유 | 대안 |
|------|------|------|
| sourceId에 파일명 사용 | sourcePath와 역할 중복 | 함수/클래스 의미명 사용 |
| sourcePath 없이 sourceId만 | 절반 관통 = 추적 불가 | 반드시 이중 ref |
| 라인 번호 생략 | 파일만으로는 대형 파일에서 위치 특정 불가 | `file:line` 필수 |
| drift 무시 | 코드 변경 후 KG가 거짓말 | 주기적 drift 검증 |
| 코드 주석 없이 KG만 업데이트 | 양방향이어야 함 | `# LONGINUS:` 주석도 삽입 |
| Contract 없이 관통 | 의미 없는 ref | ST 완료 후 관통 |

---

## Session Continuity

롱기누스 작업 후 `apt-progress.md`에 기록:

```markdown
### Longinus Piercing Progress
- [x] CT_Project_Auth → AuthService.login (src/auth/login.py:15) PIERCED
- [x] CT_Project_Profile → UserProfile.update (src/user/profile.py:33) PIERCED
- [ ] CT_Project_Search → (SCW 미완료, NO_SOURCE)
- Pierce Rate: 66% (2/3)
```

---

*롱기누스의 창은 한 번 꽂으면 뽑히지 않는다. KG와 코드 사이의 참조도 마찬가지다.*
