@dusky-bluehour/agent-service 0.6.7 → 0.6.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +263 -36
- package/catalog/tool-catalog.ko.json +17 -43
- package/claude-code/README.md +84 -66
- package/codex/README.md +55 -33
- package/common/settings/security-policy.json +1 -1
- package/common/skills/skill-catalog.json +368 -136
- package/common/workflows/workflow-catalog.json +89 -1238
- package/gemini/README.md +104 -0
- package/{antigravity/commands/definitions/cmd-dev-be-api.md → gemini/commands/definitions/cmd-dev-be-api.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-dev-fe-hook-separate.md → gemini/commands/definitions/cmd-dev-fe-hook-separate.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-dev-fe-ui-componentize.md → gemini/commands/definitions/cmd-dev-fe-ui-componentize.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-dev-perf-optimize.md → gemini/commands/definitions/cmd-dev-perf-optimize.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-dev-sequential-autorun.md → gemini/commands/definitions/cmd-dev-sequential-autorun.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-doc-handoff.md → gemini/commands/definitions/cmd-doc-handoff.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-improve-techdebt.md → gemini/commands/definitions/cmd-improve-techdebt.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-incident-triage.md → gemini/commands/definitions/cmd-incident-triage.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-ops-ci-cd-gate.md → gemini/commands/definitions/cmd-ops-ci-cd-gate.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-ops-deploy.md → gemini/commands/definitions/cmd-ops-deploy.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-ops-monitoring.md → gemini/commands/definitions/cmd-ops-monitoring.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-plan-arch-decision.md → gemini/commands/definitions/cmd-plan-arch-decision.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-plan-implementation-bootstrap.md → gemini/commands/definitions/cmd-plan-implementation-bootstrap.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-plan-prd-details.md → gemini/commands/definitions/cmd-plan-prd-details.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-plan-prd-master.md → gemini/commands/definitions/cmd-plan-prd-master.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-plan-req-lock.md → gemini/commands/definitions/cmd-plan-req-lock.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-review-code.md → gemini/commands/definitions/cmd-review-code.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-sec-dependency-audit.md → gemini/commands/definitions/cmd-sec-dependency-audit.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-sec-threat-model.md → gemini/commands/definitions/cmd-sec-threat-model.toml} +13 -21
- package/{antigravity/commands/definitions/cmd-test-unit-integration.md → gemini/commands/definitions/cmd-test-unit-integration.toml} +13 -21
- package/gemini/gemini-extension.json +6 -0
- package/{antigravity → gemini}/settings/editor-policy.json +1 -1
- package/{antigravity → gemini}/skills/change-safety-review/SKILL.md +8 -6
- package/{antigravity → gemini}/skills/code-review-and-improvement/SKILL.md +8 -3
- package/gemini/skills/frontend-repetition-pack/SKILL.md +44 -0
- package/gemini/skills/incident-response/SKILL.md +44 -0
- package/{antigravity → gemini}/skills/prd-to-production-pipeline/SKILL.md +13 -4
- package/{antigravity → gemini}/skills/release-and-operations/SKILL.md +11 -3
- package/gemini/skills/security-hardening/SKILL.md +43 -0
- package/gemini/skills/service-lifecycle-orchestration/SKILL.md +46 -0
- package/{antigravity → gemini}/workflows/workflow-catalog.json +1 -1
- package/package.json +4 -4
- package/scripts/generate-from-common.mjs +99 -70
- package/scripts/init.mjs +41 -21
- package/scripts/validate.mjs +66 -33
- package/antigravity/README.md +0 -50
- package/antigravity/skills/frontend-repetition-pack/SKILL.md +0 -35
- package/antigravity/skills/incident-response/SKILL.md +0 -35
- package/antigravity/skills/security-hardening/SKILL.md +0 -35
- package/antigravity/skills/service-lifecycle-orchestration/SKILL.md +0 -36
- package/claude-code/workflows/workflow-catalog.json +0 -688
- package/codex/workflows/workflow-catalog.json +0 -450
- /package/{antigravity/agents → common/gemini}/agent-catalog.json +0 -0
- /package/{antigravity/artifacts → common/gemini}/artifact-catalog.json +0 -0
- /package/{common/antigravity → gemini/agents}/agent-catalog.json +0 -0
- /package/{common/antigravity → gemini/artifacts}/artifact-catalog.json +0 -0
- /package/{antigravity → gemini}/commands/command-catalog.json +0 -0
- /package/{antigravity/instructions/WORKSPACE-RULES.template.md → gemini/instructions/GEMINI.template.md} +0 -0
- /package/{antigravity → gemini}/workflows/definitions/WF-FRONTEND-REFACTOR.workflow.yaml +0 -0
- /package/{antigravity → gemini}/workflows/definitions/WF-INCIDENT-RESPONSE.workflow.yaml +0 -0
- /package/{antigravity → gemini}/workflows/definitions/WF-PRD-TO-PRODUCTION.workflow.yaml +0 -0
- /package/{antigravity → gemini}/workflows/definitions/WF-SECURITY-HARDENING.workflow.yaml +0 -0
- /package/{antigravity → gemini}/workflows/definitions/WF-SERVICE-E2E.workflow.yaml +0 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-repetition-pack
|
|
3
|
+
description: UI 컴포넌트화, Hook 분리, 성능 최적화를 표준 단계로 실행한다. 반복 프론트엔드 개선 작업에서 사용한다.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 시작 전 체크리스트
|
|
7
|
+
|
|
8
|
+
- 중복 UI 후보 목록을 수집한다 (화면/컴포넌트/사용 횟수).
|
|
9
|
+
- 기준 지표를 기록한다 (번들 크기, 렌더 횟수, 핵심 UX 지연 시간).
|
|
10
|
+
- 디자인 토큰/컴포넌트 규칙을 확인한다.
|
|
11
|
+
- 상태 로직 분리 대상(부수효과/비동기/공유 상태)을 표시한다.
|
|
12
|
+
|
|
13
|
+
# 실행 절차
|
|
14
|
+
|
|
15
|
+
1. --- 1단계: UI 컴포넌트화 ---
|
|
16
|
+
2. 프로젝트 전체에서 중복되는 UI 패턴을 탐색한다: 유사한 JSX/TSX 구조, 동일 스타일 블록, 반복 레이아웃을 식별한다.
|
|
17
|
+
3. 중복 UI를 패턴별로 그룹화하고, 각 그룹에 대해 최소 Props 계약(필수/선택 props, 타입, 기본값)을 정의한다.
|
|
18
|
+
4. 공통 컴포넌트를 생성하고 기존 중복 코드를 교체한다. 스토리 또는 스냅샷 테스트를 추가하여 시각적 회귀를 방지한다.
|
|
19
|
+
5. --- 2단계: Hook 분리 ---
|
|
20
|
+
6. 컴포넌트에서 렌더링 로직과 상태 오케스트레이션(비동기/캐시/재시도/전역 상태) 경계를 식별한다.
|
|
21
|
+
7. 커스텀 Hook의 입력/출력 타입을 정의하고, 비동기/캐시/재시도 로직을 Hook으로 캡슐화한다.
|
|
22
|
+
8. Hook별 단위 테스트를 작성하여 입력별 반환값, 로딩/에러 상태를 검증한다.
|
|
23
|
+
9. --- 3단계: 성능 최적화 ---
|
|
24
|
+
10. 성능 기준선을 측정한다: 렌더링 횟수, 번들 크기, 핵심 UX 지연 시간을 기록한다.
|
|
25
|
+
11. 상위 3개 병목 지점을 식별하고, 메모이제이션/코드 스플리팅/쿼리 캐싱 등 최적화를 적용한다.
|
|
26
|
+
12. 동일 조건에서 재측정하고, 기준선 대비 개선 수치를 Artifact에 기록한다.
|
|
27
|
+
|
|
28
|
+
# 결과 보고 형식
|
|
29
|
+
|
|
30
|
+
- 컴포넌트화 결과: 기존->신규 매핑, 공통 Props 계약
|
|
31
|
+
- Hook 분리 결과: Hook 이름, 입력/출력, 부수효과 정책
|
|
32
|
+
- 성능 결과: 전/후 지표와 측정 조건
|
|
33
|
+
- 남은 리팩터 항목: 우선순위와 예상 영향
|
|
34
|
+
|
|
35
|
+
# 중단 조건
|
|
36
|
+
|
|
37
|
+
- 시각적 회귀가 차단 이슈 수준으로 발생한 경우
|
|
38
|
+
- 컴포넌트 계약이 확정되지 않아 호출부 정리가 불가능한 경우
|
|
39
|
+
- 전/후 성능 비교가 불가능해 개선 효과를 증명할 수 없는 경우
|
|
40
|
+
|
|
41
|
+
# 품질 규칙
|
|
42
|
+
|
|
43
|
+
- 단계별 전후 지표를 Artifact에 남긴다.
|
|
44
|
+
- 계약 없는 리팩터링 금지
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: incident-response
|
|
3
|
+
description: 장애 대응, 근본 원인 수정, 재발 방지까지 수행한다. 운영 장애 및 핫픽스 대응에서 사용한다.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 시작 전 체크리스트
|
|
7
|
+
|
|
8
|
+
- 장애 심각도(SEV), 영향 범위, 시작 시각을 확정한다.
|
|
9
|
+
- 즉시 복구 경로(롤백/우회/트래픽 차단)를 준비한다.
|
|
10
|
+
- 커뮤니케이션 채널과 의사결정 책임자를 지정한다.
|
|
11
|
+
- 로그/메트릭/알림 스냅샷을 보존한다.
|
|
12
|
+
|
|
13
|
+
# 실행 절차
|
|
14
|
+
|
|
15
|
+
1. --- 1단계: 장애 분류 및 초기 대응 ---
|
|
16
|
+
2. 장애 심각도(SEV1~4)와 고객 영향 범위를 분류한다: 영향 사용자 수, 기능 범위, 데이터 손상 여부를 파악한다.
|
|
17
|
+
3. 워룸 역할(인시던트 커맨더, 기술 리드, 커뮤니케이션)을 고정하고 복구 우선 경로(롤백/트래픽 차단/우회)를 실행한다.
|
|
18
|
+
4. 복구 후 고객 영향 해소를 모니터링으로 확인한다.
|
|
19
|
+
5. --- 2단계: 근본 원인 분석 및 수정 ---
|
|
20
|
+
6. 로그/메트릭/알림 스냅샷을 수집하여 타임라인을 구성한다.
|
|
21
|
+
7. 장애 관련 코드를 리뷰하고 결함을 심각도별(critical/major/minor)로 분류한다. 보안, 성능, 가독성, 확장성 관점에서 검토한다.
|
|
22
|
+
8. 기술 부채를 영향도/수정 비용으로 우선순위화하고, 근본 원인 수정을 반영한 후 테스트로 회귀를 검증한다.
|
|
23
|
+
9. --- 3단계: 재발 방지 및 문서화 ---
|
|
24
|
+
10. 재발 방지 액션을 정의한다: 각 액션에 담당자, 마감일, 검증 방법을 명시한다.
|
|
25
|
+
11. 운영 문서(런북)를 갱신한다: 역할별 탐지/복구/에스컬레이션 절차를 정리하고 변경 이력을 기록한다. 월간 갱신 담당자를 지정한다.
|
|
26
|
+
12. 포스트모템 보고서를 Artifact로 작성한다: 타임라인, 근본 원인, 재발 방지 액션을 포함한다.
|
|
27
|
+
|
|
28
|
+
# 결과 보고 형식
|
|
29
|
+
|
|
30
|
+
- 타임라인: 탐지->완화->복구 시각
|
|
31
|
+
- 복구 조치: 실행 명령/설정 변경/결과
|
|
32
|
+
- 근본 원인: 기술 원인, 프로세스 원인
|
|
33
|
+
- 재발 방지 액션: 담당자, 마감일, 검증 방법
|
|
34
|
+
|
|
35
|
+
# 중단 조건
|
|
36
|
+
|
|
37
|
+
- 고객 영향이 지속되는데 복구 경로가 없는 경우
|
|
38
|
+
- 데이터 손상 가능성이 있어 즉시 격리가 필요한 경우
|
|
39
|
+
- 재발 방지 액션의 책임자/기한이 확정되지 않은 경우
|
|
40
|
+
|
|
41
|
+
# 품질 규칙
|
|
42
|
+
|
|
43
|
+
- RCA와 재발 방지 액션 없는 종료 금지
|
|
44
|
+
- 복구와 개선을 분리 보고
|
|
@@ -12,10 +12,19 @@ description: PRD 작성 단계를 대화형으로 수행하고 구현 단계를
|
|
|
12
12
|
|
|
13
13
|
# 실행 절차
|
|
14
14
|
|
|
15
|
-
1.
|
|
16
|
-
2.
|
|
17
|
-
3.
|
|
18
|
-
4.
|
|
15
|
+
1. --- 1단계: 마스터 PRD 작성 ---
|
|
16
|
+
2. 문제를 정량화한다: 해결 대상, 영향 사용자, 기대 KPI를 명시한다.
|
|
17
|
+
3. 사용자 세그먼트와 시나리오를 정리하고 범위/비범위를 분리한다. 보안/성능/가독성 비기능 요구사항을 포함한다.
|
|
18
|
+
4. 마스터 PRD Artifact를 확정한다.
|
|
19
|
+
5. --- 2단계: 세부 PRD 작성 ---
|
|
20
|
+
6. 에픽/기능 단위로 세부 PRD Artifact를 작성한다: 수용 기준, UI 컴포넌트 전략, 구현 순서/의존성을 포함한다.
|
|
21
|
+
7. --- 3단계: 구현 부트스트랩 ---
|
|
22
|
+
8. 세부 PRD를 배치로 그룹화하고, 역할 책임/산출물/검증 게이트를 고정한다.
|
|
23
|
+
9. 자동 실행과 수동 세팅 배치를 분리한다.
|
|
24
|
+
10. --- 4단계: 순차 자동 실행 ---
|
|
25
|
+
11. 배치를 순서대로 에이전트에게 위임하여 실행한다: 각 배치 완료 후 테스트/리뷰를 자동 수행한다.
|
|
26
|
+
12. 배치별 출력 Artifact를 검증하고, 게이트 통과 시 다음 배치로 진행한다.
|
|
27
|
+
13. 수동 세팅 단계에 도달하면 검토 후 배포 준비를 완료한다.
|
|
19
28
|
|
|
20
29
|
# 결과 보고 형식
|
|
21
30
|
|
|
@@ -12,9 +12,17 @@ description: 배포 게이트와 운영 전환을 Manager 주도로 실행한다
|
|
|
12
12
|
|
|
13
13
|
# 실행 절차
|
|
14
14
|
|
|
15
|
-
1.
|
|
16
|
-
2.
|
|
17
|
-
3.
|
|
15
|
+
1. --- 1단계: CI/CD 게이트 설정 ---
|
|
16
|
+
2. 필수 검사 항목(테스트, 린트, 보안 스캔)을 파이프라인 게이트로 등록하고, 실패 시 자동 중단/알림을 설정한다.
|
|
17
|
+
3. 역할 기반 배포 승인을 고정하고 릴리즈 노트 자동 생성을 연결한다.
|
|
18
|
+
4. --- 2단계: 점진적 배포 ---
|
|
19
|
+
5. 백업과 롤백 경로를 검증한 뒤, 카나리/블루-그린 점진 배포를 실행한다.
|
|
20
|
+
6. 각 단계에서 핵심 SLI를 모니터링하고, 임계치 초과 시 롤백한다.
|
|
21
|
+
7. --- 3단계: 운영 모니터링 설정 ---
|
|
22
|
+
8. 대시보드에 핵심 메트릭/에러 예산을 구성하고, 노이즈 알림을 정리한다.
|
|
23
|
+
9. 런북을 알림에 연결하고 주간 임계치 튜닝 프로세스를 수립한다.
|
|
24
|
+
10. --- 4단계: 인수인계 ---
|
|
25
|
+
11. 운영 문서를 역할별로 분리하여 갱신하고, 변경 이력을 기록한다. 월간 갱신 담당자를 지정한다.
|
|
18
26
|
|
|
19
27
|
# 결과 보고 형식
|
|
20
28
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: security-hardening
|
|
3
|
+
description: 위협 모델링과 취약점 감사를 수행하고 보완 및 재검증까지 실행한다. 보안 강화 요청에서 사용한다.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 시작 전 체크리스트
|
|
7
|
+
|
|
8
|
+
- 신뢰 경계와 보호 대상 자산을 확정한다.
|
|
9
|
+
- 의존성 목록과 현재 취약점 현황을 수집한다.
|
|
10
|
+
- 위협 모델링 범위(인증/인가/데이터/운영)를 고정한다.
|
|
11
|
+
- 예외 승인 정책(책임자, 만료일)을 준비한다.
|
|
12
|
+
|
|
13
|
+
# 실행 절차
|
|
14
|
+
|
|
15
|
+
1. --- 1단계: 위협 모델링 ---
|
|
16
|
+
2. 보호 대상 자산을 식별하고 가치 등급을 매긴다. 신뢰 경계를 정의하고 공격 시나리오를 도출한다.
|
|
17
|
+
3. 각 위협에 완화 통제를 할당하고 잔여 위험 수용 여부를 결정한다.
|
|
18
|
+
4. --- 2단계: 의존성 취약점 감사 ---
|
|
19
|
+
5. 의존성 스캔 도구(`npm audit`, `pip-audit`, `trivy` 등)로 취약점을 수집하고 심각도별로 분류한다.
|
|
20
|
+
6. critical 항목부터 패치를 적용하고, 패치 후 전체 테스트를 실행하여 회귀를 확인한다.
|
|
21
|
+
7. 패치 불가능한 취약점은 예외로 기록한다: 책임자와 만료일을 포함한다.
|
|
22
|
+
8. --- 3단계: 보완 코드 적용 및 재검증 ---
|
|
23
|
+
9. 위협 모델의 완화 통제를 코드/설정으로 구현하고, 보안 관점 코드 리뷰를 수행한다.
|
|
24
|
+
10. 테스트를 재실행하여 보완이 기능을 파손하지 않았음을 확인한다.
|
|
25
|
+
11. 최종 보안 상태를 Artifact로 보고한다: 위협/취약점 목록, 보완 내역, 재검증 결과, 잔여 위험을 포함한다.
|
|
26
|
+
|
|
27
|
+
# 결과 보고 형식
|
|
28
|
+
|
|
29
|
+
- 위협/취약점 목록: 심각도, 영향, 우선순위
|
|
30
|
+
- 보완 적용 내역: 코드/설정 변경과 근거
|
|
31
|
+
- 재검증 결과: 스캔/테스트/리뷰 결과
|
|
32
|
+
- 잔여 위험 및 예외 승인: 책임자, 만료일
|
|
33
|
+
|
|
34
|
+
# 중단 조건
|
|
35
|
+
|
|
36
|
+
- 치명 취약점이 남아 있는데 배포를 진행하려는 경우
|
|
37
|
+
- 고위험 위협에 대한 완화 통제가 정의되지 않은 경우
|
|
38
|
+
- 예외 승인이 만료일 없이 요청된 경우
|
|
39
|
+
|
|
40
|
+
# 품질 규칙
|
|
41
|
+
|
|
42
|
+
- 치명 취약점 0건 전까지 종료 금지
|
|
43
|
+
- 예외 수용은 만료일 포함
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: service-lifecycle-orchestration
|
|
3
|
+
description: Plan-Implement-Test-Review-Release 흐름을 Manager 중심으로 실행한다. 신규 서비스 구축 및 대형 기능 출시에 사용한다.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 시작 전 체크리스트
|
|
7
|
+
|
|
8
|
+
- 요구사항/ADR/범위/비범위를 확정한다.
|
|
9
|
+
- 각 단계 책임 역할과 승인자를 지정한다.
|
|
10
|
+
- 단계별 진입/종료 기준을 작업 시작 전에 확인한다.
|
|
11
|
+
- 리스크와 롤백 전략을 초기 단계에서 기록한다.
|
|
12
|
+
|
|
13
|
+
# 실행 절차
|
|
14
|
+
|
|
15
|
+
1. --- 1단계: 요구사항 확정 ---
|
|
16
|
+
2. 목표를 정량적 지표로 변환하고, 사용자 시나리오를 우선순위화한다. 범위/비범위와 수용/거부 기준을 Artifact로 확정한다.
|
|
17
|
+
3. --- 2단계: 아키텍처 결정 ---
|
|
18
|
+
4. 후보 아키텍처를 비교하고 선택 근거를 문서화한다. 데이터 모델과 API 경계를 확정하여 Artifact로 저장한다.
|
|
19
|
+
5. --- 3단계: 구현 ---
|
|
20
|
+
6. 계약 우선 방식으로 API를 설계하고, 핸들러/비즈니스 로직을 분리한다. 인증/인가와 감사 로그를 추가한다.
|
|
21
|
+
7. 에이전트가 각 기능을 구현하고 테스트를 작성/실행한다.
|
|
22
|
+
8. --- 4단계: 검증 ---
|
|
23
|
+
9. 코드 리뷰를 수행한다: 결함을 심각도별로 분류하고 차단 이슈를 수정한다. 의존성 취약점 스캔과 보안 점검을 실행한다.
|
|
24
|
+
10. 테스트를 재실행하여 회귀를 확인하고 검증 결과를 Artifact에 기록한다.
|
|
25
|
+
11. --- 5단계: 배포 ---
|
|
26
|
+
12. CI/CD 게이트 통과를 확인하고, 백업/롤백을 검증한 뒤 점진 배포를 실행한다. SLI를 모니터링하고 이상 시 롤백한다.
|
|
27
|
+
13. --- 6단계: 운영 전환 ---
|
|
28
|
+
14. 운영 문서를 역할별로 갱신하고, 대시보드/알림/런북을 설정한다. 인수인계 Artifact를 확정하고 월간 갱신 담당자를 지정한다.
|
|
29
|
+
|
|
30
|
+
# 결과 보고 형식
|
|
31
|
+
|
|
32
|
+
- 단계 상태: 완료/미완료/차단요인
|
|
33
|
+
- 실행 근거: 단계별 명령 ID와 결과
|
|
34
|
+
- 품질 상태: 테스트/보안/리뷰 게이트 결과
|
|
35
|
+
- 다음 행동: 담당자, 마감 조건, 선행 조건
|
|
36
|
+
|
|
37
|
+
# 중단 조건
|
|
38
|
+
|
|
39
|
+
- 진입 기준이 충족되지 않은 단계가 있는 경우
|
|
40
|
+
- 차단 이슈가 해결되지 않았는데 다음 단계로 이동하려는 경우
|
|
41
|
+
- 롤백 전략 없이 배포 단계 진입이 요청된 경우
|
|
42
|
+
|
|
43
|
+
# 품질 규칙
|
|
44
|
+
|
|
45
|
+
- Artifact 검증 실패 시 단계 진행 금지
|
|
46
|
+
- command ID 없는 임의 실행 금지
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": "1.0.0",
|
|
3
3
|
"workflow_policy": {
|
|
4
|
-
"execution_rule": "
|
|
4
|
+
"execution_rule": "Gemini CLI Manager가 단계별 에이전트 체인을 구성하고, 각 단계는 Artifact 검증을 통과해야 다음으로 진행한다.",
|
|
5
5
|
"artifact_rule": "모든 단계는 입력 아티팩트 스키마와 출력 아티팩트 스키마를 명시한다."
|
|
6
6
|
},
|
|
7
7
|
"workflows": [
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dusky-bluehour/agent-service",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.8",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"description": "Service operation skills/workflows pack for Claude Code,
|
|
7
|
+
"description": "Service operation skills/workflows pack for Claude Code, Gemini CLI, and Codex",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"bin": {
|
|
10
10
|
"tri-agent-manager": "scripts/init.mjs"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"files": [
|
|
21
21
|
"common",
|
|
22
22
|
"claude-code",
|
|
23
|
-
"
|
|
23
|
+
"gemini",
|
|
24
24
|
"codex",
|
|
25
25
|
"catalog/tool-catalog.ko.json",
|
|
26
26
|
"scripts/init.mjs",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"workflow",
|
|
35
35
|
"codex",
|
|
36
36
|
"claude-code",
|
|
37
|
-
"
|
|
37
|
+
"gemini-cli",
|
|
38
38
|
"devops",
|
|
39
39
|
"security",
|
|
40
40
|
"code-review"
|
|
@@ -8,7 +8,7 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
8
8
|
const __dirname = path.dirname(__filename);
|
|
9
9
|
const rootDir = path.resolve(__dirname, '..');
|
|
10
10
|
|
|
11
|
-
const DEFAULT_TOOL_IDS = ['claude-code', 'codex', '
|
|
11
|
+
const DEFAULT_TOOL_IDS = ['claude-code', 'codex', 'gemini'];
|
|
12
12
|
const args = new Set(process.argv.slice(2));
|
|
13
13
|
const checkMode = args.has('--check');
|
|
14
14
|
|
|
@@ -159,7 +159,7 @@ function renderYamlList(lines, indent, values) {
|
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
function
|
|
162
|
+
function renderGeminiWorkflowDefinition(workflow) {
|
|
163
163
|
const lines = [];
|
|
164
164
|
lines.push('# generated by scripts/generate-from-common.mjs');
|
|
165
165
|
lines.push('workflow:');
|
|
@@ -245,7 +245,7 @@ function renderClaudeCommandMarkdown(command) {
|
|
|
245
245
|
].join('\n');
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
function
|
|
248
|
+
function renderGeminiCommandToml(command) {
|
|
249
249
|
const requiredInputs = command.input_contract?.required;
|
|
250
250
|
const optionalInputs = command.input_contract?.optional;
|
|
251
251
|
const executionSteps = command.execution_contract?.steps;
|
|
@@ -254,42 +254,49 @@ function renderAntigravityCommandDefinition(command) {
|
|
|
254
254
|
const nextRoles = command.handoff?.next_roles;
|
|
255
255
|
const blockers = command.handoff?.blockers;
|
|
256
256
|
|
|
257
|
+
const promptLines = [];
|
|
258
|
+
promptLines.push(`${command.id} - ${command.name}`);
|
|
259
|
+
promptLines.push(`Phase: ${command.phase ?? ''} | Owner: ${command.owner_role ?? ''}`);
|
|
260
|
+
promptLines.push('');
|
|
261
|
+
promptLines.push('[Purpose]');
|
|
262
|
+
promptLines.push(String(command.purpose ?? ''));
|
|
263
|
+
promptLines.push('');
|
|
264
|
+
promptLines.push('[Input Contract]');
|
|
265
|
+
promptLines.push('Required:');
|
|
266
|
+
for (const item of (requiredInputs ?? [])) {
|
|
267
|
+
promptLines.push(`- ${item}`);
|
|
268
|
+
}
|
|
269
|
+
promptLines.push('Optional:');
|
|
270
|
+
for (const item of (optionalInputs ?? [])) {
|
|
271
|
+
promptLines.push(`- ${item}`);
|
|
272
|
+
}
|
|
273
|
+
promptLines.push('');
|
|
274
|
+
promptLines.push('[Execution Steps]');
|
|
275
|
+
for (const [index, step] of (executionSteps ?? []).entries()) {
|
|
276
|
+
promptLines.push(`${index + 1}. ${step}`);
|
|
277
|
+
}
|
|
278
|
+
promptLines.push('');
|
|
279
|
+
promptLines.push('[Quality Gates]');
|
|
280
|
+
for (const gate of (qualityGates ?? [])) {
|
|
281
|
+
promptLines.push(`- ${gate}`);
|
|
282
|
+
}
|
|
283
|
+
promptLines.push('');
|
|
284
|
+
promptLines.push('[Output Artifacts]');
|
|
285
|
+
for (const artifact of (artifacts ?? [])) {
|
|
286
|
+
promptLines.push(`- ${artifact}`);
|
|
287
|
+
}
|
|
288
|
+
promptLines.push('');
|
|
289
|
+
promptLines.push('[Handoff]');
|
|
290
|
+
promptLines.push(`- next_roles: ${(Array.isArray(nextRoles) && nextRoles.length > 0 ? nextRoles.join(', ') : '(none)')}`);
|
|
291
|
+
promptLines.push(`- blockers: ${(Array.isArray(blockers) && blockers.length > 0 ? blockers.join(', ') : '(none)')}`);
|
|
292
|
+
promptLines.push('');
|
|
293
|
+
promptLines.push('Additional context: {{args}}');
|
|
294
|
+
|
|
295
|
+
const description = `${command.name} (${command.phase ?? ''} · ${command.owner_role ?? ''})`;
|
|
296
|
+
|
|
257
297
|
return [
|
|
258
|
-
|
|
259
|
-
'',
|
|
260
|
-
`# ${command.id} - ${command.name}`,
|
|
261
|
-
'',
|
|
262
|
-
`- phase: ${command.phase ?? ''}`,
|
|
263
|
-
`- owner_role: ${command.owner_role ?? ''}`,
|
|
264
|
-
'',
|
|
265
|
-
'## Purpose',
|
|
266
|
-
'',
|
|
267
|
-
String(command.purpose ?? ''),
|
|
268
|
-
'',
|
|
269
|
-
'## Input Contract',
|
|
270
|
-
'',
|
|
271
|
-
'### Required',
|
|
272
|
-
...toBulletLines(requiredInputs),
|
|
273
|
-
'',
|
|
274
|
-
'### Optional',
|
|
275
|
-
...toBulletLines(optionalInputs),
|
|
276
|
-
'',
|
|
277
|
-
'## Execution Contract',
|
|
278
|
-
'',
|
|
279
|
-
...toNumberedLines(executionSteps),
|
|
280
|
-
'',
|
|
281
|
-
'## Quality Gates',
|
|
282
|
-
'',
|
|
283
|
-
...toBulletLines(qualityGates),
|
|
284
|
-
'',
|
|
285
|
-
'## Output Contract',
|
|
286
|
-
'',
|
|
287
|
-
...toBulletLines(artifacts),
|
|
288
|
-
'',
|
|
289
|
-
'## Handoff',
|
|
290
|
-
'',
|
|
291
|
-
`- next_roles: ${(Array.isArray(nextRoles) && nextRoles.length > 0 ? nextRoles.join(', ') : '(none)')}`,
|
|
292
|
-
`- blockers: ${(Array.isArray(blockers) && blockers.length > 0 ? blockers.join(', ') : '(none)')}`,
|
|
298
|
+
`prompt = """${promptLines.join('\n')}"""`,
|
|
299
|
+
`description = "${description.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`,
|
|
293
300
|
''
|
|
294
301
|
].join('\n');
|
|
295
302
|
}
|
|
@@ -443,14 +450,14 @@ function renderClaudeLocalSettingsJson(securityPolicy) {
|
|
|
443
450
|
};
|
|
444
451
|
}
|
|
445
452
|
|
|
446
|
-
function
|
|
453
|
+
function renderGeminiEditorPolicyJson(securityPolicy) {
|
|
447
454
|
const shared = securityPolicy.shared_permissions ?? {};
|
|
448
455
|
return {
|
|
449
456
|
schema_version: '1.0.0',
|
|
450
457
|
policy_id: securityPolicy.policy_id ?? 'strict-dev',
|
|
451
458
|
description_ko:
|
|
452
|
-
'
|
|
453
|
-
editor: securityPolicy.
|
|
459
|
+
'Gemini CLI에서 수동 반영할 수 있는 프로젝트 보안/권한 정책 템플릿',
|
|
460
|
+
editor: securityPolicy.gemini?.editor_settings ?? {},
|
|
454
461
|
command_policy: {
|
|
455
462
|
allow_shell: shared.allow_bash ?? [],
|
|
456
463
|
ask_shell: shared.ask_bash ?? [],
|
|
@@ -680,14 +687,15 @@ async function pruneCodexCommandSkills(expectedDirNames, state) {
|
|
|
680
687
|
}
|
|
681
688
|
|
|
682
689
|
async function main() {
|
|
690
|
+
const packageJson = await readJson('package.json');
|
|
683
691
|
const commands = await readJson('common/commands/command-catalog.json');
|
|
684
692
|
const commonWorkflowCatalog = await readJson('common/workflows/workflow-catalog.json');
|
|
685
693
|
const skillCatalog = await readJson('common/skills/skill-catalog.json');
|
|
686
694
|
const securityPolicy = await readJson('common/settings/security-policy.json');
|
|
687
695
|
const claudeSubagents = await readJson('common/claude/subagent-catalog.json');
|
|
688
696
|
const claudeTeams = await readJson('common/claude/team-catalog.json');
|
|
689
|
-
const
|
|
690
|
-
const
|
|
697
|
+
const geminiAgents = await readJson('common/gemini/agent-catalog.json');
|
|
698
|
+
const geminiArtifacts = await readJson('common/gemini/artifact-catalog.json');
|
|
691
699
|
const { toolIds, catalogs: workflowCatalogByTool } = buildWorkflowCatalogByTool(
|
|
692
700
|
commonWorkflowCatalog
|
|
693
701
|
);
|
|
@@ -715,8 +723,8 @@ async function main() {
|
|
|
715
723
|
state
|
|
716
724
|
);
|
|
717
725
|
await writeOrCheck(
|
|
718
|
-
path.join(rootDir, '
|
|
719
|
-
toPrettyJson(
|
|
726
|
+
path.join(rootDir, 'gemini', 'settings', 'editor-policy.json'),
|
|
727
|
+
toPrettyJson(renderGeminiEditorPolicyJson(securityPolicy)),
|
|
720
728
|
state
|
|
721
729
|
);
|
|
722
730
|
await writeOrCheck(
|
|
@@ -736,7 +744,7 @@ async function main() {
|
|
|
736
744
|
state
|
|
737
745
|
);
|
|
738
746
|
await pruneGeneratedFilesBySuffix(
|
|
739
|
-
path.join(rootDir, '
|
|
747
|
+
path.join(rootDir, 'gemini', 'settings'),
|
|
740
748
|
'.json',
|
|
741
749
|
new Set(['editor-policy.json']),
|
|
742
750
|
state
|
|
@@ -748,14 +756,16 @@ async function main() {
|
|
|
748
756
|
state
|
|
749
757
|
);
|
|
750
758
|
|
|
751
|
-
const
|
|
759
|
+
const claudeCommandFileNames = new Set();
|
|
760
|
+
const geminiCommandFileNames = new Set();
|
|
752
761
|
const codexCommandSkillNames = new Set();
|
|
753
762
|
for (const command of commands.commands ?? []) {
|
|
754
763
|
if (!command?.id) {
|
|
755
764
|
throw new Error('[commands] command id가 비어 있습니다.');
|
|
756
765
|
}
|
|
757
766
|
const basename = normalizeCommandBasename(command.id);
|
|
758
|
-
|
|
767
|
+
claudeCommandFileNames.add(`${basename}.md`);
|
|
768
|
+
geminiCommandFileNames.add(`${basename}.toml`);
|
|
759
769
|
codexCommandSkillNames.add(basename);
|
|
760
770
|
|
|
761
771
|
await writeOrCheck(
|
|
@@ -764,8 +774,8 @@ async function main() {
|
|
|
764
774
|
state
|
|
765
775
|
);
|
|
766
776
|
await writeOrCheck(
|
|
767
|
-
path.join(rootDir, '
|
|
768
|
-
|
|
777
|
+
path.join(rootDir, 'gemini', 'commands', 'definitions', `${basename}.toml`),
|
|
778
|
+
renderGeminiCommandToml(command),
|
|
769
779
|
state
|
|
770
780
|
);
|
|
771
781
|
await writeOrCheck(
|
|
@@ -782,37 +792,56 @@ async function main() {
|
|
|
782
792
|
await pruneGeneratedFilesBySuffix(
|
|
783
793
|
path.join(rootDir, 'claude-code', 'commands', 'native'),
|
|
784
794
|
'.md',
|
|
785
|
-
|
|
795
|
+
claudeCommandFileNames,
|
|
786
796
|
state
|
|
787
797
|
);
|
|
788
798
|
await pruneGeneratedFilesBySuffix(
|
|
789
|
-
path.join(rootDir, '
|
|
799
|
+
path.join(rootDir, 'gemini', 'commands', 'definitions'),
|
|
800
|
+
'.toml',
|
|
801
|
+
geminiCommandFileNames,
|
|
802
|
+
state
|
|
803
|
+
);
|
|
804
|
+
// Remove legacy .md command definitions (migrated to .toml)
|
|
805
|
+
await pruneGeneratedFilesBySuffix(
|
|
806
|
+
path.join(rootDir, 'gemini', 'commands', 'definitions'),
|
|
790
807
|
'.md',
|
|
791
|
-
|
|
808
|
+
new Set(),
|
|
792
809
|
state
|
|
793
810
|
);
|
|
794
811
|
await pruneCodexCommandSkills(codexCommandSkillNames, state);
|
|
795
812
|
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
813
|
+
await writeOrCheck(
|
|
814
|
+
path.join(rootDir, 'gemini', 'gemini-extension.json'),
|
|
815
|
+
toPrettyJson({
|
|
816
|
+
name: 'tri-agent-manager',
|
|
817
|
+
version: packageJson.version,
|
|
818
|
+
description: 'Service operation skills and workflows pack for Gemini CLI',
|
|
819
|
+
contextFileName: 'GEMINI.md'
|
|
820
|
+
}),
|
|
821
|
+
state
|
|
822
|
+
);
|
|
823
|
+
|
|
824
|
+
// Workflows are gemini-only: only generate workflow catalog for gemini
|
|
825
|
+
{
|
|
826
|
+
const geminiCatalog = workflowCatalogByTool?.gemini;
|
|
827
|
+
if (!geminiCatalog) {
|
|
828
|
+
throw new Error('[workflows] gemini workflow catalog 누락');
|
|
800
829
|
}
|
|
801
|
-
const workflowPath = path.join(rootDir,
|
|
802
|
-
await writeOrCheck(workflowPath, toPrettyJson(
|
|
830
|
+
const workflowPath = path.join(rootDir, 'gemini', 'workflows', 'workflow-catalog.json');
|
|
831
|
+
await writeOrCheck(workflowPath, toPrettyJson(geminiCatalog), state);
|
|
803
832
|
}
|
|
804
833
|
|
|
805
|
-
const
|
|
806
|
-
for (const workflow of workflowCatalogByTool.
|
|
834
|
+
const geminiWorkflowNames = new Set();
|
|
835
|
+
for (const workflow of workflowCatalogByTool.gemini?.workflows ?? []) {
|
|
807
836
|
const filename = `${workflow.id}.workflow.yaml`;
|
|
808
|
-
|
|
809
|
-
const definitionPath = path.join(rootDir, '
|
|
810
|
-
await writeOrCheck(definitionPath,
|
|
837
|
+
geminiWorkflowNames.add(filename);
|
|
838
|
+
const definitionPath = path.join(rootDir, 'gemini', 'workflows', 'definitions', filename);
|
|
839
|
+
await writeOrCheck(definitionPath, renderGeminiWorkflowDefinition(workflow), state);
|
|
811
840
|
}
|
|
812
841
|
await pruneGeneratedFilesBySuffix(
|
|
813
|
-
path.join(rootDir, '
|
|
842
|
+
path.join(rootDir, 'gemini', 'workflows', 'definitions'),
|
|
814
843
|
'.workflow.yaml',
|
|
815
|
-
|
|
844
|
+
geminiWorkflowNames,
|
|
816
845
|
state
|
|
817
846
|
);
|
|
818
847
|
|
|
@@ -838,14 +867,14 @@ async function main() {
|
|
|
838
867
|
);
|
|
839
868
|
|
|
840
869
|
await writeOrCheck(
|
|
841
|
-
path.join(rootDir, '
|
|
842
|
-
toPrettyJson(
|
|
870
|
+
path.join(rootDir, 'gemini', 'agents', 'agent-catalog.json'),
|
|
871
|
+
toPrettyJson(geminiAgents),
|
|
843
872
|
state
|
|
844
873
|
);
|
|
845
874
|
|
|
846
875
|
await writeOrCheck(
|
|
847
|
-
path.join(rootDir, '
|
|
848
|
-
toPrettyJson(
|
|
876
|
+
path.join(rootDir, 'gemini', 'artifacts', 'artifact-catalog.json'),
|
|
877
|
+
toPrettyJson(geminiArtifacts),
|
|
849
878
|
state
|
|
850
879
|
);
|
|
851
880
|
|