Community코딩 & 개발github.com

fangdididi/trigger-rehearsal

이벤트 중심 또는 백그라운드 에이전트의 트리거 규칙을 실제로 활성화하기 전에 리허설합니다. 에이전트 허브 규칙 파일, 루틴, CI 'on:' 블록, 크론 라인, 코드리스 자동화 등 어떤 형식으로 작성된 규칙이든 하나의 중립적인 규칙 시트로 변환하고, 자기 트리거 루프, 보호되지 않은 체인, 누락된 상한, 이중 처리를 린트한 후, 실제 또는 기록된 이벤트를 재생하여 시작되었을 모든 실행, 병합, 건너뛰기, 대기 또는 드롭된 항목, 그리고 비용을 보여줍니다.

trigger-rehearsal란 무엇인가요?

Trigger Rehearsal은 이벤트 중심 또는 백그라운드 에이전트의 트리거 규칙을 실제로 활성화하기 전에 안전성과 효율성을 검증하는 전문 AI 에이전트 스킬입니다. 에이전트가 이벤트에 반응하여 자동으로 작업을 시작할 때, 문제는 대개 에이전트 자체가 아니라 트리거 규칙에 있습니다. 이 스킬은 다양한 형식(에이전트 허브 규칙 파일, CI 워크플로우 'on:' 블록, 크론탭, 코드리스 자동화 등)으로 작성된 규칙을 하나의 중립적인 `rules.json` 형식으로 변환하고, 자기 트리거 루프, 보호되지 않은 체인, 누락된 상한, 이중 처리 등 일반적인 문제를 린트합니다. 그런 다음 실제 또는 합성된 이벤트(예: GitHub 웹후크 로그, 헬프데스크 감사 로그)를 재생하여 각 규칙이 하루 또는 일주일 동안 얼마나 자주 실행될지, 어떤 실행이 병합, 건너뛰기, 대기 또는 드롭되는지, 그리고 예상 비용을 상세한 타임라인과 함께 보여줍니다. 결과는 ARM(안전), TRIM(최적화 필요), HOLD(활성화 금지) 중 하나로 제공되며, CI 파이프라인에서 구성 변경을 게이트하는 데 사용할 수 있습니다. 이 스킬은 Claude Code, Cursor, Codex 등 모든 AI 에이전트 플랫폼에서 사용할 수 있으며, 특히 예산 관리, 디바운스 윈도우, 병렬 제한, 일일 상한 설정에 유용합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/fangdididi/trigger-rehearsal/tree/HEAD

Installed? Explore more 코딩 & 개발 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

트리거 리허설

개요

이벤트에 스스로 깨어나는 에이전트는 트리거 규칙만큼만 안전합니다. 에이전트 자체가 아무리 조심해도 하루 예산을 모두 소진할 수 있습니다. 문제는 보통 한 단계 위에 있습니다:

  • 규칙이 자신의 작업이 생성한 이벤트에 반응하여 계속해서 다시 실행됩니다.
  • 두 규칙이 두 번째 시스템을 통해 서로를 피드백합니다 (에이전트가 댓글을 달고, 댓글이 동기화되며, 동기화가 웹훅을 발생시킴).
  • 시끄러운 소스가 2분 안에 10개의 편집을 보내고 각각이 새로운 실행을 시작합니다.
  • "가끔 확인"을 의미하는 크론 라인이 하루에 288번 실행됩니다.
  • 두 규칙이 동일한 이벤트를 처리하여 작업을 두 번 수행합니다.
  • 환불, 삭제 또는 메시지를 보내는 규칙이 누구의 허락도 없이 실행됩니다.

이러한 문제는 에이전트를 하나의 예제로 테스트할 때 나타나지 않습니다. 실제 트래픽이 도착할 때 나타납니다. Trigger Rehearsal은 실제 트래픽을 일찍, 종이 위에서 만듭니다: 규칙을 하나의 중립적인 형식으로 작성하고, 하루 또는 일주일 분량의 이벤트를 재생하며, 아무것도 활성화되기 전에 타임라인을 읽습니다.

사용 시기

  • 사람이 프롬프트를 입력하지 않고 에이전트가 작업을 시작하도록 허용하는 규칙을 켜기 전에.
  • 기존 규칙 집합에 새 규칙을 추가할 때 (새 규칙이 이전에 열려 있던 루프를 닫을 수 있음).
  • 백그라운드 에이전트가 예상보다 훨씬 자주 또는 훨씬 적게 실행될 때.
  • 디바운스 윈도우, 병렬 제한 및 일일 상한을 선택할 때, 추측 대신 숫자를 원할 때.
  • 리뷰어가 "이 Repo에 한 시간에 50개의 이슈가 들어오면 어떻게 되나요?"라고 물을 때.

사용하지 않는 경우: 에이전트가 실행 내부에서 무엇을 하는지 확인 (프롬프트 또는 스킬 질문), 또는 이벤트 소스 자체를 부하 테스트.

규칙 시트

모든 것은 rules.json으로 변환됩니다. 번역을 정직하게 유지하세요: 실제 규칙당 하나의 시트 규칙, 그리고 실제로 존재하는 가드(보호 장치)를 작성하고, 추가하려는 가드는 작성하지 마세요.

{
  "tz": "Asia/Shanghai",
  "run_s": 180,
  "external_sources": ["github"],
  "budget": {"runs_per_day": 40, "cost_per_run": 0.15, "cost_per_day": 6},
  "rules": [
    {
      "name": "triage-new-issue",
      "on": {"source": "github", "types": ["issues.opened", "issues.edited"]},
      "where": {"repo": "me/app"},
      "key": "subject",
      "debounce_s": 300,
      "parallel": 1,
      "max_per_day": 20,
      "unless_actor": ["my-bot"],
      "unless_label": "triaged",
      "emits": [{"source": "github", "types": ["issues.labeled"], "actor": "my-bot", "labels": ["triaged"]}],
      "sensitive": [],
      "asks": false
    },
    {"name": "morning-digest", "on": {"cron": "0 9 * * 1-5"}, "max_per_day": 1}
  ]
}
필드의미
on.source + on.types규칙을 시작하는 이벤트. types를 생략하면 해당 소스의 모든 유형과 일치합니다.
on.cron시트의 tz에 있는 5필드 크론 라인. 규칙은 source 또는 cron 중 하나를 가집니다.
where값과 같아야 하거나 (또는 목록 중 하나여야 하는) 이벤트 필드.
key주제 (이슈 번호, 티켓 ID, URL)를 명명하는 이벤트 필드. 반복 병합에 사용됩니다.
debounce_s한 주제에 대해 마지막 이벤트 후 이 시간만큼 기다린 다음 한 번 실행합니다.
parallel이 규칙의 동시 활성 실행 수. 초과 실행은 대기합니다.
max_per_day로컬 일 기준 상한. 초과 실행은 드롭됩니다.
run_s일반적인 실행 시간, 대기열에 사용됩니다. 시트 값으로 대체된 다음 120으로 대체됩니다.
unless_actor, unless_label가드: 이러한 액터가 만들거나 이 레이블이 있는 이벤트를 건너.
emits실행 자체가 생성하는 이벤트 (댓글, 레이블, 상태 변경, 후속 이벤트). 포함할 액터와 레이블을 작성하세요.
sensitive + asks사람이 필요한 작업 (삭제, 지출, 재시작, 보내기). asks: true는 실행이 중지되고 먼저 묻는다는 의미입니다.
external_sources외부 세계에서 공급되는 소스. 다른 모든 것은 규칙에 의해 방출되어야 합니다.
budget판결에 사용되는 선택적 일별 실행 횟수, 실행당 비용 및 일별 비용.

단계별 가이드

  1. 실제 규칙 수집. 설명이 아닌 실제 구성을 읽으세요. 에이전트 허브 규칙 파일, 저장된 루틴, CI 워크플로우 on: 블록, crontab 라인, 코드리스 자동화 화면. 다른 규칙이 감시하는 소스에 다시 쓰는 모든 것을 기록하세요.
  2. rules.json으로 변환. python3 scripts/rehearse.py new rehearsal/로 시작하세요. 모든 규칙에 대해 세 가지 질문을 하고 필드를 채우세요: 무엇이 깨우는가, 한 번의 실행이 무엇을 다시 쓰는가, 그리고 자신의 쓰기로 인해 깨어나는 것을 막는 것은 무엇인가. 세 번째 질문에 대한 답이 "없음"이면 가드를 비워두세요. 리허설은 그것을 잡기 위한 것입니다.
  3. 린트. python3 scripts/rehearse.py lint rehearsal/rules.json. 재생하기 전에 모든 HOLD를 수정하세요. REVIEW 항목은 숫자를 기다릴 수 있습니다.
  4. 이벤트 수집. 가장 좋은 방법: 소스에서 실제 바쁜 하루를 내보내세요 (웹후크 전송 로그, 이슈 타임라인, 헬프데스크 감사 로그)를 events.jsonl로, 한 줄에 하나의 JSON 객체로, 최소 t, source, type을 포함하고 key와 where가 사용하는 필드를 포함하세요. 기록이 없으면 의도적으로 짧은 합성 버스트를 작성하세요: 3분 안에 10개의 편집, 한 번에 두 개의 주제, 자신의 봇이 만든 이벤트.
  5. 전체 일별 재생. python3 scripts/rehearse.py replay rehearsal/rules.json rehearsal/events.jsonl --from 2026-11-02T00:00:00Z --to 2026-11-03T00:00:00Z --md rehearsal/report.md. --from/--to를 전달하여 짧은 창으로 인해 일별 숫자가 부풀려지지 않도록 하세요.
  6. 판결만이 아닌 타임라인 읽기. 몇 분 간격으로 같은 주제에 대한 실행을 찾으세요 (디바운스 누락 또는 너무 짧음), 깊이가 증가하는 체인 (루프), 긴 대기 (병렬 수준 너무 낮음), 드롭 (실제 작업에 비해 상한이 너무 낮거나 규칙이 노이즈에 실행된다는 신호).
  7. 조정 및 반복. 한 번에 하나의 노브를 변경하고 동일한 이벤트를 재생하여 변화가 명확히 해당 변경에서 비롯되도록 하세요.
  8. 결정. 현실적인 하루에 대한 마지막 재생이 ARM인 경우에만 활성화하세요. 최종 rules.json, 이벤트 파일 및 report.md를 규칙이 켜진 이유에 대한 기록으로 함께 보관하세요.

판결

  • ARM: HOLD 또는 REVIEW 발견 사항 없음. 작성된 대로 활성화해도 안전합니다.
  • TRIM: 실행을 낭비하거나 작업을 건너뛸 수 있음 (키 없음, 상한 없음, 중복, 상한이 실제 이벤트를 드롭함, 예산 근접). 트리밍 후에만 활성화하거나, 서면 사유와 함께 활성화하세요.
  • HOLD: 활성화하지 마세요. 자기 루프, 보호되지 않은 사이클, 깊이 5를 넘어 실행된 체인, 묻지 않고 수행되는 민감한 작업, 예산 초과 또는 깨진 크론 라인.

종료 코드는 판결을 따릅니다 (0, 1, 2; 3은 잘못된 입력을 의미). 따라서 리허설은 CI에서 구성 변경을 게이트할 수 있습니다.

예제

지원 팀이 에이전트가 헬프데스크 티켓에 응답하도록 하려고 합니다. 그들의 시트 (examples/loopy/)에는 답변을 게시하는 규칙이 있으며, 이는 티켓을 업데이트하고, 이는 동일한 규칙과 일치합니다. 평범한 하루의 재생 결과는 다음과 같습니다:

HOLD   self-loop            answer-ticket: 규칙의 자체 출력이 unless_actor/unless_label 가드 없이 자체 트리거와 일치
HOLD   runaway              answer-ticket: 체인이 깊이 5를 넘어 계속 재실행됨 (3회 차단)
HOLD   sensitive-unasked    refund-check: 민감한 작업 ['refund'] 선언했지만 'asks'가 true가 아님
HOLD   over-runs-budget     -: 100.0/일 (예산 30/일 대비)
REVIEW cron-tight           inbox-poll: 최대 720회/일 실행
VERDICT HOLD

세 번의 티켓 업데이트가 18번의 답변 실행으로 이어졌습니다. 수정은 간단합니다: 답변 규칙에 "unless_actor": ["support-bot"]을 추가하고, 환불 규칙에 "asks": true를 설정하며, 2분 폴링을 받은 편지함이 실제로 변경된 경우에만 inbox.changed를 발생시키는 스크립트로 대체하세요 (examples/loopy/rules.fixed.json 참조). 같은 날의 다음 재생은 100회 실행에서 4회로 줄어들고 판결은 TRIM으로 이동합니다. 남은 발견 사항 하나는 응답과 환불 확인 모두 환불 티켓을 본다는 것인데, 이는 의도된 것이므로 보고서 옆에 한 줄의 서면 사유와 함께 수락됩니다.

팁

  • 가장 좋은 단일 루프 방어는 실행 후에 거짓이 되는 조건입니다: 실행이 추가하고 규칙이 제외하는 레이블, 또는 규칙이 더 이상 일치하지 않는 상태.
  • 교차 시스템 루프는 놓치기 쉽습니다. 에이전트가 시스템 A에 쓰고 시스템 A가 B로 동기화되면, 동기화된 이벤트를 표시할 액터와 함께 emits 아래에 나열하세요.
  • 디바운스는 설계상 지연을 추가합니다. 사람이 편집 버스트를 완료하는 데 걸리는 시간에서 창을 선택하고, 누군가가 답변을 기다리는 곳에서는 짧게 유지하세요.
  • 디바운스는 작업 중복 제거가 아닙니다. 되돌릴 수 없는 작업의 경우, 실행 자체는 작업 전에 여전히 "이미 완료되었나?"를 확인해야 합니다.
  • 일일 상한은 퓨즈이지 계획이 아닙니다. 보통 하루 재생이 상한에 도달하면 규칙이 너무 광범위합니다.
  • 몇 분마다 폴링하는 것은 일반적으로 상태를 비교하고 변경 시 하나의 이벤트를 발생시키는 작은 스크립트로 더 저렴합니다. 에이전트는 새로운 것이 있을 때만 깨어납니다.
  • 규칙이 추가될 때마다 리허설을 다시 실행하세요. 대부분의 루프는 첫 번째 규칙이 아니라 두 번째 규칙에 의해 생성됩니다.

관련 스킬