revert: AI 코드 검토 기능 제거 (85ae82f 되돌림)

통짜 코드 전송 방식이 토큰 비효율·부정확해, 검색 기반(grep으로 좁힌 뒤 관련
스니펫만 판정) 방식으로 재설계하기 위해 일괄 제거. 추후 개선안으로 재작업 예정.

This reverts commit 85ae82f.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-20 17:56:43 +09:00
parent e72e6aee83
commit 9bcbc1564f
14 changed files with 11 additions and 543 deletions
+4 -137
View File
@@ -21,7 +21,6 @@ import {
} from '@/mock/relay.mock'
import { useTaskStore } from '@/stores/task.store'
import { useAuthStore } from '@/stores/auth.store'
import { useAi } from '@/composables/useAi'
import UserAvatar from '@/components/UserAvatar.vue'
import { attachmentKindOf, fileBadge } from '@/shared/utils/format'
@@ -32,7 +31,6 @@ const taskId = computed(() => Number(route.params.taskId))
const taskStore = useTaskStore()
const authStore = useAuthStore()
const ai = useAi()
// 업무 상세 — API 연동
const task = ref<TaskDetail | null>(null)
@@ -171,33 +169,6 @@ async function sendApproval() {
}
}
// --- AI 코드 검토 ---
// 연결된 Gitea 코드를 검토해 체크리스트 항목별 구현 여부(✓/✗)를 채운다.
const aiReviewing = ref(false)
const aiReviewSummary = ref<string | null>(null)
const aiReviewTruncated = ref(false)
async function runAiReview() {
if (!task.value || aiReviewing.value) return
aiReviewing.value = true
aiReviewSummary.value = null
try {
const result = await ai.reviewChecklist({
repoId: repoId.value,
taskSeq: task.value.id,
})
aiReviewSummary.value = result.summary
aiReviewTruncated.value = result.truncated
// 서버가 체크리스트에 판정을 반영했으므로 상세를 다시 불러와 ✓/✗ 갱신
await loadTask()
} catch {
window.alert(
'AI 코드 검토에 실패했습니다. Gitea 연결 상태를 확인하거나 잠시 후 다시 시도해 주세요.',
)
} finally {
aiReviewing.value = false
}
}
/* ============================================================
* 댓글 / 활동 탭
* ============================================================ */
@@ -515,48 +486,20 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
</div>
<!--
체크리스트는 읽기 전용 사용자가 개별 토글/추가/삭제하지 않는다.
완료 처리는 승인 워크플로우(승인 완료 일괄 완료) 또는 AI 코드 검토로 채워진다.
완료 처리는 승인 워크플로우(승인 완료 일괄 완료)로만 이루어진다.
-->
<div
v-if="aiReviewSummary"
class="ai-review-summary"
>
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
><path d="M12 3 13.4 8.6 19 10l-5.6 1.4L12 17l-1.4-5.6L5 10l5.6-1.4Z" /></svg>
<span>{{ aiReviewSummary }}<template v-if="aiReviewTruncated"> (코드 일부만 검토됨)</template></span>
</div>
<div class="checklist">
<div
v-for="(item, i) in task.checklist"
:key="item.id ?? i"
class="citem"
:class="{ done: item.done, missing: item.reviewVerdict === 'missing' }"
:title="item.reviewVerdict === 'missing' ? '미구현으로 판정됨' : undefined"
:class="{ done: item.done }"
>
<span
class="cbox"
:class="{
done: item.done,
missing: item.reviewVerdict === 'missing',
}"
:class="{ done: item.done }"
>
<svg
v-if="item.reviewVerdict === 'missing'"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="3.5"
stroke-linecap="round"
stroke-linejoin="round"
><path d="M18 6 6 18M6 6l12 12" /></svg>
<svg
v-else
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
@@ -921,23 +864,6 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
placeholder="승인 요청 메시지(선택) — 작업 내용이나 검토 포인트를 적어주세요."
/>
<div class="ap-card-actions">
<button
class="ap-btn ai-review"
type="button"
:disabled="aiReviewing"
title="연결된 Gitea 코드를 검토해 체크리스트 구현 여부를 채웁니다"
@click="runAiReview"
>
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
><path d="M12 3 13.4 8.6 19 10l-5.6 1.4L12 17l-1.4-5.6L5 10l5.6-1.4Z" /></svg>
{{ aiReviewing ? '검토 중…' : 'AI 검토' }}
</button>
<button
class="ap-btn request-send"
type="button"
@@ -985,23 +911,6 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
placeholder="보완 내용 메시지(선택)"
/>
<div class="ap-card-actions">
<button
class="ap-btn ai-review"
type="button"
:disabled="aiReviewing"
title="연결된 Gitea 코드를 검토해 체크리스트 구현 여부를 채웁니다"
@click="runAiReview"
>
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
><path d="M12 3 13.4 8.6 19 10l-5.6 1.4L12 17l-1.4-5.6L5 10l5.6-1.4Z" /></svg>
{{ aiReviewing ? '검토 중…' : 'AI 검토' }}
</button>
<button
class="ap-btn request-send"
type="button"
@@ -1588,18 +1497,13 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
background: var(--green);
border-color: var(--green);
}
.cbox.missing {
background: var(--red);
border-color: var(--red);
}
.cbox svg {
width: 0.75rem;
height: 0.75rem;
color: #fff;
opacity: 0;
}
.cbox.done svg,
.cbox.missing svg {
.cbox.done svg {
opacity: 1;
}
.citem .ctext {
@@ -1610,31 +1514,6 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
color: var(--text-3);
text-decoration: line-through;
}
.citem.missing .ctext {
color: var(--red);
}
/* AI 코드 검토 요약 배너 */
.ai-review-summary {
display: flex;
align-items: flex-start;
gap: 0.4375rem;
margin-bottom: 0.625rem;
padding: 0.5625rem 0.75rem;
background: var(--accent-weak);
border: 1px solid var(--accent-border);
border-radius: var(--radius);
font-size: 0.781rem;
line-height: 1.5;
color: var(--text);
}
.ai-review-summary svg {
width: 0.9375rem;
height: 0.9375rem;
color: var(--accent);
flex-shrink: 0;
margin-top: 0.125rem;
}
/* 댓글/활동 탭 */
.thread-tabs {
@@ -2370,18 +2249,6 @@ function badgeFor(name: string | undefined): { label: string; cls: string } {
.ap-btn.request-send:hover {
background: var(--accent-hover);
}
.ap-btn.ai-review {
color: var(--accent);
background: var(--accent-weak);
border-color: var(--accent-border);
}
.ap-btn.ai-review:hover:not(:disabled) {
background: #e7e4fb;
}
.ap-btn.ai-review:disabled {
opacity: 0.6;
cursor: default;
}
/* ===== 5단계: 첨부파일 ===== */
.files-head {