Skip to main content

forge

포지(forge) — 셀프호스팅 Forgejo 이슈/PR/라벨/코멘트 작업면. 힣 에이전트가 코드 면에서 일하는 공유 손. botment의 자식 패턴(가든 댓글면 → 코드 댓글면 endpoint swap). 'forge', 'forgejo', '포지', 'issue', 'pull request', '이슈', '풀리퀘', '코드 댓글', '라벨'.

Informations de source

Dépôt
junghan0611/forge-config
Dernière activité de la source
4 septembre 2026 à 05:31
Langue détectée de SKILL.md
coréen
Étoiles
2
Forks
0

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
forge
description
포지(forge) — 셀프호스팅 Forgejo 이슈/PR/라벨/코멘트 작업면. 힣 에이전트가 코드 면에서 일하는 공유 손. botment의 자식 패턴(가든 댓글면 → 코드 댓글면 endpoint swap). 'forge', 'forgejo', '포지', 'issue', 'pull request', '이슈', '풀리퀘', '코드 댓글', '라벨'.
user_invocable
true
# forge — Forgejo 코드 작업면 힣 에이전트가 Forgejo 이슈/라벨/코멘트를 *공유 작업면*으로 쓰는 스킬. **botment의 자식 패턴**: 가든 댓글(remark42) → 코드 댓글(Forgejo) endpoint swap. ## SSOT CLI 본체는 [`forge-config`](https://github.com/junghan0611/forge-config) repo 안에 산다. agent-config은 이 SKILL.md만 들고, 실 명령은 외부 절대경로로 호출한다. ``` ~/repos/gh/forge-config/bin/forge ``` 이 스킬에서 다루는 동사/플래그/env 변수가 실제 동작과 어긋나면 **bin/forge가 정답**이다. 의문 시 `~/repos/gh/forge-config/AGENTS.md` 와 `NEXT.md` 확인. 운영 인스턴스 (2026-05-27 기준): | profile | URL | 용도 | |---------|-----|------| | `oracle` | `https://forge.junghanacs.com` | 개인 / 공개 정원 페어 (`repos/gh/*`) | | `work` | `https://<work-forge-host>/forge` | 회사 / mirror 운영면 (`repos/work/*`) | ## 핵심 원칙 1. **공장 모델 거부** — 병렬 에이전트 수가 아니라 *공유 컨텍스트와 자취*가 핵심 2. **단일 신원** — Forgejo 사용자 `glg-bot` 하나, footer 서명으로 모델/호스트 식별 3. **사람 게이트 merge** — v1에서 자동 merge 없음 4. **닫힌 계** — 시크릿은 `~/.env.local` + `pass`. repo 에는 변수명만 5. **운영 머신 ≠ forge 인스턴스** — thinkpad 에서 양쪽 forge 다 굴린다 (세션이 thinkpad 에 남아야 andenken 임베딩됨). cwd 가 어느 forge 인지 결정한다. 6. **auto-fix는 완료가 아니라 검증 루프 시작** — minor/bounded patch candidate 뒤에 1회독 direct fix/test, 2회독 주변 동형 패턴 전수조사, 3회독 독립 리뷰, follow-up issue 생성까지 남긴다. ## 환경 변수 — profile 시스템 `bin/forge` 가 호출 시점에 **profile** 을 자동 결정해서 prefix 변수를 풀어쓴다. 에이전트는 변수만 박혀있는지만 확인하면 된다. ### Profile 결정 우선순위 (높을수록 우선) 1. `--forge oracle|work` 플래그 2. `FORGE_PROFILE` env (`oracle` / `work`) 3. **cwd 패턴 — 명시 anchor 만**: - `*/repos/work/*` → `work` - `*/repos/gh/*` → `oracle` - **그 외 (`~`, `~/org/`, `~/Downloads/` 등)** → 에러. 명시 요구. 4. Legacy env value fallback (URL/TOKEN 만) — profile prefixed 가 비어있을 때 unprefixed `FORGE_URL`/`FORGE_TOKEN` 참조. host-scoped switching 결과 (oracle/work 에 직접 ssh 들어갔을 때만 의미). `FORGE_REPO` 는 fallback 없음 (인스턴스 간 leak 방지). → thinkpad 에서 `cd ~/repos/gh/foo && forge list-open` 하면 자동 oracle. → `cd ~/repos/work/bar && forge state 3` 하면 자동 work. → `cd ~ && forge list-open` 은 **silent oracle default 금지** — 명시 요구. mutating 사고 방지. → `forge --forge work list-open glg-bot/<work-repo>` 로 어디서든 명시 override. ### Mutating 명령 stderr observability `comment` / `label-add` / `label-remove` / `label-set` 호출 시 stderr 에 한 줄 노출: ``` [forge] profile=oracle repo=glg-bot/sandbox url=https://forge.junghanacs.com ``` → 잘못된 인스턴스/repo 에 write 하기 전에 즉시 인지. `FORGE_PROFILE` env 가 셸에 오래 남아 cwd 보다 우선될 때의 사고도 같은 표면으로 잡힌다. ### Profile-prefixed env (`~/.env.local` SSOT) | 변수 | 필수 | 비고 | |------|------|------| | `ORACLE_FORGE_URL` / `_TOKEN` / `_USER` | ✅ | oracle profile 원천 | | `WORK_FORGE_URL` / `_TOKEN` / `_USER` | ✅ | work profile 원천 | | `ORACLE_FORGE_REPO` | ⭕ | default `glg-bot/sandbox` | | `WORK_FORGE_REPO` | ⭕ | default 없음 — 인자로 명시 강제 | | `FORGE_MODEL` | ⭕ | footer 의 모델 부분 (없으면 `unknown`) | > `bin/forge` 는 profile 토큰이 env 에 없으면 **`~/.env.local` 을 스스로 source** > 한다. pi 는 env 를 자동 주입하므로 sourcing 을 건너뛰고, Claude Code / 맨 셸 > 처럼 주입이 없는 하네스에서도 `source ~/.env.local` 선행 없이 바로 돈다. > 토큰이 이미 있으면(주입/명시 override) 덮지 않는다. 경로는 `FORGE_ENV_FILE` 로 교체. ### 머신별 default profile — `~/.current-forge-profile` 각 머신이 "어느 forge 의 *직접 접속 호스트* 인지" 박는다. 클라이언트 머신은 비워둔다. | 머신 | 정체성 | 파일 | |---|---|---| | oracle | "oracle forge 의 호스트" | `echo oracle > ~/.current-forge-profile` | | 회사 머신 | "work forge 의 호스트" | `echo work > ~/.current-forge-profile` | | thinkpad / laptop / nuc 등 | 양쪽의 **클라이언트** (호스트 아님) | **없음** — cwd 로 매번 결정 | `.env.local` 의 case 분기가 이 파일을 입력으로 unprefixed `FORGE_URL`/`TOKEN`/`USER` 를 set 한다. 클라이언트 머신은 case 매칭 실패 → bin/forge 의 cwd 패턴 결정에 자연 위임. > 참고: `FORGE_BOT_FOOTER` env 는 **무시된다**. footer 형식은 정책이라 > 매 호출마다 `bin/forge` 가 자동 조립한다 — 깨진 부모 셸 env 가 발현되지 > 않도록 닫아둔 표면. 모델은 `FORGE_MODEL` 로만 customize. ### footer 자동 조립 ``` — glg-bot [<FORGE_MODEL or "unknown"> / <~/.current-device or "unknown">] ``` 세션 시작 시 모델만 박아두면 footer 가 정확해진다: ```bash export FORGE_MODEL="claude-opus-4-8" # thinkpad 에서 oracle forge 코멘트 → "— glg-bot [claude-opus-4-8 / thinkpad]" # 같은 thinkpad 에서 work forge 코멘트 → 동일 footer (작업 머신 기준) ``` env 미설치 시 `bin/forge` 가 친절한 에러를 던지므로 그것을 따라가면 된다 (`FORGE_URL is required (profile=<name> — set <NAME>_FORGE_URL in ~/.env.local)`). ## 발견성 — namespace 와 처음 만난 repo 각 forge 인스턴스의 봇 namespace 는 **`glg-bot/*`** (oracle / work 양쪽 동일). 처음 다루는 repo 라 *어느 path 에 박지* 모르면 GitHub remote 의 `teamgoqual/*` / `junghan0611/*` 를 그대로 추측하지 말 것 — forge namespace 와 안 맞는다. 발견 recipe: ```bash forge --forge work repos # work forge 의 glg-bot/* 실재 목록 forge --forge oracle repos # oracle forge 의 glg-bot/* 실재 목록 forge --forge work repos <other> # 다른 namespace 도 명시 가능 ``` 운영 사실 (자취): - oracle forge → `glg-bot/forge-config`, `glg-bot/sandbox` - work forge → `glg-bot/voscli`, `glg-bot/incidentcli`, `glg-bot/sandbox` GitHub repo 의 `<owner>/<name>` 에서 `<name>` 만 떼서 `glg-bot/<name>` 매핑하는 게 자연 fallback 이지만, 실재하지 않을 수 있다 — `forge repos` 로 먼저 확인한 뒤 매칭. ## API — v2 동사 9개 | 명령 | 인자 | 동작 | |------|------|------| | `repos` | `[OWNER]` | 현 profile 의 봇 namespace (기본 `<FORGE_USER>` = `glg-bot`) 아래 실재 repo 목록. **처음 만난 forge 의 발견 자리** | | `list-open` | `[REPO]` | 열린 이슈 목록 (제목 + 라벨 + 코멘트 수). REPO 생략 시 default repo | | `state` | `ISSUE` | 이슈 상태 + 라벨 + 최근 코멘트 3개 | | `comment` | `ISSUE BODY` 또는 `ISSUE --body-file PATH|-` | 코멘트 작성. footer 자동 부착. **multi-line / child 결과는 `--body-file` 사용** | | `label-add` | `ISSUE LABEL` | 라벨 이름으로 ID 조회 후 부착 | | `label-remove` | `ISSUE LABEL` | 라벨 이름으로 ID 조회 후 제거 | | `label-set` | `ISSUE STATUS-LABEL` | 상태 라벨군(`agent:ready/running/done/blocked`, `human:needs-review`)을 하나로 교체. `ci:failed` 같은 신호 라벨은 보존. forgebot 루프의 `agent:done` = 1차 검토/분류 완료, 구현 완료 아님 | | `close` | `ISSUE` | Forgejo open/closed **state** 를 `closed` 로. lifecycle 라벨과 직교 — `agent:done`(분류 완료) ≠ `closed`(해결/철회, 추적 종료). 이유 `comment` 먼저, 그다음 close. **규약**(코드 가드 아님): 해결-close(shipped tag/commit + 재현 안 됨 확인) = 담당자 자율 ✅ / 철회-close(won't-fix·중복·설계무효·우선순위 철회 = 가치판단) = GLG 또는 `human:needs-review` 경유 | | `reopen` | `ISSUE` | 닫힌 이슈 state 를 `open` 으로 되돌림 (close 의 역) | | `issue-create` | `[REPO] TITLE BODY [OPTIONS]` 또는 `[REPO] TITLE --body-file PATH [OPTIONS]` | 이슈 생성. footer 자동 부착. atomic 라벨 (`--labels`) + Mattermost thread bridge (`--mm-channel/--mm-root-id/--mm-account`) 옵션. **multi-line BODY 는 `--body-file PATH` (또는 `-` = stdin) 필수** — inline BODY 는 single-line 만 | | `auto-fix-template` | `ISSUE` | auto-fix 회독 루프용 표준 코멘트 골격 출력. `schema/report_id/session_key/issue_updated_at/lifecycle/labels/provider_model/forge_config_commit` snapshot marker 포함. 출력 → 파일 저장 → 채운 뒤 `comment --body-file` | | `doctor-labels` | `[REPO]` | repo 가 forge v2 + auto-fix lane 에 필요한 lifecycle/signal labels (`agent:*`, `human:needs-review`, `ci:failed`, `auto-fix`) 를 갖췄는지 read-only 점검. missing 이 있으면 non-zero exit | `ISSUE` / `REPO` 인자 형식: - `1` → default repo 의 #1 - `glg-bot/sandbox#1` → 명시된 repo 의 #1 - `owner/repo` (REPO) / `repo` (`<FORGE_USER>/repo` 로 확장) `issue-create` — sweeper 의 일차 입력 자리: ```bash # atomic 라벨 — 라벨 부착이 별도 호출이 아니라 생성과 동시 forge --forge work issue-create glg-bot/<work-repo> \ "Bug: foo 안 됨" "운영팀 보고..." \ --labels agent:ready # multi-line BODY — 파일 또는 stdin 사용 (inline 인자에 \n 넣으면 positional 파서가 깨짐) forge --forge work issue-create glg-bot/<work-repo> \ "Feature: weekly/monthly VOC range report" \ --body-file /tmp/voc-issue.md \ --labels agent:ready cat <<'EOF' | forge --forge work issue-create glg-bot/<work-repo> \ "Feature: weekly/monthly VOC range report" --body-file - --labels agent:ready ## 배경 지난 분기 데이터 ... ## 요구 - 주간/월간 범위 ... EOF ``` ### Mattermost thread bridge — `--mm-channel/--mm-root-id/--mm-account` 봇이 Mattermost thread 에서 받은 요청으로 이슈 생성할 때, *원래 thread* 로 lifecycle 자취가 돌아가게 metadata 박을 자리. forge agent 가 이슈 처리 후 OpenClaw message tool 의 `replyTo` 로 같은 thread 에 답장하기 위함. (`replyToId` 아님 — 실제 schema 는 `target: "channel:<channel_id>"`, `replyTo: "<root_id>"`.) ```bash forge --forge work issue-create glg-bot/voscli \ "Bug: foo 안 됨" --body-file - --labels agent:ready \ --mm-channel cidABC123 --mm-root-id ridXYZ789 # --mm-account default = "forgebot" ``` 자취 두 자리에 박힘: - **issue body 끝** — `<!-- openclaw:mm {"channel_id":"...","root_id":"...","account":"..."} -->` HTML comment. 렌더된 마크다운에 사람한테 안 보임, 봇이 read 시 회수 - **로컬 SQLite SSOT** — `~/.openclaw/state/forge-mm-links.sqlite`. key `<profile>:<repo>#<issue_num>` → `{channel_id, root_id, account_id, created_at}`. `sqlite3` 없으면 WARN 한 줄 + 계속 (body metadata 가 canonical) 검증: - `--mm-channel` 과 `--mm-root-id` 는 **둘 다 박혀야** 한다. 한쪽만 박으면 ERROR exit 2 — 부분 metadata 가 thread bridge 동작 침묵 깨짐 자리 추가 동사(`read`, `pr ...`)는 v2 이후 운영 누적 후 forge-config 측에서 박는다. 여기서 동사를 임의로 늘리지 말 것 (SSOT 어긋남). ## git push 인증 — `git-credential-forge` `bin/forge` 는 **REST 작업면**(issue/label/comment)이다. forge repo 에 *코드를 push* 하는 건 별개 레이어 — git 의 HTTPS 인증이다. 이 자리를 채우는 게 sibling 바이너리 `bin/git-credential-forge`. 핵심: REST 와 **같은 `~/.env.local` profile 토큰**(`ORACLE_FORGE_TOKEN` / `WORK_FORGE_TOKEN`)을 git 의 native credential 기계로 잇는다. 토큰-in-URL 도, askpass 도, 분신마다 재발명도 없다 — forge 서버는 oracle/work 에 있어도 `git push` 는 어느 **클라이언트(thinkpad/nuc/laptop)** 에서나 그냥 동작한다. - **generic / host 자동판별** — url-scope 없이 helper *하나*. git 이 모든 https credential 요청에 부르면, helper 가 들어온 host(+git 이 주면 path-prefix)를 env.local 의 `ORACLE/WORK_FORGE_URL` 과 매칭해 맞는 토큰을 emit, forge 가 아니면 침묵해서 git 이 다음 helper(github 등)로 넘어간다. → **어떤 committed 파일에도 forge host literal 이 안 박힌다** (work host 가 identity term 이라 중요). - **path 격리** — work forge 는 `<work-host>/forge` 처럼 path prefix 아래 있고, 그 host 는 다른 https git 을 서빙할 수 있다. `credential.useHttpPath true` 면 helper 가 forge path prefix 를 요구해서, 같은 host 의 비-forge 서비스가 work 토큰을 못 받는다. oracle forge 는 전용 host(prefix 없음) → host-only 가 정답. - SSOT 는 `~/.env.local`. helper 는 런타임에만 토큰을 emit — 디스크에 안 쓴다 (`~/.git-credentials` 평문 복제 없음). ### 설치 — 기기마다 두 줄 (machine-local `~/.gitconfig`, nixos 아님) ```bash git config --global credential.helper ~/repos/gh/forge-config/bin/git-credential-forge git config --global credential.useHttpPath true # path 격리 (특히 work host) ``` `~/.gitconfig`(writable, machine-local)에 들어간다. home-manager 가 잡은 `~/.config/git/config`(nix 심링크, read-only)는 안 건드린다 — git 이 둘 다 읽어 머지한다. **nixos rebuild 불필요** (설치 자리 = `~/.gitconfig`, 결정 2026-06-02). > work forge host 는 identity term 이지만, helper 가 host 를 env.local 에서 런타임 > 추출하므로 이 두 줄에도 forge-config repo 에도 host 가 안 박힌다. env.local 은 > 기기 간 동기화(클라이언트 + 양쪽 forge 호스트 모두 `ORACLE_*`+`WORK_*`)라
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub