@kaydash9999/banker-plugins 0.17.1 → 0.19.0

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 (38) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +72 -0
  4. package/README.md +26 -8
  5. package/codex/manifest.json +3 -1
  6. package/codex/transform-matrix.md +5 -2
  7. package/commands/front-qa.md +3 -3
  8. package/hooks/graceful-pause.mjs +4 -2
  9. package/hooks/obsidize-hook.mjs +38 -28
  10. package/hooks/progress-plan.mjs +14 -8
  11. package/hooks/progress.mjs +174 -47
  12. package/hooks/register.mjs +14 -7
  13. package/hooks/update-checkin.mjs +29 -27
  14. package/package.json +1 -1
  15. package/skills/3d-intro-build/SKILL.md +1 -1
  16. package/skills/3d-intro-build/references/assemble.mjs +3 -3
  17. package/skills/3d-intro-setup/SKILL.md +3 -3
  18. package/skills/anti-drm/SKILL.md +254 -0
  19. package/skills/anti-drm/scripts/anti-drm.mjs +643 -0
  20. package/skills/anti-drm/scripts/instruction-toggle.mjs +733 -0
  21. package/skills/lineage/SKILL.md +3 -3
  22. package/skills/lineage/lineage.py +43 -7
  23. package/skills/omc-patch/SKILL.md +18 -6
  24. package/skills/omc-patch/scripts/omc-patch.mjs +400 -87
  25. package/skills/omc-reference/SKILL.md +1 -1
  26. package/skills/ralph-qa/SKILL.md +19 -19
  27. package/skills/theme-selection/SKILL.md +165 -0
  28. package/skills/theme-selection/assets/LICENSE +21 -0
  29. package/skills/theme-selection/assets/NOTICE.md +30 -0
  30. package/skills/theme-selection/assets/palettes.json +81 -0
  31. package/skills/theme-selection/references/contrast.md +138 -0
  32. package/skills/theme-selection/references/integrate.md +161 -0
  33. package/skills/theme-selection/scripts/themes.mjs +1067 -0
  34. package/skills/tone-compact/SKILL.md +8 -4
  35. package/skills/tone-compact/scripts/instruction-toggle.mjs +733 -0
  36. package/skills/tone-compact/scripts/tone-compact.mjs +48 -397
  37. package/skills/ultra-chain/SKILL.md +7 -6
  38. package/skills/update-banker/SKILL.md +1 -1
@@ -0,0 +1,138 @@
1
+ # 대비 보정이 이 모양인 이유
2
+
3
+ 대상 독자: 보정 규칙을 바꾸려 하거나, 왜 변수가 13개인지 묻는 사람.
4
+ 값의 원천은 이 엔진의 파이썬 원본에 적힌 주석이다. 아래 실측값은 그 주석에서 옮겼다.
5
+
6
+ ## 한 줄 요약
7
+
8
+ - 목표는 "안 보이면 기능이 사라지는 것"만 3.0 으로 올리는 것이다.
9
+ - 배경과 `rule` 은 건드리지 않는다.
10
+ - 본문 색은 제자리에서 옮기지 않고 새 이름으로 나눈다.
11
+
12
+ ## 상수
13
+
14
+ | 상수 | 값 | 뜻 |
15
+ |---|---|---|
16
+ | `TARGET` | 3.0 | 링크, 강조, 버튼 경계의 목표 대비 |
17
+ | `LABEL_TARGET` | 4.5 | 버튼 글자의 목표 대비 |
18
+ | `CONTRAST_JOBS` | `accent` 를 `bg` 에서 3.0, `surface` 에서 나빠지지 않게 | 제자리 보정 |
19
+ | `SURFACE_JOBS` | `ink`, `dim`, `accent`, `warn` 을 `surface` 에서 3.0, `bg` 에서 나빠지지 않게 | 새 이름으로 분리 |
20
+ | `LABEL_JOBS` | `label-on-accent` 는 `accent-on-surface` 위, `label-on-page-accent` 는 `accent` 위 | 글자색 선택 |
21
+
22
+ ## 한 변수가 두 배경에 쓰이면 한쪽 기준으로 못 고친다
23
+
24
+ 받기 버튼은 `--bg` 위에 테두리와 글자만으로 서 있다. 눌리는 순간 `--accent` 가 배경이 되고 글자는 `--surface` 로 뒤집힌다.
25
+ 그래서 `--accent` 는 배경을 둘 만난다. 한쪽만 보고 고치면 다른 쪽이 깨진다(실측 23개 조합).
26
+
27
+ - 두 배경을 함께 보는 것이 보정의 전부다.
28
+ - 나머지는 명도를 훑는 반복문뿐이다.
29
+ - 같은 변수가 두 배경에 쓰이는데 두 배경이 요구하는 값이 다르면 답은 이름을 나누는 것이다.
30
+
31
+ ## 왜 `--ink` 는 제자리에서 안 옮기는가
32
+
33
+ `--ink` 는 테마 고르개의 글자색이면서 `body` 의 글자색이기도 하다.
34
+ 검은 `--surface` 위에서 안 보이는 것을 고치려고 `--ink` 값을 옮기면, 멀쩡하던 `--bg` 위 본문까지 흐려진다.
35
+
36
+ | 조합 | 위치 | 본문 대비 |
37
+ |---|---|---|
38
+ | `lamborghini/light` | 보정 전 | 12.79 |
39
+ | `lamborghini/light` | `--ink` 를 제자리 보정한 뒤 | 4.20 |
40
+
41
+ 2026-09-08 크로미움 실측이다. 승인된 범위는 "기능이 사라지는 것만"이었고 본문은 사라지지 않았다.
42
+
43
+ 그래서 원본 `--ink` 는 그대로 두고 `--ink-on-surface` 를 따로 굽는다. `--dim` 도 같다.
44
+
45
+ - `--surface` 가 배경인 규칙만 `-on-surface` 변수를 쓴다.
46
+ - `--bg` 위 규칙이 이것을 쓰면 방금 막은 번짐이 돌아온다.
47
+ - 148 조합 중 `ink` 와 `dim` 값이 실제로 갈라지는 것은 3 조합(값 넷)뿐이다. `lamborghini/light` 의 `ink` 와 `dim`, `lovable/dark` 의 `dim`, `meta/light` 의 `dim` 이다.
48
+ - 나머지 145 조합은 두 변수가 같은 값이라 화면이 한 픽셀도 안 바뀐다.
49
+
50
+ `accent` 와 `warn` 이 목록에 든 이유는 다음과 같다.
51
+
52
+ | 변수 | 들어온 이유 |
53
+ |---|---|
54
+ | `accent-on-surface` | 의견 상자의 고른 별(2026-10-01). 제자리 `--accent` 는 `--bg` 기준이라 `--surface` 위에서 23 조합이 3.0 아래였음 |
55
+ | `warn-on-surface` | 2026-10-15 전수 조사. 상자 안 위험 버튼, 경고 상자, 실패 문구가 원본 `--warn` 이었고 최저 1.46 이었음 |
56
+
57
+ ## 왜 목표가 3.0 인가
58
+
59
+ - 올리는 대상은 안 보이면 기능이 통째로 사라지는 셋이다.
60
+ - 흐린 보조 텍스트와 흐린 경계선은 읽기 나쁠 뿐이다. 어디를 눌러야 하는지는 말해 준다.
61
+ - 팔레트 74개를 전부 4.5 로 끌어올리면 색이 전부 평평해진다. 테마가 테마가 아니게 된다.
62
+
63
+ ## 왜 배경과 `rule` 은 건드리지 않는가
64
+
65
+ 배경을 옮기면 그 배경을 쓰는 모든 색의 대비가 같이 움직인다.
66
+ 고칠 대상은 언제나 배경 위에 얹히는 색이고, 배경은 기준으로만 쓴다.
67
+
68
+ ## `--rule` 의 대비는 보장되지 않는다
69
+
70
+ 보정에서 뺀 것은 의도다. 그래서 소비자가 알아야 하는 수치가 있다.
71
+
72
+ | 재는 자리 | 3.0 미만 | 1.5 미만 | 최저 |
73
+ |---|---|---|---|
74
+ | `--rule` 대 `--bg` | 122 / 148 | 35 | 1.00 (`lamborghini/light`) |
75
+ | `--rule` 대 `--surface` | 121 / 148 | 37 | 1.00 (`theverge/light`) |
76
+
77
+ - 대비 1.00 은 두 색이 같다는 뜻이다. 경계선이 화면에 없다.
78
+ - `check` 는 이 자리를 재지 않는다. 종료 코드 0 이 경계선이 보인다는 뜻은 아니다.
79
+ - 경계선만으로 정보를 전달하지 않는다. 누를 수 있는 것과 고른 것은 글자색이나 배경색으로도 표시한다.
80
+ - 포커스 테두리는 `--accent-on-surface` 나 `--accent` 를 쓴다. 그 둘은 보정을 거친다.
81
+
82
+ ## `keep_bg` 의 하한은 왜 `min(원래 대비, 3.0)` 인가
83
+
84
+ `keep_bg` 는 "여기서는 나빠지면 안 되는 배경"이다.
85
+
86
+ - 원래 대비가 2.7 이었으면 2.7 만 지키면 된다. 더 좋아지라고 요구하지 않는다.
87
+ - 양쪽 배경에 3.0 을 걸면 낮은 쪽을 올리려다 높은 쪽이 3.0 아래로 떨어진다. 답이 없는 조합이 생긴다.
88
+
89
+ ## 왜 명도를 전부 훑는가
90
+
91
+ 명도를 0.000 에서 1.000 까지 1001 단계로 전부 훑어 원래 명도에서 가장 가까운 후보를 고른다. 방향을 미리 정하지 않는다.
92
+
93
+ - 밝은 `bg` 와 검은 `surface` 사이에 낀 색은 위도 아래도 아닌 가운데로 가야 한다.
94
+ - "어두우면 밝힌다" 같은 규칙은 그 자리에서 틀린다.
95
+ - 색조와 채도는 유지하고 명도만 옮긴다(HLS). 라즈베리는 여전히 라즈베리이고 노랑은 여전히 노랑이다.
96
+ - 같은 입력에는 같은 출력이다.
97
+
98
+ 판정의 입력은 언제나 원본 팔레트다. 고친 값을 다음 계산에 먹이면 결과가 목록 순서에 딸려 간다.
99
+
100
+ ## 왜 버튼 글자가 `--label-on-accent` 인가
101
+
102
+ 버튼 배경은 `--accent-on-surface` 이고 상자 배경 위에서 3.0 을 만족한다. 그 위 글자는 본문 글자라 4.5 가 필요하다.
103
+
104
+ - 경계 3.0 과 글자 4.5 가 같은 쌍을 쓰면 버튼 배경을 4.5 까지 밀어야 한다.
105
+ - 그러면 같은 변수를 쓰는 고른 별까지 딸려 간다.
106
+ - 그래서 글자는 `--label-on-accent` 라는 새 이름으로 따로 고른다.
107
+
108
+ 글자 배경은 자리마다 하나씩이다(2026-10-15 전수 조사).
109
+
110
+ | 변수 | 올라가는 배경 | 자리 |
111
+ |---|---|---|
112
+ | `--label-on-accent` | `--accent-on-surface` | 상자 안 버튼 |
113
+ | `--label-on-page-accent` | `--accent` | 페이지 위 받기 버튼의 hover |
114
+
115
+ 같은 이름 하나로 두 배경을 맞추면 한쪽이 4.5 아래로 떨어진다.
116
+
117
+ 글자색 후보는 명도를 훑지 않는다. `surface`, `bg`, `ink`, `#ffffff`, `#000000` 순서로 4.5 를 넘는 첫 후보를 고른다.
118
+
119
+ ## 답이 없을 때
120
+
121
+ 답이 없으면 원래 값을 그대로 돌려준다. 조용히 포기하는 것이 아니다.
122
+ `check` 가 출력되는 값을 재므로 그 자리를 빨강(종료 코드 1)으로 보고한다.
123
+
124
+ 버튼 글자는 기본 목표 4.5 에서 답이 늘 있다. 어떤 색이든 흰색과 검정 중 하나와는 4.58 이상이기 때문이다.
125
+ `--label-target` 을 4.58 넘게 주면 답이 없는 조합이 생긴다. 그때는 후보 중 대비가 가장 높은 색을 내고, `check` 가 그 자리를 빨강으로 보고한다.
126
+
127
+ ## check 가 재는 것
128
+
129
+ | 자리 | 기준 |
130
+ |---|---|
131
+ | `accent` 대 `bg` | `TARGET` 이상 |
132
+ | `accent` 대 `surface` | `min(원래 대비, TARGET)` 이상 |
133
+ | `ink-on-surface`, `dim-on-surface`, `accent-on-surface`, `warn-on-surface` 대 `surface` | `TARGET` 이상 |
134
+ | 위 넷 대 `bg` | `min(원래 대비, TARGET)` 이상 |
135
+ | `label-on-accent` 대 `accent-on-surface` | `LABEL_TARGET` 이상 |
136
+ | `label-on-page-accent` 대 `accent` | `LABEL_TARGET` 이상 |
137
+
138
+ 본문 대비(`ink` 대 `bg`)는 보고만 하고 판정하지 않는다.
@@ -0,0 +1,161 @@
1
+ # 프로젝트에 테마 붙이기
2
+
3
+ 대상 독자: 자기 프로젝트에 `theme-selection` 출력을 넣는 사람.
4
+ `<스킬>` 은 스킬 디렉터리 절대경로다. 명령과 옵션은 `SKILL.md` 의 표를 따른다.
5
+
6
+ ## 공통 순서
7
+ 1. `css` 로 CSS 파일을 낸다.
8
+ 2. 프로젝트가 그 파일을 읽는다.
9
+ 3. `<html>` 에 `data-theme` 과 `data-mode` 속성이 걸린다. 걸지 않아도 `:root` 가 기본 테마의 라이트와 다크를 들고 있어 화면이 읽힌다. 다크는 `--dark-via` 로 고른 자리(속성, 클래스, OS 설정)를 따른다.
10
+ 4. 색을 쓰는 자리는 하드코딩 대신 `var(--ink)` 처럼 변수를 쓴다.
11
+
12
+ ```
13
+ node <스킬>/scripts/themes.mjs css --only superhuman,airbnb,stripe --out public/themes.css
14
+ ```
15
+
16
+ ## 순수 CSS
17
+
18
+ `<link>` 하나와 `var(--ink)` 면 된다.
19
+
20
+ ```html
21
+ <link rel="stylesheet" href="/themes.css">
22
+ ```
23
+
24
+ ```css
25
+ body { background: var(--bg); color: var(--ink); }
26
+ .card { background: var(--surface); color: var(--ink-on-surface); border: 1px solid var(--rule); }
27
+ .card .muted { color: var(--dim-on-surface); }
28
+ a { color: var(--accent); }
29
+ .card a { color: var(--accent-on-surface); }
30
+ .card .danger { color: var(--warn-on-surface); box-shadow: 0 1px 4px var(--shadow); }
31
+ .btn-primary { background: var(--accent-on-surface); color: var(--label-on-accent); }
32
+ .get:hover { background: var(--accent); color: var(--label-on-page-accent); }
33
+ ```
34
+
35
+ 배경이 `--surface` 인 규칙만 `-on-surface` 변수를 쓴다. `--bg` 위 규칙은 `--ink`, `--dim`, `--accent`, `--warn` 이다.
36
+
37
+ ## Tailwind
38
+
39
+ CSS 변수를 `theme.extend.colors` 에 매핑한다. 변수는 `#rrggbb` 값이라 그대로 `var()` 로 연결한다.
40
+
41
+ ```js
42
+ // tailwind.config.js
43
+ module.exports = {
44
+ theme: {
45
+ extend: {
46
+ colors: {
47
+ bg: "var(--bg)",
48
+ surface: "var(--surface)",
49
+ ink: "var(--ink)",
50
+ dim: "var(--dim)",
51
+ rule: "var(--rule)",
52
+ accent: "var(--accent)",
53
+ warn: "var(--warn)",
54
+ "ink-on-surface": "var(--ink-on-surface)",
55
+ "dim-on-surface": "var(--dim-on-surface)",
56
+ "accent-on-surface": "var(--accent-on-surface)",
57
+ "warn-on-surface": "var(--warn-on-surface)",
58
+ "label-on-accent": "var(--label-on-accent)",
59
+ "label-on-page-accent": "var(--label-on-page-accent)",
60
+ },
61
+ },
62
+ },
63
+ };
64
+ ```
65
+
66
+ 이 방식은 `bg-surface text-ink-on-surface` 처럼 쓴다. Tailwind 의 `dark:` 변형을 쓰려면 `--dark-via class` 로 CSS 를 내고 `darkMode: "class"` 를 맞춘다.
67
+ 고르개를 붙이면 `widget` 에도 `--dark-via class` 를 준다. 모드 버튼이 `data-mode` 와 `.dark` 를 함께 바꾸므로 이 설정과 맞는다.
68
+ `--prefix` 를 줬다면 `var(--<prefix>bg)` 처럼 이름을 맞춘다.
69
+
70
+ ## React 와 Vue
71
+
72
+ 속성은 `document.documentElement` 에 건다. 컴포넌트 안의 `div` 에 걸면 선택자 `html[data-theme=...]` 가 맞지 않는다.
73
+
74
+ ```jsx
75
+ // React
76
+ import { useEffect, useState } from "react";
77
+ export function useTheme(allowed, fallback) {
78
+ const [theme, setTheme] = useState(() => {
79
+ let saved = null;
80
+ // 서버 렌더에는 localStorage 가 없고, 저장소를 막은 브라우저는 예외를 던진다.
81
+ try { saved = localStorage.getItem("theme"); } catch { saved = null; }
82
+ return allowed.includes(saved) ? saved : fallback;
83
+ });
84
+ useEffect(() => {
85
+ document.documentElement.setAttribute("data-theme", theme);
86
+ try { localStorage.setItem("theme", theme); } catch { /* 막힌 저장소 */ }
87
+ }, [theme]);
88
+ return [theme, setTheme];
89
+ }
90
+ ```
91
+
92
+ Vue 3 도 같다. `ref` 에 이름을 담고 `watchEffect` 안에서 `document.documentElement.setAttribute("data-theme", theme.value)` 를 부른다.
93
+
94
+ 모드(`data-mode="dark"`)도 같은 자리에 같은 방식으로 건다. `--dark-via class` 로 냈으면 `classList.toggle("dark", 다크인지)` 로 `.dark` 를 건다. 저장된 값은 허용 목록에 대어 본 뒤에 쓴다.
95
+
96
+ 첫 그림 전의 깜빡임은 아래 head 스크립트를 `index.html` 의 `<head>` 에 두어야 막는다.
97
+
98
+ ## SCSS 와 styled-components
99
+
100
+ - SCSS: `color: var(--ink);` 처럼 변수를 그대로 쓴다. SCSS 변수에 값을 복사하지 않는다.
101
+ - styled-components: 템플릿 안에 `color: var(--ink);` 를 그대로 쓴다. `ThemeProvider` 로 값을 다시 들고 있지 않는다.
102
+
103
+ ## 고르개 붙이기
104
+
105
+ `widget` 이 세 덩이를 주석으로 가른 하나의 출력으로 낸다.
106
+
107
+ ```
108
+ node <스킬>/scripts/themes.mjs widget --only superhuman,airbnb,stripe --out widget.html
109
+ ```
110
+
111
+ CSS 를 낼 때와 같은 `--dark-via` 를 준다. 모드 버튼은 `data-mode` 와 `.dark` 를 함께 바꾸고, `--dark-via media` 면 버튼이 없다(다크는 OS 설정을 따름).
112
+
113
+ | 덩이 | 두는 곳 | 하는 일 |
114
+ |---|---|---|
115
+ | 고르개 마크업 | 페이지의 헤더 등 보이는 자리 | `<select>` 와 모드 버튼 |
116
+ | head 스크립트 | `<head>` | 저장된 이름을 `document.documentElement` 에 바로 건다 |
117
+ | 배선 스크립트 | 마크업 뒤나 `<body>` 끝 | 고르개 요소를 찾아 묶는다 |
118
+
119
+ 🔴 head 스크립트는 `<head>` 에, 배선 스크립트는 `ready` 래퍼와 함께 둔다. 둘을 합치지 않는다.
120
+
121
+ - head 스크립트는 DOM 을 보지 않는다. 그래서 `<head>` 에서 즉시 돌아도 된다. 즉시 도는 것이 첫 그림의 깜빡임을 막는다.
122
+ - 배선 스크립트는 마크업을 본다. 마크업이 아직 없을 때 돌면 `getElementById` 가 빈손이고 고르개가 영원히 안 움직인다.
123
+ - 배선 스크립트는 `readyState` 를 보고 즉시 또는 `DOMContentLoaded` 에서 부르는 래퍼로 감싸져 있다. 이 래퍼를 떼지 않는다.
124
+
125
+ 저장된 이름은 닫힌 집합(박혀 있는 테마 목록)에 대어 본다. 목록 밖이면 기본 테마로 되돌린다.
126
+
127
+ CSP(Content-Security-Policy)를 쓰는 사이트는 인라인 스크립트 둘에 nonce 나 해시를 붙인다. `'unsafe-inline'` 으로 풀지 않는다.
128
+
129
+ ## 모드만 쓰는 화면
130
+
131
+ 테마를 고르는 사람이 없고 라이트와 다크만 OS 설정을 따르면 되면 고르개가 필요 없다.
132
+
133
+ ```
134
+ node <스킬>/scripts/themes.mjs css --only superhuman --dark-via media --out public/themes.css
135
+ ```
136
+
137
+ `@media (prefers-color-scheme: dark)` 안에 다크 값이 들어간다. `:root` 도 기본 테마의 다크를 그 안에 들고 있어, `<html>` 에 속성을 걸지 않아도 OS 가 다크면 다크가 된다. JS 가 없어도 된다.
138
+
139
+ ## 서버 렌더
140
+
141
+ 저장된 이름을 쿠키로 받아 `<html>` 속성에 미리 박는 쪽이 깜빡임이 없다.
142
+
143
+ ```js
144
+ // 예: Express
145
+ const THEMES = new Set(["superhuman", "airbnb", "stripe"]);
146
+ app.get("/", (req, res) => {
147
+ const t = THEMES.has(req.cookies.theme) ? req.cookies.theme : "superhuman";
148
+ const m = req.cookies.mode === "dark" ? "dark" : "light";
149
+ res.send(`<!doctype html><html data-theme="${t}" data-mode="${m}">...`);
150
+ });
151
+ ```
152
+
153
+ - 쿠키 값은 허용 목록에 대어 본 값만 속성에 넣는다. 그대로 넣으면 속성 주입이 된다.
154
+
155
+ ## CSS 크기
156
+
157
+ - 테마당 규칙이 둘이다. 라이트 하나, 다크 하나.
158
+ - 규칙마다 13 선언이다.
159
+ - 74종 전부면 148 규칙이다.
160
+ - 여기에 `:root` 의 기본 테마 라이트와 다크 둘, `--shadow` 둘이 더해진다.
161
+ - 쓸 테마만 `--only` 로 줄이는 쪽을 권한다.