@kaydash9999/banker-plugins 0.15.2 → 0.16.1

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.
Files changed (41) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +65 -0
  4. package/README.md +31 -9
  5. package/codex/manifest.json +6 -3
  6. package/codex/transform-matrix.md +2 -0
  7. package/commands/progress.md +10 -0
  8. package/commands/setup.md +1 -1
  9. package/hooks/graceful-pause.mjs +31 -71
  10. package/hooks/hooks.json +11 -1
  11. package/hooks/progress-fallback.mjs +10 -0
  12. package/hooks/progress.mjs +427 -0
  13. package/hooks/register.mjs +82 -5
  14. package/package.json +1 -1
  15. package/skills/3d-intro-build/SKILL.md +238 -122
  16. package/skills/3d-intro-build/references/NOTICE.md +2 -1
  17. package/skills/3d-intro-build/references/assemble.mjs +164 -108
  18. package/skills/3d-intro-build/references/azure-adapter.mjs +204 -44
  19. package/skills/3d-intro-build/references/curate.mjs +573 -267
  20. package/skills/3d-intro-build/references/intro-fixes.css +61 -0
  21. package/skills/3d-intro-build/references/panel-glass.css +55 -0
  22. package/skills/3d-intro-build/references/preview-lib.mjs +256 -0
  23. package/skills/3d-intro-build/references/prompts.md +32 -9
  24. package/skills/3d-intro-build/references/serve.mjs +111 -103
  25. package/skills/3d-intro-build/references/step-nav.css +59 -0
  26. package/skills/3d-intro-build/references/step-nav.js +503 -0
  27. package/skills/3d-intro-build/references/verify-intro.mjs +474 -0
  28. package/skills/3d-intro-build/references/verify.md +45 -0
  29. package/skills/3d-intro-build/references/video-pool.mjs +817 -0
  30. package/skills/3d-intro-setup/SKILL.md +120 -47
  31. package/skills/3d-intro-setup/references/azure-adapter.mjs +204 -44
  32. package/skills/3d-intro-setup/references/video-pool.mjs +817 -0
  33. package/skills/motion-graphic-make/SKILL.md +73 -28
  34. package/skills/motion-graphic-make/references/curate.mjs +607 -0
  35. package/skills/motion-graphic-make/references/preview-lib.mjs +256 -0
  36. package/skills/motion-graphic-make/references/serve.mjs +131 -0
  37. package/skills/omc-patch/SKILL.md +143 -0
  38. package/skills/omc-patch/scripts/omc-patch.mjs +577 -0
  39. package/skills/remains/SKILL.md +125 -0
  40. package/skills/remains/scripts/boxes.mjs +448 -0
  41. package/skills/trouble-shooting/SKILL.md +50 -0
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Claude Code skills + commands — QA, audit, docs, architecture, dependency setup, and wiki; the banker plugin marketplace.",
9
- "version": "0.15.2"
9
+ "version": "0.16.1"
10
10
  },
11
11
  "plugins": [
12
12
  {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "banker",
3
- "version": "0.15.2",
3
+ "version": "0.16.1",
4
4
  "description": "Claude Code plugin: QA/audit/docs/architecture skills + commands, a /banker:setup installer for OS dependencies (playwright, etc.), and wiki compaction.",
5
5
  "author": {
6
6
  "name": "smallOpenSource",
package/CHANGELOG.md CHANGED
@@ -1,5 +1,70 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.16.1] - 2026-10-11
4
+
5
+ ### Security
6
+ - **3d-intro 의 API 키는 https 로만 간다.** 0.16.0 은 Sora 영상 생성, Azure 이미지 생성과 목록, setup 프리플라이트가 `http://` endpoint 에도 키를 평문으로 보냈다(https 확인은 Sora `resumeClip` 에만 있었다).\
7
+ 이제 키 헤더가 실린 요청은 https 로만 가고, http 는 이 기기의 localhost 만 허용한다. 그 밖의 http endpoint 는 보내기 전에 막는다. Sora 영상 단계는 `invalid_request` 로 멈추고, 그 밖의 호출은 `HTTP 0 (EINSECURE)` 오류다. WAN endpoint 도 https 만 받는다.
8
+ - **리다이렉트로 키, 프롬프트, 유료 제출이 다른 곳에 가지 않는다.** 0.16.0 의 fetch 는 리다이렉트를 따라가며 `api-key` 헤더를 다른 출처에 넘겼고, 307, 308 에서는 프롬프트와 프레임을 다시 보냈다. 이제 리다이렉트를 직접 따라간다(최대 5회).\
9
+ 다른 출처로는 키 헤더 없이 본문 없는 GET 만 보낸다. 본문이 있는 요청은 다른 출처로 따라가지 않아, 그곳의 401, 429 를 키의 답으로 읽고 다른 키로 다시 제출하는 일(이중 과금)이 없다. https 를 벗어나는 리다이렉트(예: 다운로드 URL 이 `http://169.254.169.254` 로 보내는 것)도 따라가지 않는다. Location 이 URL 이 아니면 그 제출을 "보내지 않음" 으로 보지 않는다.
10
+ - **`3d-intro-setup` 이 키를 채팅이나 명령줄로 받지 않는다.** 키는 사람이 `umask 077` 로 만든 키 파일에 직접 적거나, 콘솔 샘플을 비공개 파일로 저장하면 에이전트가 화면에 내지 않고 합친다.\
11
+ 합칠 때는 `resolveCreds` 가 이미 읽는 키 파일(홈 fallback 포함)에 쓰고, 홈 키 파일이 있으면 프로젝트 키 파일을 새로 만들지 않는다(만들면 홈의 키가 가려진다). 파일의 다른 키를 바꾸면 길이로만 알린다. 샘플의 endpoint 가 다른데 샘플에 키가 없으면 저장하지 않는다(기존 키가 새 host 로 가지 않게). SDK 샘플의 `api_key=subscription_key` 같은 변수 이름은 키로 읽지 않는다.\
12
+ 키가 대화나 명령에 드러났다면 Azure 포털의 Regenerate, Model Studio 콘솔의 API Key 관리에서 교체한다.
13
+ - 화면, 오류, 로그에 키가 실리지 않는다. `redact` 는 길이만 보인다(0.16.0 은 앞뒤 4자를 보였고, `sk-ws-` 키는 앞이 상수라 뒤 4자가 드러났다). URL 이 아닌 endpoint 값(붙여 넣은 키일 수 있음)은 원문 대신 `null` 이다. WAN 다운로드 실패 오류의 서명 URL 은 `err.videoUrl` 로만 읽히고 JSON 과 `console.error` 에는 실리지 않는다.
14
+ - WAN 풀 상태 파일은 무작위 이름의 임시 파일을 배타적으로 만들어 써서, 미리 심어 둔 링크를 따라 다른 파일을 덮지 않는다. 폴더는 0700, 파일은 0600 이고, 쓰기나 이름 바꾸기에 실패하면 임시 파일을 지운다.
15
+
16
+ ### Fixed
17
+ - 서버의 `Retry-After` 를 1초에서 10분 사이로만 받는다. 0.16.0 은 `999999999` 면 키를 31년 쉬게 했고, `0` 이면 기다리지 않고 다시 시도했다. 쉬는 키의 기록은 `resetPoolState({ creds, labels })` 로 지운다.
18
+ - setup 프리플라이트가 status 0 의 이유(`EINSECURE`, `ERR_INVALID_URL` 등)를 보인다. FLUX 가 다른 리소스면 그 키를 `AZURE_IMAGE_SERVICES_API_KEY` 로 키 파일에 적는다.
19
+
20
+ ## [0.16.0] - 2026-10-11
21
+
22
+ ### Added
23
+ - **`3d-intro-build` 의 영상을 WAN 키 풀로 만들고, 풀이 소진되면 Sora-2 로 폴백한다.** 새 공유 모듈 `references/video-pool.mjs` 의 `generateClip` 이 모든 leg 의 진입점이다.\
24
+ WAN(Alibaba Cloud Model Studio, 기본 `wan3.0-video-prime`)은 `WAN_<n>_ENDPOINT`·`WAN_<n>_API_KEY` 를 개수 제한 없이 받아, 가장 오래전에 쓴 키부터 고른다. 할당량 소진(`AllocationQuota.*`·`Arrearage` 등)과 모델 권한 없음은 그 키를 24시간 쉬게 한다. 요청 속도 429 는 `Retry-After` 만큼 쉬게 할 뿐 퇴출하지 않고, `Throttling.AllocationQuota` 만 연속 3회면 1시간 쉬게 한다. `InvalidApiKey` 키는 제외한다. 상태는 `~/.config/banker/3d-intro/video-pool-state.json` 에 지문(엔드포인트, 키, 모델)으로만 남는다.\
25
+ 같은 leg 는 두 번 과금하지 않는다. 다른 키로 다시 내는 것은 첫 제출이 task 를 만들지 않은 게 확실할 때뿐이다(서버의 거절, 요청을 보내기 전 연결 실패, 키 할당량이나 알려진 일시 오류로 FAILED 나 CANCELED 된 task). 처음 보는 코드나 코드 없이 끝난 task 는 입력 탓이거나 과금됐을 수 있어 다시 내지 않고 `taskId` 를 담아 멈춘다. 폴링 시간 초과와 다운로드 실패도 `taskId` 를 담아 멈추고, 제출 중 연결이 끊기면 task 가 생겼는지 콘솔에서 확인하라며 멈춘다. 끝나지 않은 task 는 `resumeClip` 으로 새 제출 없이 마저 받는다. Sora job 이 사라졌으면(4xx) `resumeClip` 은 첫 폴링에서 멈추고, Sora 크레덴셜이 없거나 endpoint 가 URL 이 아니면 보내기 전에 멈춘다.\
26
+ 검열(`DataInspectionFailed`)과 `ModelNotFound` 같은 설정 오류는 다른 키나 Sora 로 넘기지 않는다. endpoint 나 모델이 형식에 맞지 않는 WAN 항목(URL 이 아닌 endpoint, 공백이 든 모델, 모델 칸에 붙인 키 등)은 건너뛰고, 모든 항목이 그렇다면 Sora 로 넘기지 않고 멈춘다. `poolSummary` 는 그 항목을 `malformed` 로 보고해, 유료 스틸을 만들기 전의 무료 점검에서 잡힌다. 형식이 잘못된 값과 네트워크 오류 문구는 출력과 오류 메시지에 싣지 않는다(키가 들어 있을 수 있음).\
27
+ 2026-10-09 실측: `wan3.0-video-prime` 480P 2초 클립 1개를 첫 프레임 data URI 로 만들어 97초에 받았고, 클립 첫 프레임과 입력 프레임의 SSIM 은 0.92 였다. WAN 은 첫+끝 프레임(`first_frame`·`last_frame`)도 받아 two-image 커넥터를 만들 수 있다(끝 프레임 경로는 UNVALIDATED).
28
+ - **`3d-intro-setup` 이 WAN 풀을 저장하고 무과금으로 검증한다.** 키마다 존재하지 않는 task 를 GET 해 200(유효)과 `401 InvalidApiKey`(무효)를 가른다. 남은 할당량은 조회 API 가 없어 확인하지 못한다. 형식이 잘못된 항목은 원래 값 대신 `BadEndpoint`, `BadModel` 로 보고한다.
29
+ - **`omc-patch` 스킬을 추가했다.** OMC 가 자동 업데이트되면 사라지는 로컬 훅 패치(훅 스크립트 최상위 `await import(...)` 의 10초 제한, `hooks.json` 의 `PostToolUse` 훅 제거)를 활성 버전에 다시 적용하고, OMC 마켓플레이스 `origin` 을 `omc-pinned://<원래 URL>` 로 바꿔 자동 업데이트를 막는다.\
30
+ 진단(`check`), 사용자 확인, `--no-update` 적용, 검증, 되돌리기(`revert`) 순서로 진행한다. 도구 `scripts/omc-patch.mjs` 는 정본에 두 가지 수정(헬퍼를 모듈 맨 앞에 둠, 마켓플레이스 폴더에 제 `.git` 이 있을 때만 고정)을 더한 사본이고, Node 18 이상과 `git` 이 필요하다. 첫 수정 전에는 최상위 `try { }` 블록이 둘 이상인 훅(OMC 5.6.x `project-memory-session.mjs`)에서 두 번째 import 가 조용히 실패했다. Codex 에서 실행해도 Claude Code 의 OMC 캐시만 다룬다.
31
+ - **`remains` 스킬을 추가했다.** 남은 버그, 하자, 미검증 항목을 찾아 표 하나로 보여 준다. 이번 대화에서 미검증이나 보류로 남긴 것, 인계 문서, 코드의 `TODO`, 건너뛴 시험, git 상태를 모으고 프로젝트의 시험을 돌린다. 읽기와 시험 실행만 하고 고치거나 커밋하거나 push 하지 않는다.\
32
+ 테스트박스를 `~/.config/banker/test-boxes.json` 에 등록하면(SSH 키 접속만, 비밀번호 칸은 거부) `scripts/boxes.mjs` 가 접속을 확인하고(`probe`) 같은 시험을 모든 박스에서 동시에 돌린다(`run`). 보내는 것은 추적 파일의 커밋된 내용뿐이고(줄 끝 변환 없음), `--ref worktree` 면 커밋하지 않은 변경도 보낸다. Linux, macOS 박스는 `mktemp -d` 로 만든 개인 폴더에서, Windows 박스는 명령을 `.cmd` 파일로 돌리고, root 로 접속하는 Linux 박스는 `runAs` 계정으로 돌린다. 박스에 둔 것은 끝나면 지우고, 시간 초과, 연결 끊김, 중단(SIGINT, SIGTERM) 때는 박스에서 시작한 프로세스를 먼저 끝낸다. 지우지 못하면 결과에 `cleaned: false` 로 알린다.
33
+ - **`trouble-shooting` 스킬을 추가했다.** 문제를 조사해 현상, 문제점, 원인, 해결방법, 조치계획을 세우고 표 하나로 간결히 보고한다(문제마다 한 행). `--no-plan` 이면 조치계획 없이 해결방법까지만 한다. 원인은 근거로 확인하고 확인하지 못한 원인은 추정과 확신 수준을 표시하며, 고치지 않고 보고만 한다.
34
+ - **`/progress` 명령을 추가했다(Claude Code 의 mod).** 진행 상황 패널을 켜고 끈다. `/progress` 와 `/progress show` 는 켜고 끄기를 번갈아 하고, `on` 과 `off` 는 그대로 켜거나 끈다. 패널이 다른 플러그인의 패널 뒤에 탭으로 가려져 있으면 `show` 와 `on` 은 닫지 않고 앞으로 올린다. 다른 인자에는 사용법을 보여 준다. 즉시 명령으로 등록해 작업 중에 입력해도 바로 실행된다(즉시 실행은 2.1.289 이상에서 확인). 명령이 오류나 시간 초과로 실패하면 이유를 한 줄로 답하고, 마크다운 대체 명령으로 넘어가지 않는다.\
35
+ 단계는 Claude 가 쓰는 작업 목록(TaskCreate, TaskUpdate 나 TodoWrite)이다. 이 모듈이 보기 전에 만든 작업(`--continue`, `--resume`)도 TaskList, TaskGet 결과와 TaskUpdate 로 채운다. 항목이 모두 완료된 목록은 다음 요청이 올 때까지 보이고, 그 뒤로는 다시 요청이 단계다. 하위 에이전트의 TodoWrite 는 그 에이전트의 목록이라 넣지 않는다. 작업 목록이 없으면 이 세션의 요청 하나하나가 단계이고, 실행 중인 요청이 진행 중인 단계다. 아직 요청이 없으면 "진행 중인 작업 없음" 단계 하나를 보인다.\
36
+ 단계를 누르면 목록 아래에 간결한 설명(요청이나 작업 내용, 상태, 걸린 시간, 도구 호출 수)이 나온다. 작업의 걸린 시간은 진행 중이 된 때부터 잰다. 화살표를 누르면 그 단계가 진행 중일 때 한 도구 호출(하위 에이전트와 백그라운드 에이전트 것 포함)이 한 단계 깊이로 펼쳐지거나 접히고, 최근 30개까지 보인다. 요청이 끝난 뒤에 백그라운드 에이전트가 한 호출은 마지막 단계 아래에 붙는다. 하위 항목을 눌러도 설명이 나온다. 단계는 50개까지 두고 넘치면 오래된 요청이나 끝난 작업부터 뺀다. 단계마다 도구 호출은 최근 200개를 두고, 호출 수는 전부 센다. 단계 이름과 설명의 제어 문자는 지운다(2.1.288 이하는 붙여넣은 이스케이프 문자가 아래 줄을 덮어 그린다).\
37
+ mod 가 없는 Claude Code(2.1.250 에서 확인)에서는 `/progress` 가 `commands/progress.md` 로 가고, UserPromptExpansion 훅(`hooks/progress-fallback.mjs`)이 모델을 부르지 않고 "mod 를 지원하지않는 claude code 버전입니다" 만 보인다. 2.1.286 과 2.1.296 에서 패널, 토글, 마우스 누름을 확인했다. Codex 에는 이 명령이 없다.
38
+ - **`3d-intro-build` 가 유료 단계마다 검토 페이지로 판정을 받는다.** `curate.mjs` 가 스틸과 클립 단계를 다루고, 산출물마다 카드 하나에 프롬프트 전문, 제외 프롬프트, 모델, 크기나 길이, 첫과 끝 프레임, 생성 시각, 비용, 경로, sha256 을 함께 보인다. sha256 은 파일을 나눠 읽어 큰 렌더도 재고, 서버를 띄울 때 미리 계산한다. 같은 장면의 테이크는 가로로 비교하고, 맨 위에 승인 수와 누적 비용, 승인 예산이 보인다.\
39
+ 판정은 페이지에서 저장하거나 대화로 받아(`--record`) 단계별 `decisions.json` 에 남긴다. 탈락한 테이크는 `--archive` 로 `rejected-YYYYMMDD/` 에 옮긴다. 모든 장면이 승인돼야 영상 단계로 간다.
40
+ - **`3d-intro-build` 의 결과 페이지에 인라인 script, style 이 없어 엄격한 CSP 에서 돈다.** 설정은 `intro.js`, 테마는 `theme.css`, 엔진 CSS 는 엔진 파일에서 글자 그대로 뽑은 `scrub-engine.css` 다. 엔진이 여전히 주입하는 `<style>` 하나의 CSP 해시(`styleHash`)를 조립이 알려 준다. 그 해시를 `style-src` 에 더하면 콘솔 오류가 없고, 더하지 않아도 같은 규칙이 적용된다. 실제 Chromium 에서 두 경우를 확인했다. 엔진과 템플릿 파일은 그대로다.
41
+ - **장면 단위 이동과 흐린 유리 패널(선택).** `stepNav` 를 켜면 휠 제스처 하나, 방향키, PageDown, Space, 30px 넘는 스와이프가 정확히 한 장면을 이동한다. 이동 중 입력은 최신 하나만 남겼다가 실행한다.\
42
+ 마지막 장면 다음은 본문 맨 위이고, 위 입력 한 번으로 돌아온다. 마지막 장면의 아래 입력 보호(`lastGuardMs`, 250ms)는 출처 프로젝트에서도 검증 중인 값이다. 메인화면 버튼은 마지막 클립이 끝까지 재생된 뒤 보이며, 움직임 줄이기 설정에서도 보인다. 건너뛰기 링크(애니메이션 없이 바로 이동, 포커스 이동), 마우스와 터치 안내, 클립 미리 받기(휴대폰과 Save-Data 에서는 처음 3개만)와 같은 주소 요청 합치기를 함께 한다. 본문 요소는 입력 때마다 찾으므로 스크립트 뒤에 그려지는 본문도 되고, 없으면 마지막 장면 뒤 스크롤을 가로채지 않는다. `panel: "glass"` 는 흐린 유리 패널이다. 기본값은 어두운 장면용이고, 본문 대비 4.5 는 독립 검증에서 잰다.
43
+ - **정지와 비행 모드(선택, 이 스킬에서 미검증).** 장면마다 스틸을 1초 영상으로 인코딩한 정지 클립(`stillToClip`, 무료)을 두고, 장면 사이를 WAN 의 첫, 끝 프레임 지정 비행 클립으로 잇는다(`order: ['wan']`, Sora 폴백 없음). `estimateCost` 의 `mode: 'holdFlight'` 는 비행 클립만 센다. WAN 첫, 끝 프레임 경로는 유료 스모크로 확인하지 않았다.
44
+ - **실제 브라우저 측정 `verify-intro.mjs`(독립 검증용).** 화면 크기마다 새 컨텍스트에서 장면별 패널 위치, 헤더, 안내와 장면 점 겹침, 가로 넘침, 콘솔 오류, 글자를 숨긴 줄 단위 최저 대비(CTA 버튼 글자 포함)와 상단 CTA 의 글자 대비를 잰다. 두 번째 장면부터는 클립이 있는데 그려지지 않으면 실패다. 기본 화면에 가로로 든 휴대폰(844x390)이 있다. 장면 단위 이동이면 휠과 관성, 키, 스와이프, 메인화면 버튼, 건너뛰기 링크도 잰다. 검증 목록은 `verify.md` 다. Node 용 playwright 패키지와 Chromium 이 필요하다(`npx playwright install chromium` 은 브라우저만 받는다).
45
+ - **`motion-graphic-make` 에 단계 관문.** 계획 승인, 스냅숏 검토 페이지(구성 지시문과 함께), 렌더 승인과 검토, 사이트 배치(선택), 독립 검증, 정리 순서다. 렌더링은 계속 hyperframes 가 한다. 검토 페이지와 서버는 `3d-intro-build` 와 같은 파일이다.
46
+
47
+ ### Fixed
48
+ - `/graceful-pause` 의 로그 줄이 플러그인 이름을 두 번 붙이지 않는다. 엔진이 플러그인 이름을 붙이는데 문구에도 `banker: ` 가 있어 `banker: banker: ...` 로 보였다.
49
+ - **`ralph-qa` 시험이 Windows, macOS 에서도 통과한다(시험만 바꿈).** 전에는 Windows 에서 40건, macOS 에서 2건이 실패했다. Windows 에서는 `verifier-probe` 시험의 가짜 세계가 파일과 폴더를 `\` 와 `/` 어느 쪽으로 찾아도 같게 본다(probe 는 실행 OS 의 규칙으로 경로를 붙인다). `gemini-seat` 시험은 임시 폴더의 실제 경로를 쓰고(macOS 의 `/var` 는 `/private/var` 링크), `.env` 시험 동안 계정 홈을 따로 만든 폴더로 두고(Windows 의 임시 폴더는 계정 홈 안) 두 홈(GEMINI_CLI_HOME, 계정 홈)의 `.env` 를 각각 확인한다. 긴 이름 시험의 가짜 경로는 임시 폴더가 있는 드라이브의 뿌리에서 시작한다.
50
+ - **스크럽 엔진의 화면 결함을 페이지 쪽에서 고친다(`intro-fixes.css`, 모든 인트로).** 엔진이 문구 블록에 매 프레임 인라인 transform 을 넣어 CSS 의 세로 가운데 맞춤이 사라졌다. `translate` 로 다시 가운데에 둔다. 860px 이하에서는 엔진의 장면 점이 문구 위에 겹쳤다. 오른쪽 여백을 둔다. 고정 헤더를 깨는 `overflow-x: hidden` 은 `clip` 으로 바꾼다.
51
+ - **검토 서버가 프로젝트 폴더의 모든 파일을 내주던 문제를 고쳤다(보안).** 전에는 setup 이 키를 저장하는 `.env.3d-intro.local` 도 내려받을 수 있었다. 이제 `curate-input.json` 에 적힌 테이크와 프레임 가운데 이미지와 영상만, 링크를 따라가도 프로젝트 안의 이미지나 영상일 때만 내준다(키 파일이 입력에 잘못 적혀도 내려가지 않는다). 오류 응답에는 절대 경로를 싣지 않는다. 두 서버 모두 Host 가 localhost 나 IP 주소가 아니면 거절해 DNS 재바인딩을 막고, 판정은 같은 출처의 JSON 요청만 받는다. 페이지를 연 뒤 대화로 기록된 판정은 그 페이지가 덮어쓰지 못한다(409).
52
+ - 엔진이 높이가 낮은 화면을 고려하지 않아 생기던 겹침을 고쳤다(`intro-fixes.css`). 가로로 든 휴대폰에서는 문구가 헤더 아래로 들어가고 마지막 장면은 화면 위로 넘쳤다. 이제 높이 500px 이하의 가로 화면에서는 문구를 두 단(라벨, 제목, 태그 쪽과 본문, 버튼 쪽)으로 나눠 헤더와 아래 안내 사이에 두고, 글자를 조금 줄이고 장면 번호는 숨긴다(장면 점이 같은 정보). 유리 패널이 없으면 그늘이 문구 위까지 올라온다. 860px 이하에서는 문구가 아래 안내와 메인화면 버튼 위에 선다(전에는 375x667, 360x640 휴대폰에서 겹쳤다).
53
+ - 어두운 테마에서 엔진의 주 버튼과 상단 CTA 글자가 보이지 않던 문제를 고쳤다. 엔진은 흰 글자를 테마 글자색 배경에 놓아, 글자색이 밝은 테마에서는 흰 글자가 밝은 배경에 놓였다. 이제 글자를 테마 배경색으로 칠한다. 유리 패널 위의 보조(ghost) 버튼은 패널 글자색으로 칠한다(밝은 테마에서 어두운 글자가 어두운 유리에 놓였다).
54
+ - 미리보기 서버가 잘못된 퍼센트 인코딩 URL 하나에 죽던 문제를 고쳤다(이제 400). 서빙 폴더 안에 `port.txt` 를 쓰지 않는다.
55
+ - 조립이 엔진 파일과 함께 scroll-world 의 MIT 고지(`scrub-engine.LICENSE.txt`)를 사이트 폴더에 둔다. CSP 해시는 줄바꿈을 LF 로 맞춰 계산해 Windows 의 CRLF 체크아웃에서도 엔진이 주입하는 스타일과 같다.
56
+ - `3d-intro-build` 의 `prompts.md` 가 다음 leg 의 시드를 톤 정합한 프레임이라고 적고 있었다. SKILL 과 실측대로 raw 마지막 프레임으로 고쳤다.
57
+
58
+ ### Changed
59
+ - **mod 모듈 `hooks/register.mjs` 가 기능들이 함께 쓰는 이벤트를 한 번씩만 건다.** 엔진은 matcher 없는 이벤트를 모듈 전체에서 한 번만 받는다. 그래서 `session.start`, `session.end`, `turn.start`, `turn.complete` 는 `register.mjs` 가 걸고 `/graceful-pause` 와 `/progress` 의 함수를 부르며, 두 명령의 등록도 `register.mjs` 가 한다. `/graceful-pause` 의 동작은 바뀌지 않았다.
60
+ - **`generateImage` 가 HTTP 429 에 `Retry-After` 만큼 기다렸다가 같은 경로로 다시 시도한다(기본 3회).** 전에는 429 에도 classic 경로로 넘어가 같은 한도에 다시 걸렸다. `azFetch` 결과에 `retryAfterMs` 를 더했다.
61
+ - **`parseEnvFile` 이 따옴표 없는 값에서 공백 뒤의 `#` 부터를 주석으로 지운다(`=` 바로 뒤도 같음).** 전에는 주석이 값에 붙어 endpoint, 키, 모델, `VIDEO_PROVIDER_ORDER` 가 깨졌다. 공백 없이 붙은 `#` 와 따옴표 안은 그대로 두고, `persistCreds` 는 그렇게 바뀔 값(공백 뒤 `#`, 앞뒤 공백이나 따옴표)을 따옴표로 감싸 써서 그대로 돌아오게 한다.
62
+ - **`pollVideo` 가 408, 429 를 뺀 4xx 에서 바로 멈춘다(오류에 `status`, `code`).** 전에는 사라진 job 도 `maxTicks` 까지 폴링했다. 폴링 사이에 주입한 `sleep` 을 쓰고, 오류 응답의 본문은 상태로 쓰지 않는다.
63
+ - `scripts/sync-adapter.js` 가 `azure-adapter.mjs` 와 `video-pool.mjs` 두 파일을 setup 스킬로 미러링하고 검사한다.
64
+ - **`serve.mjs`, `curate.mjs` 의 서버 규칙.** 포트는 시스템이 주는 빈 번호를 쓴다(전에는 고정 후보 8개). 상태 파일(PID, 포트, 폴더)은 `serve.mjs` 가 서빙 폴더 밖에, `curate.mjs` 가 프로젝트 폴더에 둔다(내주지 않음). `--stop` 은 바인드한 주소에서 그 포트가 기록된 PID 로 답할 때만 끄고 포트가 닫혔는지 확인한다. 기록된 서버가 같은 설정으로 살아 있으면 그 주소만 알리고, 설정(`--csp`, `PREVIEW_HOST`, 떠 있는 포트나 처음 요청한 포트와 다른 `--port`)이 다르면 exit 1 로 `--stop` 뒤 다시 띄우라고 알린다(CSP 없는 서버로 검증하는 일을 막음). `serve.mjs --csp` 는 운영과 같은 CSP 헤더를 붙인다. `PREVIEW_HOST=0.0.0.0` 은 경고를 낸다. 읽을 수 없는 파일은 403 으로 답하고 서버는 계속 돌며, 브라우저가 끊은 다운로드는 파일을 닫는다. 상태 파일의 PID 가 1보다 큰 정수가 아니면 끄지 않고(`invalid-state`), `--state` 를 공유한 다른 폴더의 서버는 같은 서버로 보지 않는다.
65
+ - `curate.mjs` 의 출력이 `selection.json` 에서 단계별 `decisions.json` 으로 바뀌었다. 입력의 `variants` 는 `takes` 로 읽는다.
66
+ - `scripts/sync-adapter.js` 가 `preview-lib.mjs`, `serve.mjs`, `curate.mjs` 를 `motion-graphic-make` 로도 미러링하고 검사한다.
67
+
3
68
  ## [0.15.2] - 2026-10-07
4
69
 
5
70
  ### Fixed
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  [빠른 시작](#빠른-시작) · [워크플로 예시](#워크플로-사용-예시) · [구성](#구성) · [설치 상세](#설치-상세-npm--codex) · [설정 변경 지점](#설정-변경-지점-claude-code--codex) · [요구사항](#요구사항) · [업데이트 / 제거](#업데이트--제거) · [업데이트 확인](#업데이트-확인-및-사용량-카운팅) · [라이선스 / 서드파티](#라이선스--서드파티)
10
10
 
11
- banker는 QA·보안 감사·문서·아키텍처·위키·미디어 작업과 의존성·개발환경(OS별) 설치를 아우르는 **스킬 57개 + 커맨드 2개**(총 59개 구성요소)와 Claude Code 즉시 명령 `/graceful-pause` 를 묶은 Claude Code 플러그인입니다.\
11
+ banker는 QA·보안 감사·문서·아키텍처·위키·미디어 작업과 의존성·개발환경(OS별) 설치를 아우르는 **스킬 60개 + 커맨드 2개**(총 62개 구성요소)와 Claude Code 즉시 명령 `/graceful-pause`, `/progress` 를 묶은 Claude Code 플러그인입니다.\
12
12
  설치하면 스킬과 커맨드가 `/banker:<이름>` 네임스페이스로 노출됩니다.\
13
13
  이 저장소 자체가 Claude Code 마켓플레이스(`.claude-plugin/marketplace.json`)이자 플러그인(`.claude-plugin/plugin.json`, name `banker`)이며, 도구에 무관한 스킬은 Codex CLI에도 설치됩니다.
14
14
 
@@ -59,7 +59,11 @@ Claude Code는 `/banker:<이름>`, Codex는 `banker-<이름>` 으로 호출합
59
59
  | `cleansing-memory` | 프로젝트가 장기화될 때 | 메모리 최적화 |
60
60
  | `ready-compact` | 컨텍스트를 compact 하거나 새 세션을 대비할 때 | 이어갈 프롬프트만 출력(`/copy` 한 번이면 복사), `--hand-off` = 새 세션에서 이어가기 |
61
61
  | `/graceful-pause` | 작업 도중 방향을 바꾸거나 끼어들고 싶을 때 | 작업 중에 입력해도 바로 전달. 실행 중인 도구 호출이 끝나면 그 단계까지만 마무리하고 멈춘 뒤 지시를 기다림 (Claude Code) |
62
+ | `/progress` | 지금 작업이 어디까지 왔는지 보고 싶을 때 | 진행 단계 목록 패널을 켜고 끔. 단계를 누르면 설명, 화살표를 누르면 그 단계가 진행 중일 때 한 도구 호출이 펼쳐짐 (Claude Code) |
62
63
  | `tone-compact` | 답변을 짧은 한글 개조식으로 받고 싶을 때 | 문체 규칙을 켜 두면 끌 때까지 모든 세션에 적용 |
64
+ | `omc-patch` | OMC 자동 업데이트 뒤 훅이 느려지거나 훅 프로세스가 쌓일 때 | 사라진 훅 패치를 다시 적용하고 OMC 자동 업데이트를 고정 |
65
+ | `remains` | 작업 뒤에 남은 버그, 하자, 미검증 항목을 한눈에 보고 싶을 때 | 남은 항목을 표로 정리하고, 등록한 테스트박스에서 시험까지 돌림 |
66
+ | `trouble-shooting` | 문제가 생겨 원인과 해결방법을 정리해야 할 때 | 현상, 문제점, 원인, 해결방법, 조치계획을 표로 간결히 보고(`--no-plan` 은 해결방법까지) |
63
67
 
64
68
  ## 구성
65
69
 
@@ -69,9 +73,10 @@ Claude Code는 `/banker:<이름>`, Codex는 `banker-<이름>` 으로 호출합
69
73
  |---|---|
70
74
  | `/banker:front-qa` | 스펙(note) 기반 프론트엔드 구현 + parity QA |
71
75
  | `/banker:setup` | 구성요소·의존성 설치 오케스트레이터 (multi-select) |
72
- | `/graceful-pause` | 작업 중에도 바로 실행되는 정지 요청. 지금 단계만 끝내고 멈춘 뒤 보고하고 지시를 기다림 (Claude Code 2.1.289 이상, function hooks. Codex 미지원) |
76
+ | `/graceful-pause` | 작업 중에도 바로 실행되는 정지 요청. 지금 단계만 끝내고 멈춘 뒤 보고하고 지시를 기다림 (Claude Code 2.1.289 이상, mod. Codex 미지원) |
77
+ | `/progress` | 진행 상황 패널을 켜고 끔(`show` 기본 토글, `on`, `off`). 단계는 Claude 의 작업 목록, 없으면 이 세션의 요청이고, 하위 목록은 그 단계가 진행 중일 때 한 도구 호출 한 단계까지. 작업 중에도 바로 실행됨(2.1.289 이상에서 확인) (mod. Codex 미지원) |
73
78
 
74
- `/graceful-pause` 는 `commands/` 가 아니라 function hooks(`hooks/register.mjs`)로 등록되는 명령이라 구성요소 수에 넣지 않습니다.
79
+ `/graceful-pause` 와 `/progress` 는 Claude Code 의 mod(Claude Mods, 얼리 액세스 이름 function hooks, `hooks/register.mjs`)로 등록되는 명령이라 구성요소 수에 넣지 않습니다. `commands/progress.md` 도 넣지 않습니다. 이 파일은 mod 가 없는 Claude Code 에서 `/progress` 를 받아 "mod 를 지원하지않는 claude code 버전입니다" 만 보여 주는 대체 명령이고, mod 가 있으면 mod 가 대신 처리합니다.
75
80
 
76
81
  ### 스킬: QA · 감사
77
82
 
@@ -127,13 +132,16 @@ Claude Code는 `/banker:<이름>`, Codex는 `banker-<이름>` 으로 호출합
127
132
  | `cleansing-memory` | 메모리 파일을 문서화된 threshold 내로 정리(중복 최신본화·무손실 압축) |
128
133
  | `payload-mon` | 상태표시줄 ctx 옆에 요청 payload 추정치(32MB 한도 대비, 8MB부터) 표시 켜기·끄기 |
129
134
  | `tone-compact` | 답변과 새 문서를 ASD-STE100 기반 한글 개조식(표·목록·원어 발음 표기·장식 기호 금지)으로 쓰는 문체 규칙 켜기·끄기(on 기본, 끌 때까지 유지) |
135
+ | `omc-patch` | OMC 자동 업데이트 뒤 사라진 훅 패치를 재적용하고 OMC 마켓플레이스 자동 업데이트를 고정(진단·확인·적용·검증·되돌리기) |
136
+ | `remains` | 남은 버그, 하자, 미검증 항목을 찾아 표로 보여 줌. 테스트박스(`~/.config/banker/test-boxes.json`)가 등록돼 있으면 각 OS 에서 시험을 돌려 확인(읽기와 시험만, 고치지 않음) |
137
+ | `trouble-shooting` | 문제를 조사해 현상, 문제점, 원인, 해결방법, 조치계획을 표 하나로 간결히 보고(문제마다 한 행, `--no-plan` 은 해결방법까지, 고치지 않고 보고만) |
130
138
 
131
139
  ### 스킬: 미디어 (모션 그래픽 · 3D 인트로)
132
140
 
133
141
  | 스킬 | 설명 |
134
142
  |---|---|
135
- | `motion-graphic-make` | 10초 내외 내레이션 없는 무료 모션 그래픽 제작 (hyperframes 위임) |
136
- | `3d-intro-build` | 스크롤-스크럽 3D 인트로 사이트 제작 (Azure gpt-image-2 스틸 + Sora-2 영상, 유료) |
143
+ | `motion-graphic-make` | 10초 내외 내레이션 없는 무료 모션 그래픽 제작 (hyperframes 위임). 계획 승인, 스냅숏과 렌더 검토 페이지, 독립 검증, 사이트 배치는 선택 |
144
+ | `3d-intro-build` | 스크롤-스크럽 3D 인트로 사이트 제작 (Azure gpt-image 스틸 + WAN 키 풀 영상, 소진 시 Sora-2 폴백, 유료). 단계별 검토 페이지, 엄격한 CSP 에서 도는 페이지, 실제 브라우저 독립 검증. 장면 단위 이동과 기존 사이트 통합은 선택 |
137
145
 
138
146
  ### 스킬: 개발환경 setup (OS별 · 런타임별)
139
147
 
@@ -164,7 +172,7 @@ USER_RESOURCES 가이드의 공통 요소를 OS별·런타임별(Claude Code/Cod
164
172
  | `docs-setup` | arch-diagram·pdf-vision-extract 의존성(pptx·pymupdf·plantuml) 설치 |
165
173
  | `vertical-pptx-setup` | vertical-pptx 의존성(pptxgenjs·python-pptx) + 시각 검증용 LibreOffice (OS·권한 적응형) |
166
174
  | `motion-graphic-setup` | hyperframes(무료 모션 그래픽 CLI) 전제조건 설치 (Node≥22 + ffmpeg) |
167
- | `3d-intro-setup` | 3D 인트로용 Azure 크레덴셜·의존성 설치 + 무과금 프리플라이트 (Node/ffmpeg) |
175
+ | `3d-intro-setup` | 3D 인트로용 Azure·WAN 크레덴셜·의존성 설치 + 무과금 프리플라이트 (Node/ffmpeg) |
168
176
  | `setup-bypass-permissions` | Claude Code 기본 권한 모드를 `bypassPermissions` 로 바꿔 모든 세션에서 도구 실행 확인을 끔. 사용자가 직접 입력해야 실행(모델은 호출 불가), 위험 경고와 확인 뒤 적용, `off` 로 원복. `/banker:setup` 에서는 기본 미선택 |
169
177
 
170
178
  ## 설치 상세 (npm · Codex)
@@ -183,11 +191,12 @@ banker uninstall # 제거
183
191
 
184
192
  - `--scope project` 로 프로젝트 로컬(`./.codex`)에 설치하고, `--dry-run` 으로 미리 볼 수 있습니다.
185
193
  - non-root 전용입니다(전역 sudo 설치 시 root 소유 파일을 방지). postinstall이 없으므로 `banker setup` 을 직접 실행합니다.
186
- - Codex에는 스킬 57개가 `~/.codex/skills/banker-<name>/` 에, 커맨드 2개가 `~/.codex/prompts/banker-<name>.md` 에 설치됩니다(`codex/manifest.json`). \
194
+ - Codex에는 스킬 60개가 `~/.codex/skills/banker-<name>/` 에, 커맨드 2개가 `~/.codex/prompts/banker-<name>.md` 에 설치됩니다(`codex/manifest.json`). \
187
195
  디렉터리명과 일치하도록 프론트매터 `name:` 이 `banker-<name>` 으로 재작성되어 Codex가 `banker-<name>` 으로 인식합니다.
188
196
  - OMC/Claude 에 결합됐던 오케스트레이터·설치·유틸 표면(all-in-one·ultra-init·front-qa·setup·setup-omc·setup-omc-hud·setup-stitch·omc-reference·compact-copy)은 본문이 **런타임 인식**이라 Codex에서도 동작합니다.
189
197
  - `payload-mon` 은 Codex에서 실행해도 같은 머신의 Claude Code HUD 래퍼만 켜고 끕니다. \
190
198
  32MB 요청 한도는 Claude Code 의 것이라 Codex 자신의 요청 크기는 재지 않습니다.
199
+ - `omc-patch` 도 Codex에서 실행하면 같은 머신의 Claude Code OMC 플러그인 캐시(`~/.claude/plugins/`)만 다룹니다. Codex 의 OMX 는 건드리지 않습니다.
191
200
  - Codex에선 OMC 대신 **oh-my-codex(OMX)** 의 동명 스킬(ralplan·ralph·ultraqa·hud 등)과 `codex mcp`·내장 `/copy` 를 사용합니다(Codex는 `omx setup` 전제).
192
201
  - OMC 5 는 `ultraqa` 를 삭제했습니다. 그래서 Claude Code 의 `all-in-one`·`ultra-init` QA 게이트는 `verify` 순환으로 돌고, Codex 는 OMX `ultraqa` 를 그대로 씁니다.
193
202
  - 설치기는 `~/.codex/AGENTS.md` 를 건드리지 않습니다(omx가 재생성하므로 `~/.codex/skills/` 자동 검색에 의존). \
@@ -230,6 +239,8 @@ banker uninstall # 제거
230
239
  | `smart-compact` | `statusLine.command` 래핑 + `UserPromptSubmit` 훅 추가 (백업·멱등) | `~/.codex/` 대응 |
231
240
  | `payload-mon` | `hud/omc-hud-custom.mjs` 에 표시 블록 1개 삽입(`.payload-mon.bak` 백업·멱등·`node --check` 검증) + 래퍼 옆 `hud/payload-mon/` 에 모듈 사본 (`off` 로 원복) | — (Codex에서 실행해도 Claude Code HUD 만 다룸) |
232
241
  | `tone-compact` | `rules/banker-tone-compact.md` 생성 (`off` 로 삭제) | `AGENTS.md`(내용이 있는 `AGENTS.override.md` 우선) 끝에 `USER:OMX:POLICY` 로 감싼 블록 1개(`.tone-compact.bak` 백업·멱등, `off` 로 원복) |
242
+ | `omc-patch` | 활성 OMC 버전의 `scripts/*.mjs` 와 `hooks/hooks.json` 수정(`.omcbak` 백업, `PostToolUse` 훅 제거) + OMC 마켓플레이스 `origin` 을 `omc-pinned://` 로 고정(기록 `~/.claude/omc-local-patches/PINNED`, `revert` 로 원복) | — (Codex에서 실행해도 Claude Code 의 OMC 캐시만 다룸) |
243
+ | `remains` | 설정 파일 미변경. `~/.config/banker/test-boxes.json` 은 읽기만 함(사용자가 만들거나, 사용자가 준 정보로 확인받고 만듦). 처음 접속하는 박스의 호스트 키가 `~/.ssh/known_hosts` 에 더해짐. 테스트박스에는 임시 폴더를 만들고 끝나면 지움(시간 초과나 중단 때는 시작한 프로세스를 먼저 끝냄, 못 지우면 결과에 표시) | 동일 |
233
244
  | `motion-graphic-setup` | 설정 파일 미패치 (Node/ffmpeg 확보 + `npx hyperframes` 설치만) | 동일 (`config.toml` 미변경) |
234
245
  | `3d-intro-setup` | `settings.json` 미패치 — 크레덴셜을 untracked env 파일에 기록(`.env.3d-intro.local` 또는 `~/.config/banker/3d-intro/env`) | 동일 (`config.toml` 미변경) |
235
246
  | `setup-bypass-permissions` | `permissions.defaultMode` = `bypassPermissions` (켜기 전 내용은 `settings.json.bypass-permissions.bak`, 되돌리기 기록은 `settings.json.bypass-permissions.json`, `off` 로 원복. 관리 정책, 설정 파일의 금지 키, root 계정이면 거부) | Codex 에서 실행해도 같은 머신의 Claude Code 설정을 바꿈 (Codex 승인 정책은 미변경) |
@@ -242,9 +253,12 @@ banker uninstall # 제거
242
253
  - 또는 Node.js ≥ 16.7 (npm 전역 설치 경로): `banker` CLI 제공.
243
254
  - 일부 스킬은 별도 의존성이 필요하며 `/banker:setup` 으로 설치합니다. 의존성이 없으면 각 스킬이 실행 전에 설치부터 안내합니다.
244
255
  - `all-in-one`, `ultra-init`, `/banker:front-qa`: oh-my-claudecode(OMC) 5 와 같은 버전대의 `omc` CLI(`ralph` 가 `omc ralph verify` 를 부르므로 4.x CLI 로는 멈춤). Codex에서는 OMX.
245
- - `audit-web-page`, `play-qa`, `ultra-ui-qa`: playwright.
256
+ - `audit-web-page`, `play-qa`, `ultra-ui-qa`: playwright. `3d-intro-build` 의 독립 검증(`verify-intro.mjs`)도 Node 용 playwright 패키지와 Chromium 을 씁니다(`npm i -g playwright && npx playwright install chromium`).
246
257
  - `payload-mon`: OMC 커스텀 HUD 래퍼(`setup-omc-hud` 로 설치).
247
- - `/graceful-pause`: Claude Code 2.1.289 이상(function hooks). 그보다 오래된 Claude Code 는 명령을 등록하지 않고 한 줄로 알리며, Codex 에는 이 명령이 없습니다.
258
+ - `omc-patch`: Node 18 이상과 `git`(OMC 마켓플레이스 고정과 확인에 사용).
259
+ - `remains`: 테스트박스를 쓰려면 이 머신에 `ssh`, `scp`, `git`, 박스에 `tar` 와 시험에 필요한 런타임(예: Node)이 있어야 하고, SSH 키로 암호 없이 접속돼야 합니다.
260
+ - `/graceful-pause`: Claude Code 2.1.289 이상(mod). 그보다 오래된 Claude Code 는 명령을 등록하지 않고 한 줄로 알리며, Codex 에는 이 명령이 없습니다.
261
+ - `/progress`: mod 를 지원하는 Claude Code(2.1.286 과 2.1.296 에서 확인). 작업 중 즉시 실행은 2.1.289 이상에서 확인했습니다. mod 가 없는 Claude Code(2.1.250 에서 확인)에서는 "mod 를 지원하지않는 claude code 버전입니다" 만 보이고 모델은 호출되지 않습니다. Codex 에는 이 명령이 없습니다.
248
262
  - `lineage`: Python 3.7+ (표준 라이브러리만 사용). RHEL8/Rocky8은 기본 `python3` 가 3.6이라 `setup-python` 등으로 3.11을 설치해 지정해야 합니다.
249
263
 
250
264
  ## 업데이트 / 제거
@@ -282,6 +296,12 @@ Codex는 재설치할 때마다 기존 `banker-*` 를 먼저 정리하므로 옛
282
296
  > 규칙 파일과 블록은 플러그인 밖(`~/.claude/rules/`, `~/.codex/AGENTS.md`)에 있어서, 플러그인을 지워도 남아 계속 적용됩니다.\
283
297
  > 이미 지웠다면 `~/.claude/rules/banker-tone-compact.md` 를 지우고, AGENTS.md 에서 `<!-- banker:tone-compact:start -->` 부터 `<!-- banker:tone-compact:end -->` 까지와 그 바깥의 `USER:OMX:POLICY` 표시 두 줄을 지우면 됩니다.
284
298
 
299
+ > `omc-patch` 를 적용했다면 제거 전에 `/banker:omc-patch revert`(Codex는 `banker-omc-patch` 에 `revert`)를 실행하세요.\
300
+ > 훅 패치와 마켓플레이스 고정은 플러그인 밖(`~/.claude/plugins/`)에 있어서, 플러그인을 지워도 남고 OMC 도 계속 자동 업데이트되지 않습니다.\
301
+ > 이미 지웠다면 `~/.claude/plugins/marketplaces/omc` 의 origin 에서 `omc-pinned://` 를 뗀 주소로 `git remote set-url origin <주소>` 를 실행하고, 활성 버전 폴더의 `scripts/*.mjs.omcbak` 과 `hooks/hooks.json.omcbak` 을 원래 이름으로 되돌린 뒤 `~/.claude/omc-local-patches/PINNED` 를 지우면 됩니다.
302
+
303
+ > `remains` 의 테스트박스 등록 파일(`~/.config/banker/test-boxes.json`)은 플러그인 밖에 있어 제거해도 남습니다. 필요 없으면 직접 지우세요.
304
+
285
305
  ## 업데이트 확인 및 사용량 카운팅
286
306
 
287
307
  banker는 기본값(default-on)으로 두 가지를 합니다.\
@@ -336,6 +356,7 @@ banker 자체는 **MIT** ([LICENSE](LICENSE)). Owner: [smallOpenSource](https://
336
356
  |---|---|---|---|
337
357
  | Python | python-pptx | MIT | `arch-diagram` · `vertical-pptx` |
338
358
  | Node | pptxgenjs | MIT | `vertical-pptx` |
359
+ | Node | Playwright | Apache-2.0 | `3d-intro-build`(독립 검증, `verify-intro.mjs`) |
339
360
  | Python | python-docx | MIT | `rfp-author` |
340
361
  | Python | Playwright | Apache-2.0 | `audit-web-page`·`play-qa`·`ultra-ui-qa` |
341
362
  | Python | detect-secrets | Apache-2.0 | `lineage`(시크릿 스캔) |
@@ -371,3 +392,4 @@ banker 자체는 **MIT** ([LICENSE](LICENSE)). Owner: [smallOpenSource](https://
371
392
  | 디자인(상표) | Nothing 디자인 언어 | 상표 | `nothing-design` |
372
393
  | QA 엔진(예시) | Godot·Phaser 등 | MIT | `play-qa` |
373
394
  | 서비스(독점·상표) | Microsoft Azure OpenAI (Sora-2·gpt-image-2·FLUX.2-pro) | 독점 | `3d-intro-setup`·`3d-intro-build` |
395
+ | 서비스(독점·상표) | Alibaba Cloud Model Studio (WAN 영상 모델) | 독점 | `3d-intro-setup`·`3d-intro-build` |
@@ -61,11 +61,14 @@
61
61
  { "name": "cleansing-memory", "type": "skill", "target": "both", "reason": "keeps agent memory files inside their documented thresholds by de-duping to latest, condensing losslessly, and converting append-style records into replace-style", "supportingFiles": [], "caveat": "only MEMORY.md has a documented hard gate (200 lines or 25KB, whichever comes first); CLAUDE.md has NO documented size limit, so asserting a byte cap for it would be fabrication. Codex's 32768-byte project_doc_max_bytes covers project-scope AGENTS.md only, not the global one, and truncates raw bytes before a lossy UTF-8 decode, so cutting to an exact byte count corrupts the boundary character. Codebase-derivable CLAUDE.md trimming is left to Claude's own /doctor." },
62
62
 
63
63
  { "name": "motion-graphic-setup", "type": "skill", "target": "both", "reason": "installs hyperframes prereqs (Node22+ffmpeg per-OS) then npx hyperframes init/skills update/doctor; ffmpeg never bundled; runtime-agnostic installer", "supportingFiles": [], "caveat": "needs Node+ffmpeg; hyperframes npx-installed (Apache-2.0)" },
64
- { "name": "motion-graphic-make", "type": "skill", "target": "both", "reason": "thin wrapper delegating to hyperframes /motion-graphics (free form categories); owns no render pipeline; runtime-agnostic", "supportingFiles": [], "caveat": "needs hyperframes via motion-graphic-setup (npx, Apache-2.0)" },
65
- { "name": "3d-intro-setup", "type": "skill", "target": "both", "reason": "collects Azure creds (direct or console-sample parse) to untracked env + FREE preflight; installs Node/ffmpeg; runtime-agnostic", "supportingFiles": ["references/azure-adapter.mjs"] },
66
- { "name": "3d-intro-build", "type": "skill", "target": "both", "reason": "scroll-scrub 3D intro via Azure Sora-2 forward-chaining + gpt-image-2 stills; vendored scroll-world engine (MIT); cross-platform Node", "supportingFiles": ["references/azure-adapter.mjs", "references/scrub-engine.js", "references/index-template.html", "references/prompts.md", "references/LICENSE", "references/NOTICE.md", "references/serve.mjs", "references/assemble.mjs", "references/curate.mjs"] },
64
+ { "name": "motion-graphic-make", "type": "skill", "target": "both", "reason": "thin wrapper delegating to hyperframes /motion-graphics (free form categories); owns no render pipeline, only the stage gates (plan approval, snapshot and render review, independent check) and the review page and preview server it shares with 3d-intro-build; runtime-agnostic", "supportingFiles": ["references/preview-lib.mjs", "references/serve.mjs", "references/curate.mjs"], "caveat": "needs hyperframes via motion-graphic-setup (npx, Apache-2.0); the three references are byte-identical copies of 3d-intro-build's (scripts/sync-adapter.js)" },
65
+ { "name": "3d-intro-setup", "type": "skill", "target": "both", "reason": "collects Azure creds (direct or console-sample parse) to untracked env + FREE preflight; installs Node/ffmpeg; runtime-agnostic", "supportingFiles": ["references/azure-adapter.mjs", "references/video-pool.mjs"] },
66
+ { "name": "3d-intro-build", "type": "skill", "target": "both", "reason": "scroll-scrub 3D intro: gpt-image stills, WAN key pool video with Sora-2 fallback (forward-chaining, or the optional hold-and-flight mode), a review page for every paid stage, a page with no inline script or style (strict CSP), optional scene-by-scene navigation and glass panel, and a Playwright measurement for the independent check; vendored scroll-world engine (MIT) left unmodified; cross-platform Node", "supportingFiles": ["references/azure-adapter.mjs", "references/video-pool.mjs", "references/scrub-engine.js", "references/index-template.html", "references/prompts.md", "references/LICENSE", "references/NOTICE.md", "references/preview-lib.mjs", "references/serve.mjs", "references/assemble.mjs", "references/curate.mjs", "references/intro-fixes.css", "references/panel-glass.css", "references/step-nav.js", "references/step-nav.css", "references/verify-intro.mjs", "references/verify.md"], "caveat": "the independent check (verify-intro.mjs) needs Node Playwright with Chromium (setup-playwright); the hold-and-flight mode needs WAN keys and is not yet confirmed by a paid smoke" },
67
67
  { "name": "payload-mon", "type": "skill", "target": "both", "reason": "toggles an estimated API request payload segment (bytes against Claude Code's 32MB request limit) in the OMC custom HUD statusline, beside ctx; pure Node, no deps", "supportingFiles": ["scripts/payload-mon.mjs", "scripts/payload-size.mjs"], "caveat": "measures Claude Code sessions only (the 32MB limit and the transcript format are Claude Code's); run from Codex it still manages the same machine's Claude Code HUD wrapper but never measures Codex's own requests. Needs the OMC custom HUD wrapper (setup-omc-hud); the wrapper imports a module copy kept beside it because plugin install paths are versioned and retired on update" },
68
68
  { "name": "tone-compact", "type": "skill", "target": "both", "reason": "turns compact Korean writing rules (ASD-STE100 based: lists and tables, transliterated terms, no decorative symbols) on or off across sessions; pure Node, no deps", "supportingFiles": ["scripts/tone-compact.mjs"], "caveat": "per runtime: Claude Code gets <config>/rules/banker-tone-compact.md; Codex gets one marked block at the end of $CODEX_HOME/AGENTS.override.md (when it has content of its own) or AGENTS.md, wrapped in USER:OMX:POLICY so omx setup --merge-agents and a plain omx setup with team mode on keep it (--force, a confirmed overwrite or a plain omx setup with team mode off replace the file; run on again). Turning it on in one runtime leaves the other as it is" },
69
+ { "name": "omc-patch", "type": "skill", "target": "both", "reason": "re-applies local OMC hook patches after an OMC auto-update and pins the OMC marketplace origin; pure Node, no deps", "supportingFiles": ["scripts/omc-patch.mjs"], "caveat": "acts on the Claude Code OMC plugin cache under ~/.claude even when run from Codex; TARGET_VERSION 5.3.0 is hard-coded in the tool and only a plain apply uses it; the skill always passes --no-update" },
70
+ { "name": "remains", "type": "skill", "target": "both", "reason": "finds remaining bugs, defects and unverified items and shows them in one table; runs the project's tests on registered SSH test boxes; pure Node, no deps", "supportingFiles": ["scripts/boxes.mjs"], "caveat": "box runs need ssh, scp and git on this machine and key-only SSH logins; boxes are registered in ~/.config/banker/test-boxes.json; read and test only, never fixes or pushes" },
71
+ { "name": "trouble-shooting", "type": "skill", "target": "both", "reason": "investigates a problem and reports symptom, problem, cause, fix and action plan in one table, one row per problem; --no-plan stops at the fix; report only, never fixes", "supportingFiles": [] },
69
72
 
70
73
  { "name": "front-qa", "type": "command", "target": "both", "reason": "ralplan->ralph frontend-QA pipeline; Claude=OMC, Codex=OMX", "supportingFiles": [] },
71
74
  { "name": "setup", "type": "command", "target": "both", "reason": "installer orchestrator; Claude AskUserQuestion multi-select, Codex prompt-based selection", "supportingFiles": [] }
@@ -43,6 +43,8 @@ The generator (`banker setup --codex`) applies the rules below for `target: both
43
43
  - `obsidizer` — OMC-managed trees respect the 9-field frontmatter whitelist + reserved files + no-rename + bare `[[slug]]` links only; `aliases` are written in generic vaults only; Canvas sidecars and body-inline `::` are durable in-place; no `wiki_*` write dependency, `wiki_lint` read-only for verification. `--enable` is Claude-only (plugin-declared PostToolUse hook); Codex has no MCP tool hooks → honest no-op.
44
44
  - `payload-mon` — needs the OMC custom HUD wrapper (`setup-omc-hud`). It measures Claude Code sessions only; from Codex it manages the same machine's Claude Code HUD wrapper and never measures Codex's own requests.
45
45
  - `tone-compact` — per runtime: Claude Code loads `<config>/rules/banker-tone-compact.md`; Codex reads one marked block at the end of `$CODEX_HOME/AGENTS.override.md` (when it has content of its own) or `AGENTS.md`, wrapped in `USER:OMX:POLICY` so `omx setup --merge-agents` keeps it (`--force` or team mode off replaces the file; run `on` again). Turning it on in one runtime leaves the other as it is.
46
+ - `omc-patch` — acts on the Claude Code OMC plugin cache (`~/.claude/plugins/`) even when run from Codex; Codex's own OMX is untouched. The skill always passes `--no-update` (a plain apply would switch the active OMC to the tool's hard-coded `TARGET_VERSION`).
47
+ - `remains` — the same procedure in both runtimes; box runs go through `scripts/boxes.mjs` (Codex: `~/.codex/skills/banker-remains/scripts/boxes.mjs`), which needs `ssh`, `scp` and `git` on the machine and key-only logins to the boxes in `~/.config/banker/test-boxes.json`. It reads and runs tests only: no fix, no commit, no push.
46
48
  - `/graceful-pause` (not a manifest surface) — a Claude Code function-hooks command (`hooks/register.mjs`, 2.1.289+) registered `immediate`, so it runs mid-turn; it appends one hidden user row the running turn reads at its next model request. Codex has no equivalent (no function hooks), and the earlier `graceful_pause` skill was removed because a typed skill waits until the turn ends.
47
49
 
48
50
  신규 스킬(0.7.0)도 `both`·런타임 인식:
@@ -0,0 +1,10 @@
1
+ ---
2
+ description: "진행 상황 패널을 켜고 끔. mod(Claude Mods)를 지원하는 Claude Code 에서 동작함. 'progress'/'진행 상황' 시 사용."
3
+ argument-hint: "[show | on | off]"
4
+ disable-model-invocation: true
5
+ ---
6
+
7
+ 이 명령은 Claude Code 의 mod(Claude Mods)가 처리한다. 이 문서가 열렸다면 이 세션에서 mod 가 돌지 않는다.
8
+ 다른 일은 하지 말고, 도구도 쓰지 말고, 아래 한 줄만 그대로 답한다.
9
+
10
+ mod 를 지원하지않는 claude code 버전입니다
package/commands/setup.md CHANGED
@@ -38,7 +38,7 @@ banker 플러그인이 제공하는 설치 스킬들을 **multi-select**로 골
38
38
  - **setup-playwright** — Playwright + 브라우저 + Xvfb(RHEL8/Rocky8 폴백). (`ultra-ui-qa`·`audit-web-page`·`play-qa` 의존성)
39
39
  - **docs-setup** — arch-diagram·pdf-vision-extract 의존성(python-pptx·pymupdf·plantuml). (의존: python)
40
40
  - **motion-graphic-setup** — hyperframes(무료 모션 그래픽 CLI) 전제조건(Node≥22 + ffmpeg → `npx hyperframes`). (`motion-graphic-make` 의존성)
41
- - **3d-intro-setup** — Azure Sora-2/gpt-image-2 3D 인트로용 크레덴셜·의존성(Node/ffmpeg) + 무과금 프리플라이트. (`3d-intro-build` 의존성)
41
+ - **3d-intro-setup** — 3D 인트로용 크레덴셜(Azure gpt-image·Sora-2, 선택 WAN 영상 키 풀)·의존성(Node/ffmpeg) + 무과금 프리플라이트. (`3d-intro-build` 의존성)
42
42
 
43
43
  **권한 (주의, 기본 미선택)**
44
44
  - **setup-bypass-permissions** — Claude Code 의 기본 권한 모드를 `bypassPermissions` 로 바꿔 모든 세션에서 도구 실행 확인을 끔.
@@ -32,7 +32,7 @@
32
32
  export const COMMAND = 'graceful-pause';
33
33
  export const MIN_ENGINE = [2, 1, 289];
34
34
 
35
- const SPEC = {
35
+ export const SPEC = {
36
36
  name: COMMAND,
37
37
  description: '지금 단계만 끝내고 멈춘 뒤 보고하고 지시를 기다림. 작업 중에 입력해도 바로 전달',
38
38
  argumentHint: '[멈춘 뒤 다룰 지시나 메모]',
@@ -79,25 +79,6 @@ export function atLeast(version, min = MIN_ENGINE) {
79
79
 
80
80
  const userRow = (text) => ({ message: { type: 'user', content: [{ type: 'text', text }] } });
81
81
 
82
- async function registerIfSupported($) {
83
- let version = null;
84
- try {
85
- const v = await $.session.version();
86
- version = v?.base || v?.version || null;
87
- } catch {
88
- /* an engine without the call is older than the command needs */
89
- }
90
- if (!atLeast(version)) {
91
- $.ui.log(`banker: /${COMMAND} 는 Claude Code ${MIN_ENGINE.join('.')} 이상에서만 켭니다 (이 엔진: ${version || '버전 미상'})`);
92
- return;
93
- }
94
- try {
95
- await $.command.register(SPEC);
96
- } catch (err) {
97
- $.ui.log(`banker: /${COMMAND} 를 등록하지 못했습니다 (${String(err?.message ?? err)})`);
98
- }
99
- }
100
-
101
82
  // Appends the note to the running turn; the answer the command shows. The note counts
102
83
  // as sent before the call returns: a model request starting meanwhile reads the stored
103
84
  // row, and a second /graceful-pause meanwhile must not append another.
@@ -127,7 +108,7 @@ function queueReport($, state, memo) {
127
108
  state.queued = true;
128
109
  const failed = (why) => {
129
110
  state.queued = false;
130
- $.ui.log(`banker: /${COMMAND} 정지 보고 요청을 보내지 못했습니다 (${why})`);
111
+ $.ui.log(`/${COMMAND} 정지 보고 요청을 보내지 못했습니다 (${why})`);
131
112
  };
132
113
  $.clock.after(1, () => {
133
114
  $.prompt.submit({ text: pauseNote(memo), asUser: true }).then(
@@ -138,52 +119,26 @@ function queueReport($, state, memo) {
138
119
  return { text: QUEUED };
139
120
  }
140
121
 
141
- // At the main turn's end: a note no later request read is voided unless background
142
- // work will wake the session (the turn it starts reads the note then).
143
- async function settlePending($, state) {
144
- const { pending } = state;
145
- state.pending = null;
146
- if (!pending || pending.read || state.background > 0) return;
147
- try {
148
- await $.session.append(userRow(VOID));
149
- } catch {
150
- /* nothing more to do: the log line below still tells the person */
151
- }
152
- $.ui.log('banker: /graceful-pause 요청이 작업 끝에 도착해 적용되지 않았습니다.');
153
- }
154
-
155
122
  // Nothing in flight: the state a fresh session, or one after /clear, starts from.
156
123
  const fresh = () => ({ main: null, step: -1, pending: null, background: 0, queued: false });
157
124
  const listed = (v) => (Array.isArray(v) ? v.length : 0);
158
125
  const backgroundCount = (e) => listed(e.background_tasks) + listed(e.session_crons);
159
126
 
127
+ // The main turn in flight and its latest model request; subagent loops raise no turn.start and
128
+ // end with an agentId. `queued`: a report prompt not started yet. One per loaded module.
129
+ const state = fresh();
130
+
131
+ // The command and the events only this feature hooks. register.mjs hooks the events every banker
132
+ // feature shares (the engine takes one hook per event from the module) and calls the functions
133
+ // below for them; it also registers this feature's command (SPEC) from 2.1.289 on.
160
134
  export function registerGracefulPause(on) {
161
- // The main turn in flight and its latest model request; subagent loops raise no
162
- // turn.start and end with an agentId. `queued`: a report prompt not started yet.
163
- const state = fresh();
164
- watchSession(on, state);
165
- watchTurns(on, state);
135
+ Object.assign(state, fresh());
166
136
 
167
137
  on('command.run', { command: COMMAND }, async ($, e) => {
168
138
  if (state.main) return deliver($, state, e.args);
169
139
  if (state.background > 0) return queueReport($, state, e.args);
170
140
  return { text: IDLE };
171
141
  });
172
- }
173
-
174
- // The command's registration, a fresh state after /clear, and the background count the
175
- // stop events report.
176
- function watchSession(on, state) {
177
- on('session.start', async ($, e, next) => {
178
- await registerIfSupported($);
179
- return next(e);
180
- });
181
-
182
- // `/clear` ends the conversation and raises no session.start for the next one.
183
- on('session.end', async ($, e, next) => {
184
- Object.assign(state, fresh());
185
- return next(e);
186
- });
187
142
 
188
143
  on('classic.Stop', async ($, e, next) => {
189
144
  state.background = backgroundCount(e);
@@ -194,17 +149,9 @@ function watchSession(on, state) {
194
149
  state.background = backgroundCount(e);
195
150
  return next(e);
196
151
  });
197
- }
198
-
199
- // The main turn in flight and the model requests it makes. turn.step wraps every
200
- // request's stream, subagents' too: in the engine's kit that cost 25 to 45 µs a chunk,
201
- // well under 1% of a request.
202
- function watchTurns(on, state) {
203
- on('turn.start', async ($, e, next) => {
204
- Object.assign(state, { main: e.turnId, step: -1, queued: false });
205
- return next(e);
206
- });
207
152
 
153
+ // turn.step wraps every model request's stream, subagents' too: in the engine's kit that
154
+ // cost 25 to 45 µs a chunk, well under 1% of a request.
208
155
  on('turn.step', async function* ($, e, next) {
209
156
  if (e.turnId === state.main) {
210
157
  state.step = e.index;
@@ -212,11 +159,24 @@ function watchTurns(on, state) {
212
159
  }
213
160
  return yield* next(e);
214
161
  });
162
+ }
215
163
 
216
- on('turn.complete', async ($, e, next) => {
217
- if (e.agentId || e.turnId !== state.main) return next(e);
218
- state.main = null;
219
- await settlePending($, state);
220
- return next(e);
221
- });
164
+ // session.end: `/clear` ends the conversation and raises no session.start for the next one.
165
+ export function pauseReset() {
166
+ Object.assign(state, fresh());
167
+ }
168
+
169
+ export function pauseTurnStarted(e) {
170
+ Object.assign(state, { main: e.turnId, step: -1, queued: false });
171
+ }
172
+
173
+ // The main turn's end. A request it never read (it came in after the last model request, and no
174
+ // background work will report) is voided: what to append and log, which register.mjs does; or null.
175
+ export function pauseTurnCompleted(e) {
176
+ if (e.agentId || e.turnId !== state.main) return null;
177
+ state.main = null;
178
+ const { pending } = state;
179
+ state.pending = null;
180
+ if (!pending || pending.read || state.background > 0) return null;
181
+ return { row: userRow(VOID), log: '/graceful-pause 요청이 작업 끝에 도착해 적용되지 않았습니다.' };
222
182
  }
package/hooks/hooks.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "description": "banker hooks: obsidizer wiki canonicalization (PostToolUse, inert until `obsidizer --enable`) + anonymous usage counting (PostToolUse Skill / UserPromptExpansion, count-default-on, opt-out BANKER_NO_TELEMETRY, no-op without endpoint) + update-check notification (SessionStart, opt-out BANKER_NO_UPDATE_CHECK). modules: function hooks (Claude Code 2.1.289+) serving /graceful-pause, which runs at once even mid-turn.",
2
+ "description": "banker hooks: obsidizer wiki canonicalization (PostToolUse, inert until `obsidizer --enable`) + anonymous usage counting (PostToolUse Skill / UserPromptExpansion, count-default-on, opt-out BANKER_NO_TELEMETRY, no-op without endpoint) + update-check notification (SessionStart, opt-out BANKER_NO_UPDATE_CHECK). modules: Claude Mods (function hooks) serving /graceful-pause (Claude Code 2.1.289+), which runs at once even mid-turn, and /progress, a pane of the session's progress; without mods, /progress expands commands/progress.md and a UserPromptExpansion hook answers it with one message.",
3
3
  "modules": ["./register.mjs"],
4
4
  "hooks": {
5
5
  "PostToolUse": [
@@ -25,6 +25,16 @@
25
25
  }
26
26
  ],
27
27
  "UserPromptExpansion": [
28
+ {
29
+ "matcher": "^banker:progress$",
30
+ "hooks": [
31
+ {
32
+ "type": "command",
33
+ "command": "node \"$CLAUDE_PLUGIN_ROOT\"/hooks/run.cjs \"$CLAUDE_PLUGIN_ROOT\"/hooks/progress-fallback.mjs",
34
+ "timeout": 5
35
+ }
36
+ ]
37
+ },
28
38
  {
29
39
  "matcher": "banker:.*",
30
40
  "hooks": [
@@ -0,0 +1,10 @@
1
+ /**
2
+ * /progress on a Claude Code without mods (Claude Mods, the function hooks of early access): an
3
+ * engine older than them, or one where they are turned off.
4
+ *
5
+ * There the mod in hooks/progress.mjs never loads, so `/progress` finds commands/progress.md
6
+ * instead and Claude Code expands it. This UserPromptExpansion hook stops that expansion before
7
+ * the model reads it and shows the one message. Where mods run, the mod answers the command
8
+ * itself and nothing expands, so this hook does not run.
9
+ */
10
+ process.stdout.write(JSON.stringify({ decision: 'block', reason: 'mod 를 지원하지않는 claude code 버전입니다' }));