Skip to content

feat(ci): Strix LLM 기반 보안 스캔 파이프라인 추가 + GitHub Models 지원#1

Closed
seonghobae wants to merge 28 commits into
mainfrom
add-strix-pipeline
Closed

feat(ci): Strix LLM 기반 보안 스캔 파이프라인 추가 + GitHub Models 지원#1
seonghobae wants to merge 28 commits into
mainfrom
add-strix-pipeline

Conversation

@seonghobae

@seonghobae seonghobae commented May 14, 2026

Copy link
Copy Markdown

개요

Strix LLM 기반 보안 스캔 파이프라인을 CI에 추가합니다. PR이 열릴 때마다 LLM을 활용해 하드코딩된 비밀키, 취약한 의존성, 코드 품질 문제를 자동으로 탐지합니다.

주요 변경 사항

파일 변경 사항
.github/workflows/strix.yml Strix 보안 스캔 워크플로우 추가 (1020줄)
.github/workflows/dependency-review.yml 의존성 취약점 리뷰 워크플로우 추가
.github/workflows/osvscanner.yml OSV 취약점 스캐너 워크플로우 추가
scripts/ci/strix_model_utils.sh LLM 공급자 정규화 유틸리티 스크립트
scripts/ci/strix_quick_gate.sh 빠른 보안 게이트 스크립트
requirements-strix-ci.txt Strix CI 파이썬 의존성 목록

GitHub Models 활성화 방법

이 워크플로우는 GitHub Models를 LLM 공급자로 사용할 수 있습니다 (추가 API 키 불필요):

  1. 리포지토리 Settings → Secrets and variables → Actions 로 이동
  2. STRIX_LLM 시크릿을 아래 형식으로 추가:
    github/gpt-4o-mini
    
    또는 더 강력한 모델:
    github/gpt-4o
    
  3. 워크플로우 권한에 models: read가 이미 포함되어 있어 별도 설정 불필요

지원 가능한 GitHub Models 식별자 예시:

  • github/gpt-4o-mini (경량, 빠름)
  • github/gpt-4o (고성능)
  • github/meta-llama-3.1-70b-instruct (오픈소스)

보안 설계 원칙

  • 승인 전 고비용 LLM 스캔을 지연 실행 (비용 절감)
  • 악의적 커밋이 진행 중인 스캔을 취소하지 못하도록 cancel-in-progress: false
  • 보호된 브랜치에서 STRIX_LLM 미설정 시 fail-closed 정책 적용

테스트 방법

bash scripts/ci/test_strix_quick_gate.sh

참고: naruon 리포지토리의 Strix 파이프라인을 기반으로 이 프로젝트에 맞게 조정했습니다.

greatSumini and others added 3 commits May 14, 2026 21:20
- docs/usecases/ 카탈로그 구조 신설 (README 가 포맷·ID·시나리오 단계 규칙의 단일 원천, _ids.yaml 이 next-id 카운터 + lookup 캐시)
- ID 체계: UC-<DOMAIN>-<NNN>, 도메인 prefix 7개(ORG/PROJ/SESS/CLI/BILL/AUTH/SHARED)
- 시나리오 단계는 (액터·표면) 접두사 + 관찰 가능한 사실만으로 작성해 e2e 직역 가능 보장
- 상위 scope UC 가 하위 UC 를 포함: 본문 [[UC-XXX]] inline 링크 + frontmatter includes: 미러
- new-task-clarify: finalize 산출에 UC 초안 섹션 + Cockburn 작성 규칙 12항 추가, draft ID 는 UC-DRAFT-<slug>-<n> 형식
- new-task-usecase: clarify 초안을 카탈로그로 승격하는 sub-agent 신설 (NEW/UPDATE/SUPERSEDE 분류 + ID 발급 + lint)
- new-task SKILL: Step 6 (UC 승격) 을 foreground 자동 호출로 추가

Co-Authored-By: Claude <noreply@anthropic.com>
- UC-PROJ-001 프로젝트를 다른 organization 으로 이동시킨다 (user-goal, 웹 대시보드 + 백엔드 API)
- UC-CLI-001 stale .argos/project.json 을 hook 응답으로 자동 보정한다 (user-goal, CLI hook + events API)
- 두 UC 모두 docs/tasks/2026-05-14-project-transfer-org 의 clarify/plan 을 sources 로 인용
- _ids.yaml: next_id.PROJ, next_id.CLI 를 2 로 bump + 신규 entry 등록

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@seonghobae, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 17 minutes and 51 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5a8e6358-dc91-4e27-97d8-5f546da5e9b1

📥 Commits

Reviewing files that changed from the base of the PR and between 8640510 and e0511b7.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (67)
  • .claude/agents/new-task-clarify.md
  • .claude/agents/new-task-implement.md
  • .claude/agents/new-task-usecase.md
  • .claude/skills/new-task/SKILL.md
  • .github/workflows/dependency-review.yml
  • .github/workflows/osvscanner.yml
  • .github/workflows/strix.yml
  • docs/adr.md
  • docs/tasks/2026-05-14-project-transfer-org/01-clarify-round-1.md
  • docs/tasks/2026-05-14-project-transfer-org/01-clarify-round-2.md
  • docs/tasks/2026-05-14-project-transfer-org/01-clarify.md
  • docs/tasks/2026-05-14-project-transfer-org/02-context.md
  • docs/tasks/2026-05-14-project-transfer-org/03-plan-critique-1.md
  • docs/tasks/2026-05-14-project-transfer-org/03-plan-critique-2.md
  • docs/tasks/2026-05-14-project-transfer-org/03-plan.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-1.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-2.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-3.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-4.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-5.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-6.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-7.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-8.md
  • docs/tasks/2026-05-14-project-transfer-org/05-qa.md
  • docs/tasks/2026-05-14-project-transfer-org/05-review.md
  • docs/tasks/2026-05-14-project-transfer-org/_conversation.md
  • docs/tasks/2026-05-14-project-transfer-org/_pipeline-improvements.md
  • docs/usecases/README.md
  • docs/usecases/_ids.yaml
  • docs/usecases/cli/UC-CLI-001-self-heal-project-config.md
  • docs/usecases/project/UC-PROJ-001-transfer-project.md
  • package.json
  • packages/cli/package.json
  • packages/cli/src/__tests__/default-command.test.ts
  • packages/cli/src/__tests__/hook-command.test.ts
  • packages/cli/src/__tests__/setup-command.test.ts
  • packages/cli/src/adapters.ts
  • packages/cli/src/commands/hook.ts
  • packages/cli/src/deps.ts
  • packages/cli/src/lib/event-sender.test.ts
  • packages/cli/src/lib/event-sender.ts
  • packages/cli/src/lib/project.test.ts
  • packages/cli/src/lib/project.ts
  • packages/shared/src/schemas/project.ts
  • packages/shared/src/types/events.ts
  • packages/shared/src/types/project.ts
  • packages/web/package.json
  • packages/web/src/app/api/events/route.test.ts
  • packages/web/src/app/api/events/route.ts
  • packages/web/src/app/api/projects/[projectId]/transfer/route.ts
  • packages/web/src/app/dashboard/[orgSlug]/settings/projects/page.tsx
  • packages/web/src/app/globals.css
  • packages/web/src/components/dashboard/session-activity-ribbon.tsx
  • packages/web/src/components/org/create-org-modal.tsx
  • packages/web/src/components/org/create-project-modal.tsx
  • packages/web/src/components/org/delete-org-modal.tsx
  • packages/web/src/components/org/delete-project-modal.tsx
  • packages/web/src/components/org/rename-project-modal.tsx
  • packages/web/src/hooks/use-transfer-project.ts
  • packages/web/src/lib/server/project-actions.test.ts
  • packages/web/src/lib/server/project-actions.ts
  • requirements-strix-ci.in
  • requirements-strix-ci.overrides.txt
  • requirements-strix-ci.txt
  • scripts/ci/strix_model_utils.sh
  • scripts/ci/strix_quick_gate.sh
  • scripts/ci/test_strix_quick_gate.sh
📝 Walkthrough

Walkthrough

이 PR은 Strix 보안 스캔 GitHub Action 및 관련 CI 스크립트/유틸을 추가하고, CLI의 이벤트 self‑heal과 프로젝트 탐색 리팩터링, 서버의 프로젝트 transfer API·로직·테스트, 프런트 훅·UI, 공유 스키마·타입, 관련 문서·테스트를 포함한 전반적 보안·운영 통합을 도입합니다. (요약 50단어 이내)

Changes

Strix CI 통합 시스템

Layer / File(s) Summary
워크플로우 설정·트리거·컨커런시
.github/workflows/strix.yml
Strix 스캔 워크플로우 추가: PR/PR review/workflow_run/schedule/dispatch 트리거, 이벤트별 concurrency key, permissions 및 시크릿 게이팅/enable 결정 로직을 정의.
Quick‑gate 런타임·입력 검증·실행 제어
scripts/ci/strix_quick_gate.sh, .github/workflows/strix.yml
quick gate 스크립트: 입력/파일/타임아웃/스캔 모드 검증, PR 컨텍스트 직렬화, bounded/full scope 처리, retry·fallback·severity 기반 게이팅, 아티팩트 퍼블리시 및 exit 코드 정책 구현.
workflow_run PR head 안전 준비
.github/workflows/strix.yml (Python tar 처리 단계)
workflow_run에서 PR head tarball 다운로드 및 Python으로 안전 검사(심링크/하드링크/절대경로/경로 traversal 차단) 후 ./strix-pr-head 구성.
모델/자격 게이팅·키 파일 준비
.github/workflows/strix.yml, scripts/ci/strix_model_utils.sh
모델 정규화/Vertex 판별, LLM/GCP/GitHub 토큰 필요성 결정, 비밀 트림/마스킹, umask 077 기반 입력 파일 생성 및 env export 로직.
Strix 실행·quick run 및 결과 처리
.github/workflows/strix.yml, scripts/ci/strix_quick_gate.sh
quick run 환경 구성(폴백/timeout), scripts/ci/strix_quick_gate.sh 호출, PR‑associated는 continue-on-error, 결과 요약·단계별 exit 규칙, strix_runs/ 아티팩트 업로드 보장.
CI 파이프라인 의존성 파일
requirements-strix-ci.*
CI에서 사용하는 Python 패키지(스트릭스/Vertex SDK) 및 override 버전 고정 파일 추가/갱신.

보조 보안 워크플로우

Layer / File(s) Summary
Dependency Review 워크플로우
.github/workflows/dependency-review.yml
actions/dependency-review-action@v4 기반 PR 대상 의존성 리뷰 워크플로우 추가(대상 브랜치: main, fail-on-severity: moderate).
OSV Scanner 워크플로우
.github/workflows/osvscanner.yml
google/osv-scanner-action를 사용한 재귀 OSV 스캔 워크플로우 추가.

CI 유틸: 모델 정규화

Layer / File(s) Summary
모델/프로바이더 정규화 유틸
scripts/ci/strix_model_utils.sh
normalize_model, Vertex 경로 판별, provider 토큰/식별자 검증, 모델 의존 자격 요구 판정 등 쉘 헬퍼 추가(입력 트림/검증/오류 코드 규약).

CLI — 이벤트 self‑heal 및 프로젝트 검색 리팩터링

Layer / File(s) Summary
프로젝트 탐색 리팩터링
packages/cli/src/lib/project.ts, packages/cli/src/lib/project.test.ts
findProjectConfigWithPath(startDir?) 추가: 절대 경로 정규화, 상위 탐색, configconfigPath 함께 반환; 기존 findProjectConfig는 래퍼로 유지.
sendEventBackground → opts API 및 detached self‑heal
packages/cli/src/lib/event-sender.ts, packages/cli/src/lib/event-sender.test.ts
SendEventBackgroundOpts 도입, buildSelfHealScript로 inline detached 스크립트 생성, 202 응답의 project 검증·교차‑프로젝트/레이스 가드·원자적 .argos/project.json 갱신 및 정적 테스트 추가.
deps/adapters 시그니처·어댑터 변경
packages/cli/src/deps.ts, packages/cli/src/adapters.ts
ExternalDeps.project.findWithPath 추가, events.sendBackground(opts) 시그니처로 변경 및 어댑터에서 래핑 제공.
hook 호출부와 테스트 갱신
packages/cli/src/commands/hook.ts, packages/cli/src/__tests__/*
findWithPath 사용으로 projectJsonPath/currentConfig 수집 후 sendBackground에 전달; 관련 유닛 테스트 확장 및 목 갱신.

서버 — 프로젝트 transfer 기능 및 events 응답 확장

Layer / File(s) Summary
Server action: transferProjectForUser
packages/web/src/lib/server/project-actions.ts, packages/web/src/lib/server/project-actions.test.ts
transferProjectForUser 추가: 존재·권한 검증, same_org no‑op, db.$transaction 내 권한 재검증·projectMember.deleteMany·project.update(orgId), Prisma P2002/P2025 에러 매핑, 광범위 단위 테스트 추가.
Transfer 라우트 추가
packages/web/src/app/api/projects/[projectId]/transfer/route.ts
POST /api/projects/:projectId/transfer 라우트 추가(요청 검증→server action 호출→kind→HTTP 매핑, runtime/dynamic 설정, createdAt ISO 직렬화 보장 포인트).
/api/events 응답 확장 및 테스트
packages/web/src/app/api/events/route.ts, packages/web/src/app/api/events/route.test.ts
성공(202) 응답을 IngestEventResponse 형태로 { ok: true, project: { id, orgId, orgSlug } } 확장(4xx는 정보 누설하지 않음) 및 관련 테스트 추가.
프런트 훅·UI 통합
packages/web/src/hooks/use-transfer-project.ts, packages/web/src/app/dashboard/[orgSlug]/settings/projects/page.tsx
useTransferProject 훅 추가: mutation과 캐시 무효화, TransferProjectPanel 도입: OWNER 후보 필터링, confirm, 에러(403/404/409) 처리 및 성공 라우팅.
공유 타입·스키마
packages/shared/src/schemas/project.ts, packages/shared/src/types/*.ts
TransferProjectSchema, TransferProjectResponse, IngestEventResponse 추가로 API 계약 확장.

문서·프로세스·유스케이스 카탈로그

Layer / File(s) Summary
ADR / Plan / WU / QA / Review 문서
docs/adr.md, docs/tasks/2026-05-14-project-transfer-org/*
ADR‑013~022 및 WU별 구현/검증/QA/리뷰 문서 일괄 추가·정리.
유스케이스 카탈로그·ID 레지스트리
docs/usecases/README.md, docs/usecases/_ids.yaml, docs/usecases/*
유스케이스 운영 규약 문서 및 UC‑CLI‑001, UC‑PROJ‑001 등 카탈로그 항목 추가.
CLAUDE 작업 규약 보강
.claude/*
finalize/UC 승격, 절대 경로 실행, typecheck self‑check 등 작업 규약 강화 문서 추가.

Sequence Diagram(s)

sequenceDiagram
  participant GH as GitHub Actions
  participant Runner as Runner
  participant Gate as Quick Gate Script
  participant Strix as Strix Scanner
  participant Web as Web API
  participant CLI as CLI Detached Child

  GH->>Runner: 워크플로우 트리거·체크아웃
  Runner->>Gate: quick gate 실행 (환경/모델/자격검증)
  Gate->>Strix: 스캔 실행 (run_strix_once)
  Strix-->>Gate: 리포트 반환
  Gate->>Runner: 결과 요약·아티팩트 준비
  Runner->>Web: POST /api/events (normal flow)
  Web-->>Runner: 202 + project (IngestEventResponse)
  Runner->>CLI: spawn detached self-heal (payload + projectJsonPath)
  CLI->>CLI: detached child: 응답 검증 → `.argos/project.json` atomically 업데이트
Loading

코드 검토 노력 예상도

🎯 4 (Complex) | ⏱️ ~45 minutes

"당근 심은 러비트가 전해요:
게이트는 단단히, 시크릿은 조심히,
모델은 깔끔히 정리하고 스캔은 부지런히,
리포트는 남기고 파일은 안전히 바꿔요,
작은 발자국 위에 큰 평화가 깃들길 🥕🐇"

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-strix-pipeline
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch add-strix-pipeline

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
scripts/ci/strix_model_utils.sh (1)

75-77: 💤 Low value

빈 모델 입력에 대한 처리를 검토하세요.

model 값을 조용히 허용하고 있습니다. 호출 코드에서 빈 모델 값이 유효한 경우인지 확인하세요. 만약 빈 모델이 항상 오류여야 한다면 return 1을 사용하는 것이 더 안전합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/ci/strix_model_utils.sh` around lines 75 - 77, The current check
silently accepts an empty model by returning 0 in the if [ -z "$model" ] block;
decide whether an empty model should be treated as an error and, if so, change
the branch to return 1 instead of return 0, and update or add a clear error log
message (e.g., using echo or a logger) before returning; also audit all call
sites that pass the model variable to ensure they intentionally allow empty
models and update their handling if you make this a hard error.
.github/workflows/strix.yml (1)

4-6: ⚡ Quick win

모든 브랜치에서 푸시 시 워크플로우가 실행됩니다.

현재 설정은 모든 브랜치에서 푸시 시 Strix 스캔을 실행합니다. 이로 인해 다음과 같은 영향이 있습니다:

  • 개인 feature 브랜치에서도 스캔 실행
  • GitHub Actions 사용 시간 소모 증가
  • 잠재적으로 불필요한 스캔 실행

보호된 브랜치(예: main, develop)나 특정 브랜치 패턴으로 제한하는 것을 고려하세요:

branches:
  - main
  - develop
  - 'release/**'

또는 현재 설정이 의도된 것이라면 이 코멘트를 무시하세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/strix.yml around lines 4 - 6, 현재 push trigger가 branches: -
'**' 로 설정되어 모든 브랜치에서 스캔이 실행되므로 불필요한 실행이 발생합니다; 수정하려면
.github/workflows/strix.yml의 push.branches 설정(현재 패턴 '**')을 보호된 브랜치들만 포함하도록 변경하세요
— 예: main, develop 및 'release/**' 패턴(또는 팀의 규칙에 맞는 다른 브랜치 패턴)으로 제한하거나 필요 시 수동
트리거(workflow_dispatch)만 허용하도록 구성하면 됩니다.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/strix.yml:
- Around line 224-226: The default model name written to the strix LLM file is
incorrectly formatted; update the printf call that currently writes
"gemini/gemini-pro-3.1-preview" (the string in the diff referencing
"$strix_llm_file") so it writes the correct model identifier
"gemini-3.1-pro-preview" instead, preserving the same printf and file write
logic but replacing the bad model string with the correct one.

In `@scripts/ci/strix_quick_gate.sh`:
- Around line 778-781: The script variable required in
scripts/ci/strix_quick_gate.sh lists two workflow paths that do not exist;
either create the missing files at .github/workflows/dependency-review.yml and
.github/workflows/osvscanner.yml with the expected SCA workflows, or update the
required map (variable required) to point to the correct existing workflow paths
(or replace the hardcoded map with a configurable env var or config value) so
the script references valid files; ensure the change touches the required
variable and any lookup logic that validates those paths.

---

Nitpick comments:
In @.github/workflows/strix.yml:
- Around line 4-6: 현재 push trigger가 branches: - '**' 로 설정되어 모든 브랜치에서 스캔이 실행되므로
불필요한 실행이 발생합니다; 수정하려면 .github/workflows/strix.yml의 push.branches 설정(현재 패턴 '**')을
보호된 브랜치들만 포함하도록 변경하세요 — 예: main, develop 및 'release/**' 패턴(또는 팀의 규칙에 맞는 다른 브랜치
패턴)으로 제한하거나 필요 시 수동 트리거(workflow_dispatch)만 허용하도록 구성하면 됩니다.

In `@scripts/ci/strix_model_utils.sh`:
- Around line 75-77: The current check silently accepts an empty model by
returning 0 in the if [ -z "$model" ] block; decide whether an empty model
should be treated as an error and, if so, change the branch to return 1 instead
of return 0, and update or add a clear error log message (e.g., using echo or a
logger) before returning; also audit all call sites that pass the model variable
to ensure they intentionally allow empty models and update their handling if you
make this a hard error.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 945e4de4-8a37-4bf7-8a0b-b9b38b467b4c

📥 Commits

Reviewing files that changed from the base of the PR and between 8640510 and d99a4ed.

📒 Files selected for processing (5)
  • .github/workflows/strix.yml
  • requirements-strix-ci.txt
  • scripts/ci/strix_model_utils.sh
  • scripts/ci/strix_quick_gate.sh
  • scripts/ci/test_strix_quick_gate.sh

Comment thread .github/workflows/strix.yml Outdated
Comment thread scripts/ci/strix_quick_gate.sh
greatSumini and others added 3 commits May 14, 2026 22:02
- 출발/대상 organization OWNER 양쪽 권한을 충족할 때 project 를 다른 org 로
  이동시키는 기능 추가. 트랜잭션 내 OWNER 재SELECT 로 race 방지, ProjectMember
  레코드는 transfer 시 모두 삭제.
- 신규 `POST /api/projects/[projectId]/transfer` route + server action
  `transferProjectForUser`. slug 충돌은 409 + `PROJECT_SLUG_CONFLICT` 로 매핑
  (자동 rename 안 함).
- 프로젝트 settings 화면에 OWNER 한정 Transfer 카드 추가.
- `/api/events` 응답을 `{ ok, project: { id, orgId, orgSlug } }` superset 으로
  확장하고, CLI 가 detached 자식에서 `.argos/project.json` 을 atomic rewrite
  하도록 self-heal 흐름 추가. 4xx 응답에는 self-heal payload 미포함.

Co-Authored-By: Claude <noreply@anthropic.com>
project-transfer-org task 의 10개 결정 항목:
- ADR-013: 별도 `POST /api/projects/[projectId]/transfer` 라우트 분리
- ADR-014: CLI self-heal 채널은 `/api/events` 응답 확장
- ADR-015: slug 충돌 시 409 + 안내, 자동 rename 없음
- ADR-016: 단일 `db.\$transaction` + 트랜잭션 내 OWNER 재검증
- ADR-017: same_org transfer 는 트랜잭션 skip (idempotent no-op)
- ADR-018: 권한 체크는 server action 내부에서
- ADR-019: self-heal payload 는 202 응답에만 포함
- ADR-020: events 응답 확장은 superset (구버전 CLI 후방 호환)
- ADR-021: CLI self-heal 자식 스크립트는 inline 확장
- ADR-022: self-heal 발생 시 사용자 알림은 git diff 만

Co-Authored-By: Claude <noreply@anthropic.com>
new-task 5단계 파이프라인 산출물 (clarify/context/plan/implement/qa/review).

Co-Authored-By: Claude <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented May 14, 2026

Copy link
Copy Markdown

Greptile Summary

이 PR은 두 가지 주요 기능을 추가합니다: (1) 프로젝트를 다른 org로 이전하는 UI/API (TransferProject), (2) CLI가 이벤트를 전송할 때 서버 응답의 orgSlug.argos/project.json에 자동으로 반영하는 백그라운드 자가치유(self-heal) 메커니즘.

  • 프로젝트 이전: /api/projects/:id/transfer 엔드포인트를 신설하고 transferProjectForUser 서버 액션에서 트랜잭션 내 이중 권한 재검증, ProjectMember 일괄 삭제, 원자적 orgId 갱신을 수행합니다.
  • CLI 자가치유: sendEventBackground를 opts 기반으로 리팩터링하고, 디태치드 child 프로세스가 /api/events 202 응답의 project.orgSlug를 읽어 project.json을 원자적 rename 방식으로 갱신합니다. 여기에 inter-process lock(mkdirSync 기반), 재독 race 보호, cross-project 오염 가드가 포함됩니다.
  • Strix CI 파이프라인: Strix 코드 리뷰 자동화 워크플로우와 OSV/Dependency Review 워크플로우를 추가합니다.

Confidence Score: 3/5

핵심 데이터 쓰기 경로(프로젝트 이전)에 동시성 문제가 있어 바로 병합하기는 어렵습니다.

트랜잭션 내 P2025 에러가 forbidden으로 매핑되어 실제 충돌인지 권한 부족인지 클라이언트가 구분할 수 없고, same_org 조기 반환 이전의 외부 read와 트랜잭션 진입 사이의 짧은 TOCTOU 구간에서 다른 세션이 이전을 완료했을 때도 동일한 문제가 발생합니다. 이 두 이슈는 프로젝트 소유권이라는 중요 데이터의 오류 신호를 왜곡합니다.

packages/web/src/lib/server/project-actions.ts의 P2025 에러 매핑과 동시 이전 충돌 처리를 중점적으로 확인하세요.

Important Files Changed

Filename Overview
packages/web/src/lib/server/project-actions.ts Adds transferProjectForUser with transaction-internal permission re-verification; concurrent-transfer race and P2025→forbidden mapping issues were flagged in previous threads
packages/web/src/app/api/projects/[projectId]/transfer/route.ts New transfer endpoint with auth guard, Zod validation, and discriminated result handling; correctly delegates to project-actions
packages/cli/src/lib/event-sender.ts Adds self-heal script builder for background child process; lock acquisition, race protection re-read, and atomic write are all correctly implemented
packages/web/src/app/dashboard/[orgSlug]/settings/projects/page.tsx Adds TransferProjectPanel component with org selector and confirm dialog; uses window.confirm for destructive action instead of a modal
packages/web/src/app/api/events/route.ts 202 response now includes project.id, orgId, orgSlug for CLI self-heal; select projection changed from include to select for efficiency
.github/workflows/strix.yml New Strix CI workflow; multiple issues flagged in previous threads (dev branch in trigger, hardcoded model, missing workflow_dispatch in fail-closed gate, non-existent workflow references)

Sequence Diagram

sequenceDiagram
    participant Claude as Claude Code (Hook)
    participant CLI as argos-cli (hook.ts)
    participant Child as 백그라운드 Child Process
    participant API as /api/events (Next.js)
    participant TransferAPI as /api/projects/:id/transfer
    participant DB as Prisma / PostgreSQL
    participant FS as .argos/project.json

    Claude->>CLI: Hook 이벤트 (PreToolUse 등)
    CLI->>FS: findProjectConfigWithPath()
    FS-->>CLI: "{ config, configPath }"
    CLI->>Child: spawn(node -e script) detached
    CLI-->>Claude: exit 0 (즉시 반환)

    Note over Child,FS: 백그라운드 자가치유 흐름
    Child->>API: POST /api/events (Bearer token)
    API->>DB: project.findUnique + 멤버십 확인
    DB-->>API: "project { id, orgId, orgSlug }"
    API-->>Child: "202 { ok, project: { id, orgId, orgSlug } }"
    Child->>FS: lockDir 획득 (mkdirSync)
    Child->>FS: project.json 재독(race 보호)
    alt orgId/orgSlug 변경됨
        Child->>FS: atomic write (tmp + renameSync)
        Child->>FS: lockDir 해제 (rmdirSync)
    else 이미 최신
        Child->>FS: lockDir 해제 (no-op)
    end

    Note over CLI,TransferAPI: 수동 이전 흐름 (UI)
    actor User
    User->>TransferAPI: "POST /api/projects/:id/transfer { targetOrgSlug }"
    TransferAPI->>DB: project + org 멤버십 조회
    DB-->>TransferAPI: 권한 확인
    TransferAPI->>DB: $transaction(재검증 + project.update + projectMember.deleteMany)
    DB-->>TransferAPI: 업데이트된 project
    TransferAPI-->>User: "200 { project: { id, orgId, orgSlug, ... } }"
Loading

Reviews (16): Last reviewed commit: "Support GitHub Models in Strix scans" | Re-trigger Greptile

Comment thread scripts/ci/strix_model_utils.sh Outdated
Comment thread .github/workflows/strix.yml Outdated
Comment thread scripts/ci/test_strix_quick_gate.sh Outdated
Comment thread .github/workflows/strix.yml
Comment thread .github/workflows/strix.yml Outdated
Comment thread scripts/ci/strix_quick_gate.sh Outdated
@seonghobae

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Comment thread .github/workflows/strix.yml Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/ci/strix_model_utils.sh (1)

5-14: 💤 Low value

SC2295: 패턴 매칭에서 변수 확장 시 별도 인용 필요

Lines 11-12에서 ${value%%[!$space]*} 패턴의 $space 변수가 인용되지 않아, 의도치 않게 패턴 문자로 해석될 수 있습니다. 현재 코드는 동작하지만, 명시적 인용으로 안전성을 높일 수 있습니다.

♻️ 제안된 수정
-	value="${value#"${value%%[!$space]*}"}"
-	value="${value%"${value##*[!$space]}"}"
+	value="${value#"${value%%[!"$space"]*}"}"
+	value="${value%"${value##*[!"$space"]}"}"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/ci/strix_model_utils.sh` around lines 5 - 14, The trim_whitespace
function uses unquoted variable expansions in pattern matches (the occurrences
of ${value%%[!$space]*} and ${value##*[!$space]}) which can let $space be
misinterpreted as pattern characters; update those expansions to quote the
$space variable inside the bracket-expression (e.g., use the form that embeds
$space as ${space} inside the [!...] patterns) so both the leading-trim and
trailing-trim lines in trim_whitespace safely treat the whitespace characters as
literals.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@scripts/ci/strix_model_utils.sh`:
- Around line 5-14: The trim_whitespace function uses unquoted variable
expansions in pattern matches (the occurrences of ${value%%[!$space]*} and
${value##*[!$space]}) which can let $space be misinterpreted as pattern
characters; update those expansions to quote the $space variable inside the
bracket-expression (e.g., use the form that embeds $space as ${space} inside the
[!...] patterns) so both the leading-trim and trailing-trim lines in
trim_whitespace safely treat the whitespace characters as literals.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c9fd7c2e-defa-40fc-8076-f23e7b0cb778

📥 Commits

Reviewing files that changed from the base of the PR and between 2361fa9 and d33ab58.

📒 Files selected for processing (4)
  • .github/workflows/strix.yml
  • scripts/ci/strix_model_utils.sh
  • scripts/ci/strix_quick_gate.sh
  • scripts/ci/test_strix_quick_gate.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/ci/strix_quick_gate.sh

@seonghobae

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@seonghobae

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@seonghobae

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Comment thread .github/workflows/strix.yml Fixed
Comment thread .github/workflows/strix.yml Fixed
Comment thread .github/workflows/osvscanner.yml Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/osvscanner.yml (1)

20-20: ⚡ Quick win

3rd party 액션을 특정 commit hash로 고정하세요.

google/osv-scanner-action/osv-scanner-action@v2는 GitHub 공식 액션이 아니므로, 공급망 보안을 위해 태그 대신 commit SHA로 고정하는 것이 좋습니다. 최신 v2.3.5 릴리스의 commit hash는 9eebeaea7417372f39d21f50ad5ef4e6b3358566입니다.

권장 변경:

uses: google/osv-scanner-action/osv-scanner-action@9eebeaea7417372f39d21f50ad5ef4e6b3358566
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/osvscanner.yml at line 20, Replace the floating tag
reference "google/osv-scanner-action/osv-scanner-action@v2" with the specific
commit SHA to pin the third‑party GitHub Action; update the uses entry for
google/osv-scanner-action/osv-scanner-action to use the provided commit hash
9eebeaea7417372f39d21f50ad5ef4e6b3358566 (i.e., change the `@v2` suffix to
`@9eebeaea7417372f39d21f50ad5ef4e6b3358566`) so the workflow uses an immutable
action version.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/ci/strix_quick_gate.sh`:
- Around line 2264-2285: The is_timeout_error function contains duplicated grep
checks for the same patterns; remove the repeated blocks so each unique check
appears only once (keep checks for 'litellm.exceptions.Timeout',
'litellm.APIConnectionError', and 'Strix run timed out after' against the
"$STRIX_LOG" file), ensure each match returns 0, and leave a single fallback
(e.g., return 1) if none match; this will eliminate the copy-paste duplicates
while preserving the intended behavior.

---

Nitpick comments:
In @.github/workflows/osvscanner.yml:
- Line 20: Replace the floating tag reference
"google/osv-scanner-action/osv-scanner-action@v2" with the specific commit SHA
to pin the third‑party GitHub Action; update the uses entry for
google/osv-scanner-action/osv-scanner-action to use the provided commit hash
9eebeaea7417372f39d21f50ad5ef4e6b3358566 (i.e., change the `@v2` suffix to
`@9eebeaea7417372f39d21f50ad5ef4e6b3358566`) so the workflow uses an immutable
action version.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8cb71d5b-ab5f-45b3-a895-089d7ba4c0bd

📥 Commits

Reviewing files that changed from the base of the PR and between 1b10986 and e8dfa2a.

📒 Files selected for processing (5)
  • .github/workflows/dependency-review.yml
  • .github/workflows/osvscanner.yml
  • .github/workflows/strix.yml
  • scripts/ci/strix_quick_gate.sh
  • scripts/ci/test_strix_quick_gate.sh
✅ Files skipped from review due to trivial changes (1)
  • .github/workflows/dependency-review.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/strix.yml

Comment on lines +2264 to +2285
is_timeout_error() {
# Tier 1: litellm SDK timeout — provider-specific, always trusted.
if grep -Fq 'litellm.exceptions.Timeout' "$STRIX_LOG"; then
return 0
fi

if grep -Fq 'litellm.APIConnectionError' "$STRIX_LOG"; then
return 0
fi

if grep -Fq 'Strix run timed out after' "$STRIX_LOG"; then
return 0
fi

if grep -Fq 'litellm.APIConnectionError' "$STRIX_LOG"; then
return 0
fi

if grep -Fq 'Strix run timed out after' "$STRIX_LOG"; then
return 0
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

is_timeout_error 함수에 중복 코드가 있습니다.

Lines 2270-2272와 2278-2280이 동일하고, Lines 2274-2276과 2282-2284도 동일합니다. 복사-붙여넣기 실수로 보입니다.

🔧 중복 코드 제거 제안
 is_timeout_error() {
 	# Tier 1: litellm SDK timeout — provider-specific, always trusted.
 	if grep -Fq 'litellm.exceptions.Timeout' "$STRIX_LOG"; then
 		return 0
 	fi

 	if grep -Fq 'litellm.APIConnectionError' "$STRIX_LOG"; then
 		return 0
 	fi

 	if grep -Fq 'Strix run timed out after' "$STRIX_LOG"; then
 		return 0
 	fi

-	if grep -Fq 'litellm.APIConnectionError' "$STRIX_LOG"; then
-		return 0
-	fi
-
-	if grep -Fq 'Strix run timed out after' "$STRIX_LOG"; then
-		return 0
-	fi
-
 	# Tier 2a: httpx transport timeout — requires LLM provider marker.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
is_timeout_error() {
# Tier 1: litellm SDK timeout — provider-specific, always trusted.
if grep -Fq 'litellm.exceptions.Timeout' "$STRIX_LOG"; then
return 0
fi
if grep -Fq 'litellm.APIConnectionError' "$STRIX_LOG"; then
return 0
fi
if grep -Fq 'Strix run timed out after' "$STRIX_LOG"; then
return 0
fi
if grep -Fq 'litellm.APIConnectionError' "$STRIX_LOG"; then
return 0
fi
if grep -Fq 'Strix run timed out after' "$STRIX_LOG"; then
return 0
fi
is_timeout_error() {
# Tier 1: litellm SDK timeout — provider-specific, always trusted.
if grep -Fq 'litellm.exceptions.Timeout' "$STRIX_LOG"; then
return 0
fi
if grep -Fq 'litellm.APIConnectionError' "$STRIX_LOG"; then
return 0
fi
if grep -Fq 'Strix run timed out after' "$STRIX_LOG"; then
return 0
fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/ci/strix_quick_gate.sh` around lines 2264 - 2285, The
is_timeout_error function contains duplicated grep checks for the same patterns;
remove the repeated blocks so each unique check appears only once (keep checks
for 'litellm.exceptions.Timeout', 'litellm.APIConnectionError', and 'Strix run
timed out after' against the "$STRIX_LOG" file), ensure each match returns 0,
and leave a single fallback (e.g., return 1) if none match; this will eliminate
the copy-paste duplicates while preserving the intended behavior.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/osvscanner.yml:
- Line 18: 현재 워크플로우의 리포지토 체크아웃 액션 참조(actions/checkout@v4)가 mutable 태그를 사용하므로 공급망
무결성 위험이 있습니다; 해당 참조를 불변 커밋 SHA로 교체하여 고정하세요: 사용 중인 actions/checkout@v4를
actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5로 바꿔 커밋 SHA로 고정하도록
수정합니다.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 60ccd9e1-5229-433a-93ed-5edb18e4bc76

📥 Commits

Reviewing files that changed from the base of the PR and between e8dfa2a and 50e6e2a.

📒 Files selected for processing (1)
  • .github/workflows/osvscanner.yml

Comment thread .github/workflows/osvscanner.yml Outdated
Comment thread scripts/ci/test_strix_quick_gate.sh
Comment thread packages/cli/src/lib/event-sender.ts Fixed
Comment thread packages/web/src/lib/server/project-actions.ts
Comment thread packages/web/src/lib/server/project-actions.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.claude/agents/new-task-usecase.md:
- Around line 78-85: The fenced code block in .claude/agents/new-task-usecase.md
is missing a language tag, triggering markdownlint MD040; update the opening
fence (the triple backticks that start the block containing "Promoted UCs for
task <slug>: ...") to include a language identifier such as text (e.g.,
```text). Ensure any other fenced blocks in the same file also include an
explicit language to satisfy MD040.

In @.claude/skills/new-task/SKILL.md:
- Around line 198-203: The fenced code block showing the Agent invocation
(Agent({...})) lacks a language tag and triggers markdownlint MD040; update that
code fence to include a language identifier (for example "text" or "javascript")
so the block starts with ```text (or ```javascript) to remove the lint warning
while leaving the Agent({ subagent_type: "new-task-usecase", prompt: task_slug,
clarify_path, plan_path, evaluate_path 전달 }) contents unchanged.
- Around line 194-197: The document's overall step count at the top still states
"5단계" while you added "Step 6 — UC 카탈로그 승격 (foreground)"; update the top-level
description/heading that references "5단계" to "6단계" so the summary matches the
new steps, and scan for any other occurrences of the phrase "5단계" in the same
file (e.g., in the introduction, overview, or TOC) and replace them with "6단계"
to keep numbering consistent with the new "Step 6 — UC 카탈로그 승격 (foreground)"
section.

In `@docs/tasks/2026-05-14-project-transfer-org/05-qa.md`:
- Around line 37-38: The CI typecheck fails because the test-local TxClient type
in src/lib/server/project-actions.test.ts does not match Prisma's
TransactionClient signature (TS2345); update the test so TxClient either uses
Prisma's TransactionClient type (import type { Prisma } from '@prisma/client'
and type TxClient = Prisma.TransactionClient) or reshape the mock to implement
the exact methods/overloads Prisma.TransactionClient expects (or explicitly cast
the mock to unknown as Prisma.TransactionClient) and ensure any helper functions
in project-actions.test.ts that accept TxClient reflect that type change so pnpm
--filter `@argos/web` typecheck passes.
- Around line 5-26: The markdown file contains a fenced code block in
docs/tasks/2026-05-14-project-transfer-org/05-qa.md that lacks a language
specifier, triggering markdownlint MD040; update the opening fence from ``` to
```text (or another appropriate language) so the block is annotated (ensure the
closing ``` remains unchanged) and commit the change to eliminate the lint
warning.

In `@docs/usecases/README.md`:
- Around line 7-18: The top README code fences in docs/usecases/README.md are
missing a language tag which triggers markdownlint MD040; update each
triple-backtick fence (the initial directory list fence and the later "주 성공
시나리오" fence near the example) to include a language (e.g., replace ``` with
```text for the directory list and ```markdown for the scenario list) so the
lint warning is resolved while preserving the intended rendering.

In `@packages/cli/src/lib/project.ts`:
- Around line 22-25: The function findProjectConfigWithPath can return a
relative configPath when startDir is provided as a relative path; normalize the
starting directory to an absolute path before walking up. Replace the currentDir
initialization to resolve the startDir (or fallback to process.cwd()) using
path.resolve (or equivalent) so currentDir and any returned configPath are
absolute; update references to currentDir, startDir, and configPath accordingly.

In `@packages/web/package.json`:
- Line 29: The package.json shows a major-version mismatch between next
(^15.5.18) and eslint-config-next (^16.2.6); update package.json so their major
versions match — either bump next to ^16.x or (preferably for minimal change)
change eslint-config-next to a ^15.x release that aligns with next (update the
"eslint-config-next" dependency entry), then run install and test to verify
lint/build still work.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 62532219-21b8-43a4-836f-ef1ea951ab20

📥 Commits

Reviewing files that changed from the base of the PR and between 7bad4f6 and 1ce496f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (56)
  • .claude/agents/new-task-clarify.md
  • .claude/agents/new-task-implement.md
  • .claude/agents/new-task-usecase.md
  • .claude/skills/new-task/SKILL.md
  • docs/adr.md
  • docs/tasks/2026-05-14-project-transfer-org/01-clarify-round-1.md
  • docs/tasks/2026-05-14-project-transfer-org/01-clarify-round-2.md
  • docs/tasks/2026-05-14-project-transfer-org/01-clarify.md
  • docs/tasks/2026-05-14-project-transfer-org/02-context.md
  • docs/tasks/2026-05-14-project-transfer-org/03-plan-critique-1.md
  • docs/tasks/2026-05-14-project-transfer-org/03-plan-critique-2.md
  • docs/tasks/2026-05-14-project-transfer-org/03-plan.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-1.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-2.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-3.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-4.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-5.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-6.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-7.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-8.md
  • docs/tasks/2026-05-14-project-transfer-org/05-qa.md
  • docs/tasks/2026-05-14-project-transfer-org/05-review.md
  • docs/tasks/2026-05-14-project-transfer-org/_conversation.md
  • docs/tasks/2026-05-14-project-transfer-org/_pipeline-improvements.md
  • docs/usecases/README.md
  • docs/usecases/_ids.yaml
  • docs/usecases/cli/UC-CLI-001-self-heal-project-config.md
  • docs/usecases/project/UC-PROJ-001-transfer-project.md
  • package.json
  • packages/cli/package.json
  • packages/cli/src/__tests__/default-command.test.ts
  • packages/cli/src/__tests__/hook-command.test.ts
  • packages/cli/src/__tests__/setup-command.test.ts
  • packages/cli/src/adapters.ts
  • packages/cli/src/commands/hook.ts
  • packages/cli/src/deps.ts
  • packages/cli/src/lib/event-sender.test.ts
  • packages/cli/src/lib/event-sender.ts
  • packages/cli/src/lib/project.ts
  • packages/shared/src/schemas/project.ts
  • packages/shared/src/types/events.ts
  • packages/shared/src/types/project.ts
  • packages/web/package.json
  • packages/web/src/app/api/events/route.test.ts
  • packages/web/src/app/api/events/route.ts
  • packages/web/src/app/api/projects/[projectId]/transfer/route.ts
  • packages/web/src/app/dashboard/[orgSlug]/settings/projects/page.tsx
  • packages/web/src/components/dashboard/session-activity-ribbon.tsx
  • packages/web/src/components/org/create-org-modal.tsx
  • packages/web/src/components/org/create-project-modal.tsx
  • packages/web/src/components/org/delete-org-modal.tsx
  • packages/web/src/components/org/delete-project-modal.tsx
  • packages/web/src/components/org/rename-project-modal.tsx
  • packages/web/src/hooks/use-transfer-project.ts
  • packages/web/src/lib/server/project-actions.test.ts
  • packages/web/src/lib/server/project-actions.ts
✅ Files skipped from review due to trivial changes (31)
  • packages/cli/package.json
  • packages/web/src/components/org/delete-org-modal.tsx
  • packages/web/src/components/org/create-project-modal.tsx
  • packages/web/src/components/org/create-org-modal.tsx
  • package.json
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-7.md
  • packages/shared/src/types/events.ts
  • .claude/agents/new-task-implement.md
  • packages/shared/src/schemas/project.ts
  • packages/web/src/app/api/events/route.test.ts
  • docs/tasks/2026-05-14-project-transfer-org/02-context.md
  • packages/web/src/components/org/delete-project-modal.tsx
  • packages/web/src/components/org/rename-project-modal.tsx
  • docs/tasks/2026-05-14-project-transfer-org/03-plan-critique-2.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-2.md
  • packages/web/src/components/dashboard/session-activity-ribbon.tsx
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-8.md
  • docs/tasks/2026-05-14-project-transfer-org/01-clarify-round-1.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-4.md
  • docs/tasks/2026-05-14-project-transfer-org/01-clarify-round-2.md
  • docs/tasks/2026-05-14-project-transfer-org/_pipeline-improvements.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-1.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-6.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-3.md
  • docs/usecases/cli/UC-CLI-001-self-heal-project-config.md
  • docs/tasks/2026-05-14-project-transfer-org/_conversation.md
  • docs/tasks/2026-05-14-project-transfer-org/04-implement-WU-5.md
  • docs/adr.md
  • docs/tasks/2026-05-14-project-transfer-org/05-review.md
  • docs/tasks/2026-05-14-project-transfer-org/03-plan.md
  • docs/tasks/2026-05-14-project-transfer-org/03-plan-critique-1.md

Comment on lines +78 to +85
```
Promoted UCs for task <slug>:
- NEW UC-PROJ-002 docs/usecases/project/UC-PROJ-002-transfer-project.md
- UPDATE UC-CLI-001 docs/usecases/cli/UC-CLI-001-hook-resolve-project.md (last_reviewed 갱신)
Registry updated: docs/usecases/_ids.yaml
Open questions for main session:
- (있으면 1~3줄, 없으면 생략)
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

코드블록 fence에 언어가 없어 markdownlint(MD040) 경고가 발생합니다.

해당 fenced block 시작 줄에 언어를 명시해 주세요.

🔧 제안 수정안
-```
+```text
 Promoted UCs for task <slug>:
 - NEW   UC-PROJ-002  docs/usecases/project/UC-PROJ-002-transfer-project.md
 - UPDATE UC-CLI-001  docs/usecases/cli/UC-CLI-001-hook-resolve-project.md (last_reviewed 갱신)
 Registry updated: docs/usecases/_ids.yaml
 Open questions for main session:
 - (있으면 1~3줄, 없으면 생략)
</details>

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.22.1)</summary>

[warning] 78-78: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/agents/new-task-usecase.md around lines 78 - 85, The fenced code
block in .claude/agents/new-task-usecase.md is missing a language tag,
triggering markdownlint MD040; update the opening fence (the triple backticks
that start the block containing "Promoted UCs for task : ...") to include
a language identifier such as text (e.g., ```text). Ensure any other fenced
blocks in the same file also include an explicit language to satisfy MD040.


</details>

<!-- fingerprinting:phantom:poseidon:hawk -->

<!-- This is an auto-generated comment by CodeRabbit -->

Comment thread .claude/skills/new-task/SKILL.md
Comment on lines +198 to +203
```
Agent({
subagent_type: "new-task-usecase",
prompt: task_slug, clarify_path, plan_path, evaluate_path 전달
})
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

펜스 코드 블록 언어가 없어 markdownlint 경고가 납니다.

해당 블록에 언어를 지정해 lint 경고(MD040)를 제거해 주세요.

🔧 제안 수정
-```
+```text
 Agent({
   subagent_type: "new-task-usecase",
   prompt: task_slug, clarify_path, plan_path, evaluate_path 전달
 })
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 198-198: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.claude/skills/new-task/SKILL.md around lines 198 - 203, The fenced code
block showing the Agent invocation (Agent({...})) lacks a language tag and
triggers markdownlint MD040; update that code fence to include a language
identifier (for example "text" or "javascript") so the block starts with ```text
(or ```javascript) to remove the lint warning while leaving the Agent({
subagent_type: "new-task-usecase", prompt: task_slug, clarify_path, plan_path,
evaluate_path 전달 }) contents unchanged.

Comment on lines +5 to +26
```
docs/adr.md | 296 +++ (신규 ADR)
packages/cli/src/__tests__/default-command.test.ts | 31 +-
packages/cli/src/__tests__/hook-command.test.ts | 38 +-
packages/cli/src/__tests__/setup-command.test.ts | 3 +
packages/cli/src/adapters.ts | 5 +-
packages/cli/src/commands/hook.ts | 21 +-
packages/cli/src/deps.ts | 6 +-
packages/cli/src/lib/event-sender.ts | 165 ++ (self-heal)
packages/cli/src/lib/project.ts | 21 +
packages/shared/src/schemas/project.ts | 4 +
packages/shared/src/types/events.ts | 10 +
packages/shared/src/types/project.ts | 11 +
packages/web/src/app/api/events/route.ts | 23 +- (self-heal payload)
packages/web/src/app/dashboard/.../settings/projects/page.tsx | 154 + (Transfer UI)
packages/web/src/lib/server/project-actions.ts | 135 + (transferProjectForUser)
+ 신규: packages/web/src/app/api/projects/[projectId]/transfer/route.ts
+ 신규: packages/web/src/hooks/use-transfer-project.ts
+ 신규: packages/web/src/lib/server/project-actions.test.ts
+ 신규: packages/web/src/app/api/events/route.test.ts
+ 신규: packages/cli/src/lib/event-sender.test.ts
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

펜스 코드 블록에 언어 지정이 없어 markdownlint 경고가 발생합니다.

MD040 경고를 없애려면 코드 블록에 언어를 지정해 주세요.

🔧 제안 수정
-```
+```text
 docs/adr.md                                        | 296 +++ (신규 ADR)
 packages/cli/src/__tests__/default-command.test.ts |  31 +-
 ...
 + 신규: packages/cli/src/lib/event-sender.test.ts
-```
+```
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 5-5: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/tasks/2026-05-14-project-transfer-org/05-qa.md` around lines 5 - 26, The
markdown file contains a fenced code block in
docs/tasks/2026-05-14-project-transfer-org/05-qa.md that lacks a language
specifier, triggering markdownlint MD040; update the opening fence from ``` to
```text (or another appropriate language) so the block is annotated (ensure the
closing ``` remains unchanged) and commit the change to eliminate the lint
warning.

Comment on lines +37 to +38
| `pnpm --filter @argos/web typecheck` | **fail** | `src/lib/server/project-actions.test.ts` 의 `TxClient` 최소 타입이 Prisma `TransactionClient` 시그니처와 불일치 (TS2345 x 2건). 런타임/빌드/테스트는 모두 통과하지만 CI typecheck job 이 깨짐. — issue #1 |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

CI typecheck 실패를 미해결 상태로 두면 머지 블로커가 남습니다.

pnpm --filter @argos/web typecheck가 실패한 상태를 문서에만 남기고 넘어가면 PR의 신뢰성이 깨집니다. 해당 타입 불일치 원인을 먼저 수정하고 QA 결과를 갱신해 주세요.

Also applies to: 67-68

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/tasks/2026-05-14-project-transfer-org/05-qa.md` around lines 37 - 38,
The CI typecheck fails because the test-local TxClient type in
src/lib/server/project-actions.test.ts does not match Prisma's TransactionClient
signature (TS2345); update the test so TxClient either uses Prisma's
TransactionClient type (import type { Prisma } from '@prisma/client' and type
TxClient = Prisma.TransactionClient) or reshape the mock to implement the exact
methods/overloads Prisma.TransactionClient expects (or explicitly cast the mock
to unknown as Prisma.TransactionClient) and ensure any helper functions in
project-actions.test.ts that accept TxClient reflect that type change so pnpm
--filter `@argos/web` typecheck passes.

Comment thread docs/usecases/README.md
Comment on lines +7 to +18
```
docs/usecases/
README.md ← 이 문서 (포맷·규약·인덱스의 단일 원천)
_ids.yaml ← 기계 인덱스 + next-id 카운터
org/ ← organization 도메인
project/ ← project 도메인
session/ ← Claude 세션/이벤트 도메인
cli/ ← argos-ai CLI / hook
billing/ ← 결제·플랜·토큰 한도
auth/ ← 인증·세션 쿠키·역할
_shared/ ← 여러 도메인 user-goal UC 가 공통 참조하는 subfunction
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

펜스 코드블록 언어 지정이 빠져 markdownlint(MD040) 경고가 발생합니다.

코드블록 시작 fence에 언어를 명시해 lint 경고를 제거해 주세요.

🔧 제안 수정안
-```
+```text
 docs/usecases/
   README.md         ← 이 문서 (포맷·규약·인덱스의 단일 원천)
   _ids.yaml         ← 기계 인덱스 + next-id 카운터
   org/              ← organization 도메인
   project/          ← project 도메인
   session/          ← Claude 세션/이벤트 도메인
   cli/              ← argos-ai CLI / hook
   billing/          ← 결제·플랜·토큰 한도
   auth/             ← 인증·세션 쿠키·역할
   _shared/          ← 여러 도메인 user-goal UC 가 공통 참조하는 subfunction

@@
- +markdown

주 성공 시나리오

  1. (User · UI) [[UC-ORG-001]] 로 organization 을 만든다.
  2. (User · UI) [[UC-PROJ-001]] 로 첫 프로젝트를 만든다.
  3. (User · CLI) [[UC-CLI-001]] 로 로컬에서 hook 을 연결한다.

Also applies to: 107-112

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 7-7: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/usecases/README.md` around lines 7 - 18, The top README code fences in
docs/usecases/README.md are missing a language tag which triggers markdownlint
MD040; update each triple-backtick fence (the initial directory list fence and
the later "주 성공 시나리오" fence near the example) to include a language (e.g.,
replace ``` with ```text for the directory list and ```markdown for the scenario
list) so the lint warning is resolved while preserving the intended rendering.

Comment thread packages/cli/src/lib/project.ts Outdated
Comment thread packages/web/package.json
"jose": "^5",
"lucide-react": "^1.8.0",
"next": "15",
"next": "^15.5.18",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Next.js와 eslint-config-next의 peer dependency 호환성 확인
npm view next@15.5.18 version peerDependencies --json
npm view eslint-config-next@16.2.6 version peerDependencies --json
npm view eslint-config-next@15 version peerDependencies --json

Repository: Seongho-Bae/argos

Length of output: 10805


eslint-config-next 메이저 버전을 next와 일치시켜야 합니다.

Line 29는 next@^15.5.18이지만 Line 48은 eslint-config-next@^16.2.6입니다. 주요 버전 불일치가 있으며, 밀접하게 관련된 패키지들의 주요 버전을 일치시키는 것이 안정성과 호환성을 보장합니다.

제안 수정안
-    "eslint-config-next": "^16.2.6",
+    "eslint-config-next": "^15.5.18",
🧰 Tools
🪛 GitHub Actions: CI / build

[error] pnpm build failed for @argos/web: step "next build" exited with status code 1 (ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/web/package.json` at line 29, The package.json shows a major-version
mismatch between next (^15.5.18) and eslint-config-next (^16.2.6); update
package.json so their major versions match — either bump next to ^16.x or
(preferably for minimal change) change eslint-config-next to a ^15.x release
that aligns with next (update the "eslint-config-next" dependency entry), then
run install and test to verify lint/build still work.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/cli/src/lib/event-sender.ts`:
- Around line 83-95: The current read-then-rename sequence (variables latest,
projectJsonPathJson, atomicTmp; calls fs.readFileSync, fs.writeFileSync,
fs.renameSync) is vulnerable to races because another process can update the
file between the re-read and the rename; wrap the whole read-modify-write in an
inter-process lock or other atomic CAS mechanism: acquire a file lock (e.g., via
a lockfile or flock) on projectJsonPathJson before re-reading latest, perform
the guard checks and write the temp file, then rename and finally release the
lock; alternatively implement an atomic CAS by reading the current file into a
variable and using a platform-supported atomic replace that fails if the file
changed (or use an external lock library) so that fs.writeFileSync/
fs.renameSync only occur while the lock is held to prevent overwrites.

In `@packages/cli/src/lib/project.test.ts`:
- Around line 34-35: The finally block deletes tmpRoot while the test's cwd may
still be inside it; before calling rmSync(tmpRoot, { recursive: true, force:
true }) restore the original working directory by invoking
process.chdir(originalCwd) (or process.chdir(repoRoot) if originalCwd is named
repoRoot) so the current process is not inside tmpRoot when rmSync runs; update
the finally block in project.test.ts to call process.chdir(originalCwd)
immediately before rmSync to ensure deletion succeeds on Windows.

In `@scripts/ci/strix_model_utils.sh`:
- Around line 104-128: The extract_vertex_model_id logic uses echo to print
parsed IDs, which can misinterpret tokens beginning with '-' as options; update
every echo that outputs the extracted model id in the extract_vertex_model_id
function/block to use a safe printf invocation (e.g., printf '%s\n' <value>)
instead, replacing occurrences that print "${parts[...]}" or "$raw_model" so
outputs are never treated as options or subject to escape processing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: aaf925d0-182c-47bf-809b-787b2d5fd043

📥 Commits

Reviewing files that changed from the base of the PR and between 1ce496f and d1c6e2c.

📒 Files selected for processing (11)
  • .github/workflows/strix.yml
  • packages/cli/src/lib/event-sender.test.ts
  • packages/cli/src/lib/event-sender.ts
  • packages/cli/src/lib/project.test.ts
  • packages/cli/src/lib/project.ts
  • packages/web/src/app/globals.css
  • packages/web/src/lib/server/project-actions.test.ts
  • packages/web/src/lib/server/project-actions.ts
  • scripts/ci/strix_model_utils.sh
  • scripts/ci/strix_quick_gate.sh
  • scripts/ci/test_strix_quick_gate.sh
💤 Files with no reviewable changes (1)
  • packages/web/src/app/globals.css
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/web/src/lib/server/project-actions.ts
  • packages/cli/src/lib/project.ts
  • packages/cli/src/lib/event-sender.test.ts
  • packages/web/src/lib/server/project-actions.test.ts
  • .github/workflows/strix.yml
  • scripts/ci/strix_quick_gate.sh

Comment thread packages/cli/src/lib/event-sender.ts Outdated
Comment thread packages/cli/src/lib/project.test.ts
Comment thread scripts/ci/strix_model_utils.sh Outdated
@seonghobae seonghobae removed the run-strix Force Strix heavy scan label May 14, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/ci/strix_model_utils.sh`:
- Around line 48-56: The current is_provider_qualified_model() blindly accepts
any string whose characters match the allowed pattern segments; instead
explicitly parse and validate the provider prefix against a fixed allowlist:
extract the substring before the first '/' and check it belongs to the approved
providers (vertex_ai, vertex_ai_beta, openai, anthropic, azure, gemini, bedrock,
groq, mistral, cohere, ollama, huggingface, xai) and only return success when
that prefix is allowed and a non-empty model-name follows; update
is_provider_qualified_model() to perform this prefix-check (and apply the same
stricter validation to the duplicate logic mentioned around the other similar
block) so malformed inputs like "foo/bar" or typo'd DEFAULT_PROVIDER values are
rejected early.
- Around line 84-93: The credential gating is too coarse:
model_requires_llm_api_key() currently only checks is_vertex_model and forces
LLM_API_KEY_FILE for all non-Vertex models, which blocks local/no-auth providers
like ollama/*; update model_requires_llm_api_key() to branch by provider prefix
(inspect the model string passed in) and return appropriately — e.g., return
non-zero (no API key required) for ollama/* and other local providers, require
an API key (return zero) for openai/* and any providers that need an API key
(huggingface/* if applicable), and keep vertex handled by is_vertex_model; use
the same provider-identification logic as is_provider_qualified_model() to
detect prefixes so the change stays consistent across functions (reference
functions: model_requires_llm_api_key, model_requires_gcp_credentials,
is_vertex_model, is_provider_qualified_model).

In `@scripts/ci/strix_quick_gate.sh`:
- Around line 43-45: The script fills default values into STRIX_LLM_MAX_RETRIES,
LLM_TIMEOUT, and STRIX_MEMORY_COMPRESSOR_TIMEOUT but never passes them to the
child strix process; update the script so before the python3/child invocation
you export or set STRIX_CHILD_LLM_MAX_RETRIES="${STRIX_LLM_MAX_RETRIES}",
STRIX_CHILD_LLM_TIMEOUT="${LLM_TIMEOUT}", and
STRIX_CHILD_MEMORY_COMPRESSOR_TIMEOUT="${STRIX_MEMORY_COMPRESSOR_TIMEOUT}" (or
include them in the environment of the python3 command), ensuring the validated
defaults are forwarded to the child process (search for the python3 invocation
that launches strix and add these environment variables there).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: dd5501aa-e308-4521-b9d2-05177b1ca955

📥 Commits

Reviewing files that changed from the base of the PR and between e070bc7 and 98b2ab0.

📒 Files selected for processing (4)
  • .github/workflows/strix.yml
  • scripts/ci/strix_model_utils.sh
  • scripts/ci/strix_quick_gate.sh
  • scripts/ci/test_strix_quick_gate.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/strix.yml

Comment thread scripts/ci/strix_model_utils.sh
Comment thread scripts/ci/strix_model_utils.sh
Comment on lines +43 to +45
STRIX_LLM_MAX_RETRIES="${STRIX_LLM_MAX_RETRIES:-3}"
LLM_TIMEOUT="${LLM_TIMEOUT:-240}"
STRIX_MEMORY_COMPRESSOR_TIMEOUT="${STRIX_MEMORY_COMPRESSOR_TIMEOUT:-20}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

검증한 retry/timeout 기본값이 child strix 프로세스로 전달되지 않습니다.

여기서 기본값을 채우고 검증하지만, 실제 python3 실행 시에는 STRIX_CHILD_LLM_MAX_RETRIES, STRIX_CHILD_LLM_TIMEOUT, STRIX_CHILD_MEMORY_COMPRESSOR_TIMEOUT를 넘기지 않습니다. 그래서 workflow 환경변수가 없는 CLI 실행에서는 주석과 달리 child가 이 기본값을 보지 못합니다.

제안 수정안
 	STRIX_CHILD_MODEL="$model" \
 		STRIX_CHILD_LLM_API_KEY="$LLM_API_KEY" \
 		STRIX_CHILD_LLM_API_BASE="$llm_api_base_value" \
 		STRIX_CHILD_REPORTS_DIR="$ACTIVE_REPORTS_DIR" \
+		STRIX_CHILD_LLM_MAX_RETRIES="$STRIX_LLM_MAX_RETRIES" \
+		STRIX_CHILD_LLM_TIMEOUT="$LLM_TIMEOUT" \
+		STRIX_CHILD_MEMORY_COMPRESSOR_TIMEOUT="$STRIX_MEMORY_COMPRESSOR_TIMEOUT" \
 		STRIX_CHILD_REASONING_EFFORT="$STRIX_REASONING_EFFORT" \
 		STRIX_CHILD_INSTRUCTION_FILE="$instruction_file" \
 		python3 - "$timeout_seconds" "$resolved_target_path" "$SCAN_MODE" "$STRIX_LOG" "$instruction_file" <<'PY'

Also applies to: 1861-1867, 1915-1924

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/ci/strix_quick_gate.sh` around lines 43 - 45, The script fills
default values into STRIX_LLM_MAX_RETRIES, LLM_TIMEOUT, and
STRIX_MEMORY_COMPRESSOR_TIMEOUT but never passes them to the child strix
process; update the script so before the python3/child invocation you export or
set STRIX_CHILD_LLM_MAX_RETRIES="${STRIX_LLM_MAX_RETRIES}",
STRIX_CHILD_LLM_TIMEOUT="${LLM_TIMEOUT}", and
STRIX_CHILD_MEMORY_COMPRESSOR_TIMEOUT="${STRIX_MEMORY_COMPRESSOR_TIMEOUT}" (or
include them in the environment of the python3 command), ensuring the validated
defaults are forwarded to the child process (search for the python3 invocation
that launches strix and add these environment variables there).

Comment on lines +349 to +354
if (
err instanceof Prisma.PrismaClientKnownRequestError &&
err.code === 'P2025'
) {
return { kind: 'forbidden' }
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 P2025를 forbidden으로 매핑하면 동시 이전 시 오해하기 쉬운 403 반환

트랜잭션 내 tx.project.update({ where: { id: projectId, orgId: project.orgId } })에서 다른 세션이 이미 해당 프로젝트를 이전했다면, orgId 불일치로 Prisma P2025가 발생합니다. 현재 코드는 이를 { kind: 'forbidden' }으로 매핑해 route에서 403 "You must be an OWNER of both the source and target organization" 메시지를 반환합니다. 실제 원인은 동시 이전으로 인한 충돌인데, 사용자는 "권한 없음"으로 잘못 안내받게 됩니다.

FORBIDDEN_RACE(멤버십 강등 경쟁)와 P2025(프로젝트 이전 경쟁)는 서로 다른 원인이므로 별도 kind로 구분하는 것이 좋습니다. 예를 들어 kind: 'conflict'를 추가하고 route에서 409로 응답하면 클라이언트가 "이미 다른 곳으로 이전된 프로젝트입니다" 메시지를 표시할 수 있습니다.

@seonghobae

Copy link
Copy Markdown
Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@seonghobae

Copy link
Copy Markdown
Author

@coderabbitai 이 PR의 전체 코드를 리뷰해 주세요. 특히 다음 사항에 집중해 주시기 바랍니다:

  1. 보안: GitHub Actions 워크플로우 권한 설정이 최소 권한 원칙을 따르는지
  2. GitHub Models 통합: github/ 프로바이더 처리 로직의 정확성 (strix_model_utils.sh)
  3. Shell 스크립트 안전성: strix_quick_gate.sh의 인젝션 방지
  4. CI 로직: post-approval 실행 게이트의 race condition 가능성

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Read the strix workflow file
cat .github/workflows/strix.yml

Length of output: 57951


🏁 Script executed:

#!/bin/bash
# Read strix_model_utils.sh
cat scripts/ci/strix_model_utils.sh

Length of output: 6337


🏁 Script executed:

#!/bin/bash
# Read strix_quick_gate.sh - first 300 lines for validation/injection section
head -n 300 scripts/ci/strix_quick_gate.sh

Length of output: 10129


🏁 Script executed:

#!/bin/bash
# Read strix_quick_gate.sh - post-approval gate logic (search key sections)
grep -n "post.approval\|should_scan\|auto.merge\|approval\|race\|GITHUB_ENV\|GITHUB_OUTPUT\|eval\|bash -c\|printf.*%s\|injection\|UNTRUSTED\|prompt.injection" scripts/ci/strix_quick_gate.sh | head -80

Length of output: 3374


🏁 Script executed:

#!/bin/bash
# Look at the workflow permissions sections
grep -n "permissions\|contents:\|pull-requests:\|id-token:\|actions:\|checks:\|security-events:\|packages:\|deployments:\|statuses:" .github/workflows/strix.yml | head -60

Length of output: 370


🏁 Script executed:

#!/bin/bash
# Look at the post-approval decision logic in the workflow
grep -n "Decide post-approval\|should_scan\|auto.merge\|approved\|review_state\|GITHUB_OUTPUT\|race\|concurrency\|head.sha\|workflow_run" .github/workflows/strix.yml | head -80

Length of output: 7659



@seonghobae 요청하신 4개 영역에 대한 심층 검토 결과를 아래에 정리했습니다.


1. 보안 — GitHub Actions 권한 설정

선언된 권한:

permissions:
  actions: read
  checks: read
  contents: read
  models: read
  pull-requests: read

✅ 양호: 모든 권한이 읽기 전용으로 최소 권한 원칙을 잘 따르고 있습니다.

⚠️ 지적 사항 1 — GCP 서비스 계정 키 JSON 사용 (장기 자격증명)
GCP_SA_KEY 시크릿을 사용하는 방식은 장기 자격증명(long-lived credential)을 저장소 시크릿에 보관해야 합니다. Google 및 GitHub은 모두 OIDC Workload Identity Federation(WIF)을 권장합니다. WIF를 사용하면 id-token: write 권한만 추가하면 되고 키 로테이션 부담도 없습니다.

# 권장 방향 (WIF 적용 시)
permissions:
  id-token: write   # OIDC 토큰 취득용
  contents: read

# Authenticate step
- uses: google-github-actions/auth@...
  with:
    workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/...'
    service_account: 'strix-scanner@PROJECT.iam.gserviceaccount.com'

⚠️ 지적 사항 2 — harden-runneregress-policy: audit
현재 설정은 예상치 못한 외부 네트워크 송신을 로그만 하고 차단하지 않습니다. LLM provider 엔드포인트, GCP, GitHub API 외의 egress를 방지하려면 block 정책으로 업그레이드하고 allowed egress 도메인을 명시하는 것이 바람직합니다.

- uses: step-security/harden-runner@...
  with:
    egress-policy: block
    allowed-endpoints: >
      api.github.com:443
      models.inference.ai.azure.com:443   # GitHub Models
      aiplatform.googleapis.com:443        # Vertex AI

2. GitHub Models 통합 (strix_model_utils.sh)

github/ 프로바이더 처리 흐름을 전체 추적한 결과입니다.

✅ 핵심 흐름 정확: github/gpt-4o 입력 기준 실행 경로:

normalize_model("github/gpt-4o")
  → is_provider_qualified_model → extract_model_provider → "github" ✓ (allowlist 포함)
  → validate_model_identifier → segments ["github", "gpt-4o"] → is_safe_model_token 통과
  → returns "github/gpt-4o"

model_requires_github_api_key("github/gpt-4o") → provider="github" → true ✓
model_requires_llm_api_key("github/gpt-4o") → provider="github" → return 1 (불필요) ✓

⚠️ 지적 사항 — is_provider_qualified_model() 내 조기 반환 순서 혼용

is_provider_qualified_model() {
    local model="$1"
    local provider
    provider="$(extract_model_provider "$model")" || return 1  # ← 슬래시 없는 입력은 여기서 return 1
    if [ -z "${model#*/}" ]; then                              # ← "github/" 같은 trailing-slash 처리
        return 1
    fi
    case "$provider" in
    ... | github | ...)
        validate_model_identifier "$model" >/dev/null
        return $?
        ;;

extract_model_provider 실패 시 return 1로 즉시 나가기 때문에 trailing-slash 검사([ -z "${model#*/}" ])는 도달 불가능한 분기입니다. "github/" 입력은 extract_model_provider"github"를 리턴하여 성공하고, 이후 validate_model_identifier "github/" → case */ 패턴 매칭 → return 2로 거부됩니다. 결과는 올바르지만 trailing-slash 가드 코드 자체는 dead code입니다.

⚠️ 지적 사항 — is_safe_model_token@ 포함 GitHub 모델명 거부

is_safe_model_token() {
    [[ "$1" =~ ^[[:alnum:]_.:-]+$ ]]
}

GitHub Models의 일부 모델 식별자(e.g., Meta-Llama-3.1-70B-Instruct)는 현재 패턴으로 통과하지만, 향후 @latestuser/repo@version 형태의 식별자가 추가될 경우 거부됩니다. 현재 GitHub Models 카탈로그에는 해당 형태가 없으므로 즉각적 문제는 아닙니다.


3. Shell 스크립트 안전성 (strix_quick_gate.sh)

✅ 양호한 부분:

  • STRIX_LLM을 직접 환경변수로 받지 않고 umask 077 파일로 전달 → secrets 로그 노출 방지
  • STRIX_TARGET_PATH allowlist 검증 (정확한 문자열 비교, 와일드카드 없음)
  • STRIX_SCAN_MODE 알파뉴메릭 정규식 검증
  • STRIX_INSTRUCTION_FILE symlink 거부 및 REPO_ROOT/RUNNER_TEMP 외부 거부
  • PR title/body에 UNTRUSTED — prompt-injection guard active 명시 및 펜스 처리
  • eval 미사용

⚠️ 지적 사항 — LLM_API_KEY_FILE / GITHUB_API_KEY_FILE symlink 검증 누락

STRIX_LLM_FILE은 명시적으로 검증됩니다:

if [ -z "$STRIX_LLM_FILE" ] || [ ! -f "$STRIX_LLM_FILE" ] || [ -L "$STRIX_LLM_FILE" ]; then
    echo "ERROR: STRIX_LLM_FILE must reference a regular file containing the model." >&2
    exit 2
fi

그러나 LLM_API_KEY_FILEGITHUB_API_KEY_FILE에는 동일한 [ -L "$file" ] (symlink 거부) 검사가 보이지 않습니다. RUNNER_TEMP에 symlink가 생성되는 경우는 제한적이지만, 일관성을 위해 동일한 검증을 추가하는 것이 좋습니다:

for key_file_var in LLM_API_KEY_FILE GITHUB_API_KEY_FILE LLM_API_BASE_FILE; do
    key_file="${!key_file_var}"
    if [ -n "$key_file" ] && { [ ! -f "$key_file" ] || [ -L "$key_file" ]; }; then
        echo "ERROR: $key_file_var must reference a regular file." >&2
        exit 2
    fi
done

⚠️ 지적 사항 — STRIX_REASONING_EFFORT 입력 검증 없음

STRIX_REASONING_EFFORT="${STRIX_REASONING_EFFORT:-}"

Strix 문서에 따르면 허용값은 minimal | low | medium | high입니다. 해당 값이 child 환경에 그대로 전달될 경우 Strix가 예상치 못한 동작을 할 수 있습니다. 간단한 allowlist 검증을 권장합니다:

if [ -n "$STRIX_REASONING_EFFORT" ]; then
    case "$STRIX_REASONING_EFFORT" in
    minimal | low | medium | high) ;;
    *)
        echo "ERROR: STRIX_REASONING_EFFORT must be one of: minimal, low, medium, high." >&2
        exit 2
        ;;
    esac
fi

4. CI 로직 — Post-Approval 게이트의 Race Condition

✅ 잘 설계된 부분:

  • 승인 체크가 commit_id == PR_HEAD_SHA 필터를 사용하여 오래된 커밋의 승인이 현재 헤드에 적용되는 것을 방지
  • concurrency group에 head SHA 포함으로 동일 PR의 구 헤드 스캔이 현재 필수 체크 컨텍스트를 방해하지 않음
  • cancel-in-progress: false로 malicious force-push에 의한 진행 중 스캔 취소 방지
  • check-run identity 이중 검증 (check-runs API → 개별 run API로 head_sha + path 재확인)

⚠️ 지적 사항 — pull_request_reviewworkflow_run 동시 실행 가능

두 이벤트는 서로 다른 concurrency 그룹을 사용합니다:

pull_request_review → strix-{wf}-pr-{pr_number}-{head.sha}
workflow_run        → strix-{wf}-workflow-run-{run_id}

같은 PR의 같은 헤드 SHA에 대해 두 이벤트가 동시에 트리거되면 두 개의 독립적인 heavy 스캔이 실행됩니다. 보안 문제는 아니지만 LLM 비용 낭비 가능성이 있습니다.

⚠️ 지적 사항 — 비-PR workflow_run의 조건 우회

if [ "$EVENT_NAME" = "workflow_run" ] && [ "$WORKFLOW_RUN_CONCLUSION" = "success" ] && \
   [ "$WORKFLOW_RUN_EVENT" = "push" ] && \
   { [ "$WORKFLOW_RUN_HEAD_BRANCH" = "develop" ] || [ "$WORKFLOW_RUN_HEAD_BRANCH" = "main" ]; }; then
    cond_auto_merge='yes'
    cond_approved='yes'
    cond_mergeable='yes'
    cond_checks_green='no'   # ← 여기서도 checks_green='no'이면 아래 조건에서 거부됨

cond_checks_green='no'로 설정되기 때문에 아래 최종 판단:

if [ "$cond_auto_merge" = 'yes' ] && [ "$cond_approved" = 'yes' ] \
  && [ "$cond_mergeable" = 'yes' ] && [ "$cond_checks_green" = 'yes' ]; then

에서 항상 deferred로 떨어집니다. 즉, develop/main push-backed workflow_runchecks_green 채움이 없어 실제로 heavy 스캔이 실행되지 않습니다. 이 로직이 의도된 것인지 확인이 필요합니다.


요약 테이블

영역 심각도 항목
권한 🟡 중간 GCP SA Key JSON → Workload Identity Federation 전환 권장
권한 🟢 낮음 egress-policy: auditblock 전환 권장
GitHub Models 🟢 낮음 is_provider_qualified_model 내 trailing-slash 가드가 dead code
Shell 안전성 🟡 중간 LLM_API_KEY_FILE/GITHUB_API_KEY_FILE symlink 검증 누락
Shell 안전성 🟢 낮음 STRIX_REASONING_EFFORT 입력값 allowlist 검증 누락
CI 로직 🟢 낮음 pull_request_review + workflow_run 동시 실행 → 이중 비용 가능
CI 로직 🟡 중간 develop/main push-backed workflow_runchecks_green='no'로 실제 never scans — 의도 확인 필요

전반적으로 보안 설계가 매우 세심하게 이루어져 있습니다. cancel-in-progress: false 결정, SHA 핀닝, UNTRUSTED 라벨링, 파일 기반 시크릿 전달 등의 설계는 특히 잘 구현되어 있습니다. 위 지적 사항들은 주로 방어 깊이 강화 및 일관성 개선에 해당합니다.

🐇

@seonghobae seonghobae changed the title Add Strix pipeline (internal PR) feat(ci): Strix LLM 기반 보안 스캔 파이프라인 추가 + GitHub Models 지원 May 30, 2026
@seonghobae

Copy link
Copy Markdown
Author

@coderabbitai review

이 PR을 전체 검토해 주세요. 특히 다음 사항을 중점적으로 확인해 주시기 바랍니다:

  • 코드 정확성 및 잠재적 버그
  • 보안 취약점 여부
  • 성능 영향
  • 코딩 표준 및 best practice 준수 여부

@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown

@seonghobae 전체 PR 리뷰를 시작하겠습니다. 다음 영역을 포함하여 모든 변경 파일을 종합 검토합니다:

  • 코드 정확성 / 버그: transferProjectForUser의 P2002 target 매핑, CLI self-heal script의 race guard, findProjectConfigWithPath path 정규화
  • 보안: GH Actions 권한, shell injection, GCP 자격증명 처리 (이전 분석 결과 보완)
  • 성능: LLM fallback retry 루프, React Query 캐시 무효화 범위, strix_quick_gate.sh의 hallucination 재시도 비용
  • 코딩 표준 / Best Practice: TypeScript 타입 안전성, Prisma 트랜잭션 패턴, Bash 방어적 코딩
✅ Actions performed

Full review triggered.

@seonghobae

Copy link
Copy Markdown
Author

upstream 리뷰 대응 현황

upstream PR vibemafiaclub/argos#9에서 받은 리뷰 피드백에 따라 다음과 같이 조치하였습니다:

  1. 스코프 분리: dependency-review.ymlosvscanner.yml을 별도 PR vibemafiaclub/argos#26으로 분리하여 제출하였습니다.
  2. Strix 워크플로우: workflow_run 트리거 문제와 스크립트 크기 문제를 해결한 후 별도 PR로 재제출할 예정입니다.
  3. 앱 코드 변경: project-actions.ts 등 CI와 무관한 변경 사항은 독립 PR로 분리할 예정입니다.

이 PR은 위 분리 작업이 완료되면 닫겠습니다.

@seonghobae

Copy link
Copy Markdown
Author

upstream PR vibemafiaclub#9 리뷰 피드백에 따라 이 대형 혼합 PR은 닫습니다.

이미 분리한 항목:

순수 Strix 파이프라인은 리뷰 피드백(P2/P3)을 반영해 별도 PR로 재작성하겠습니다.

@seonghobae seonghobae closed this Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants