@kaydash9999/banker-plugins 0.18.0 → 0.19.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +103 -0
- package/README.md +18 -7
- package/bin/lib/telemetry-config.mjs +25 -0
- package/codex/manifest.json +1 -0
- package/codex/transform-matrix.md +1 -0
- package/hooks/graceful-pause.mjs +4 -2
- package/hooks/obsidize-hook.mjs +61 -32
- package/hooks/progress-plan.mjs +14 -8
- package/hooks/progress.mjs +187 -48
- package/hooks/register.mjs +15 -7
- package/hooks/telemetry-count-skill.mjs +4 -6
- package/hooks/telemetry-count.mjs +4 -6
- package/hooks/update-checkin.mjs +46 -43
- package/hooks/update-fetch.mjs +8 -7
- package/package.json +1 -1
- package/skills/anti-drm/SKILL.md +46 -15
- package/skills/anti-drm/scripts/anti-drm.mjs +213 -61
- package/skills/anti-drm/scripts/instruction-toggle.mjs +280 -44
- package/skills/lineage/SKILL.md +4 -1
- package/skills/lineage/lineage.py +196 -73
- package/skills/omc-patch/SKILL.md +37 -11
- package/skills/omc-patch/scripts/omc-patch.mjs +635 -103
- package/skills/theme-selection/SKILL.md +165 -0
- package/skills/theme-selection/assets/LICENSE +21 -0
- package/skills/theme-selection/assets/NOTICE.md +30 -0
- package/skills/theme-selection/assets/palettes.json +81 -0
- package/skills/theme-selection/references/contrast.md +138 -0
- package/skills/theme-selection/references/integrate.md +161 -0
- package/skills/theme-selection/scripts/themes.mjs +1067 -0
- package/skills/tone-compact/SKILL.md +14 -5
- package/skills/tone-compact/scripts/instruction-toggle.mjs +280 -44
- package/skills/tone-compact/scripts/tone-compact.mjs +4 -4
- package/skills/update-banker/SKILL.md +1 -1
package/hooks/update-checkin.mjs
CHANGED
|
@@ -27,27 +27,32 @@ import {
|
|
|
27
27
|
installedVersion,
|
|
28
28
|
writeUpdateCache,
|
|
29
29
|
changedSkillsBetween,
|
|
30
|
+
SKILL_NAME_RE,
|
|
31
|
+
collectBody,
|
|
32
|
+
netDeadlineMs,
|
|
30
33
|
} from '../bin/lib/telemetry-config.mjs';
|
|
31
34
|
|
|
32
35
|
const NET_TIMEOUT_MS = 10_000;
|
|
36
|
+
const NET_DEADLINE_MS = netDeadlineMs(); // 교환 전체 마감(위 값은 무활동 기준).
|
|
37
|
+
const MAX_BODY_BYTES = 256 * 1024; // 체크인 응답, 매니페스트 모두 수 KB 다.
|
|
33
38
|
|
|
34
39
|
// usage-log 각 줄 `<name>\t<hour 0-23>` 를 스킬별 x 시간대별 count 로 집계한다.
|
|
35
40
|
// 빈 줄·TAB 없는 줄·이름 없는 줄·hour 가 0-23 정수가 아닌 줄은 무시한다.
|
|
36
41
|
// 반환 예: { 'banker:compact-copy': { '9': 3, '14': 1 }, 'banker:setup': { '9': 1 } }.
|
|
37
42
|
function aggregate(raw) {
|
|
38
|
-
const counts =
|
|
43
|
+
const counts = Object.create(null);
|
|
39
44
|
for (const line of raw.split('\n')) {
|
|
40
45
|
if (!line.trim()) continue; // 빈 줄 무시.
|
|
41
46
|
const tab = line.indexOf('\t');
|
|
42
47
|
if (tab < 0) continue; // TAB 없는 malformed 줄 무시.
|
|
43
48
|
const name = line.slice(0, tab).trim();
|
|
44
49
|
const hourStr = line.slice(tab + 1).trim();
|
|
45
|
-
if (!name) continue;
|
|
50
|
+
if (!SKILL_NAME_RE.test(name)) continue; // banker:<slug> 꼴이 아닌 줄 무시(쓰는 훅과 같은 규칙).
|
|
46
51
|
if (!/^\d+$/.test(hourStr)) continue; // 정수 아닌 hour 무시(음수·소수·비수치 배제).
|
|
47
52
|
const hour = Number(hourStr);
|
|
48
53
|
if (hour > 23) continue; // 0-23 범위 밖 무시(하한은 \d+ 가 보장).
|
|
49
54
|
const key = String(hour); // '09' -> '9' 정규화.
|
|
50
|
-
if (!counts[name]) counts[name] =
|
|
55
|
+
if (!counts[name]) counts[name] = Object.create(null);
|
|
51
56
|
counts[name][key] = (counts[name][key] || 0) + 1;
|
|
52
57
|
}
|
|
53
58
|
return counts;
|
|
@@ -65,7 +70,8 @@ function isLoopback(hostname) {
|
|
|
65
70
|
function post(url, body) {
|
|
66
71
|
return new Promise((resolvePromise) => {
|
|
67
72
|
let done = false;
|
|
68
|
-
|
|
73
|
+
let deadline = null;
|
|
74
|
+
const finish = (responseBody = null) => { if (!done) { done = true; clearTimeout(deadline); resolvePromise(responseBody); } };
|
|
69
75
|
let parsed;
|
|
70
76
|
try {
|
|
71
77
|
parsed = new URL(url);
|
|
@@ -85,14 +91,10 @@ function post(url, body) {
|
|
|
85
91
|
const req = transport.request(parsed, {
|
|
86
92
|
method: 'POST',
|
|
87
93
|
headers: { 'content-type': 'application/json', 'content-length': Buffer.byteLength(body) },
|
|
88
|
-
}, (res) =>
|
|
89
|
-
let data = '';
|
|
90
|
-
res.on('data', (c) => { data += c; });
|
|
91
|
-
res.on('end', () => finish(data));
|
|
92
|
-
res.on('error', () => finish());
|
|
93
|
-
});
|
|
94
|
+
}, (res) => collectBody(res, MAX_BODY_BYTES, finish));
|
|
94
95
|
req.on('error', () => finish()); // 연결 거부/리셋 등은 즉시 여기로.
|
|
95
96
|
req.setTimeout(NET_TIMEOUT_MS, () => req.destroy());
|
|
97
|
+
deadline = setTimeout(() => { req.destroy(); finish(); }, NET_DEADLINE_MS);
|
|
96
98
|
req.write(body);
|
|
97
99
|
req.end();
|
|
98
100
|
} catch {
|
|
@@ -120,7 +122,8 @@ function extractLatest(responseBody) {
|
|
|
120
122
|
function fetchSkillChangesMap(url) {
|
|
121
123
|
return new Promise((resolvePromise) => {
|
|
122
124
|
let done = false;
|
|
123
|
-
|
|
125
|
+
let deadline = null;
|
|
126
|
+
const finish = (result) => { if (!done) { done = true; clearTimeout(deadline); resolvePromise(result); } };
|
|
124
127
|
let parsed;
|
|
125
128
|
try {
|
|
126
129
|
parsed = new URL(url);
|
|
@@ -137,20 +140,18 @@ function fetchSkillChangesMap(url) {
|
|
|
137
140
|
const req = transport.request(parsed, { method: 'GET' }, (res) => {
|
|
138
141
|
const status = res.statusCode || 0;
|
|
139
142
|
if (status >= 300 && status < 400) { res.resume(); return finish(null); } // 리다이렉트 미추적.
|
|
140
|
-
|
|
141
|
-
res.on('data', (c) => { data += c; });
|
|
142
|
-
res.on('end', () => {
|
|
143
|
+
collectBody(res, MAX_BODY_BYTES, (data) => {
|
|
143
144
|
try {
|
|
144
|
-
const obj = JSON.parse(data);
|
|
145
|
+
const obj = JSON.parse(data); // data null(한도 초과, 스트림 오류)은 null 로 읽혀 아래서 걸러진다.
|
|
145
146
|
finish((obj && typeof obj === 'object' && !Array.isArray(obj)) ? obj : null);
|
|
146
147
|
} catch {
|
|
147
148
|
finish(null);
|
|
148
149
|
}
|
|
149
150
|
});
|
|
150
|
-
res.on('error', () => finish(null));
|
|
151
151
|
});
|
|
152
152
|
req.on('error', () => finish(null));
|
|
153
153
|
req.setTimeout(NET_TIMEOUT_MS, () => req.destroy());
|
|
154
|
+
deadline = setTimeout(() => { req.destroy(); finish(null); }, NET_DEADLINE_MS);
|
|
154
155
|
req.end(); // GET - 요청 본문 없음.
|
|
155
156
|
} catch {
|
|
156
157
|
finish(null);
|
|
@@ -158,42 +159,44 @@ function fetchSkillChangesMap(url) {
|
|
|
158
159
|
});
|
|
159
160
|
}
|
|
160
161
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if (!url) return; // 엔드포인트 없음 - 무동작(로그 미변경).
|
|
165
|
-
|
|
166
|
-
// 로그 없음도 유효한 체크인(설치 펄스 + 알림 fetch 겸함): 빈 counts 로 진행한다.
|
|
162
|
+
// 보낼 본문. PII/IP/지속ID 없음: version + os(플랫폼 계열) + counts(스킬별 x 시간대)뿐.
|
|
163
|
+
// 로그 없음도 유효한 체크인(설치 펄스 + 알림 fetch 겸함): 빈 counts 로 진행한다.
|
|
164
|
+
function checkinBody() {
|
|
167
165
|
let raw = '';
|
|
168
166
|
try { raw = readFileSync(USAGE_LOG_PATH, 'utf8'); } catch { raw = ''; }
|
|
167
|
+
return JSON.stringify({ version: installedVersion() || 'unknown', os: process.platform, counts: aggregate(raw) });
|
|
168
|
+
}
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
});
|
|
176
|
-
const responseBody = await post(url, payload);
|
|
177
|
-
|
|
178
|
-
// 응답의 latest 로 공유 update-check 캐시를 갱신(알림 겸함). 없으면 캐시 미변경.
|
|
179
|
-
// update-fetch 처럼 notified:null 재무장을 하지 않아도 등가다: dedupe 판정이 notified===latest
|
|
180
|
-
// (update-notify)라 전진 버전에서 구 notified 는 항상 신 latest 와 달라 재고지가 정상 발화하고,
|
|
181
|
-
// count-default-on 은 이 훅만·npm 배포는 update-fetch 만 써 같은 캐시를 겹쳐 쓰지 않는다.
|
|
170
|
+
// 응답의 latest 로 공유 update-check 캐시를 갱신(알림 겸함). 없으면 캐시 미변경.
|
|
171
|
+
// update-fetch 처럼 notified:null 재무장을 하지 않아도 등가다: dedupe 판정이 notified===latest
|
|
172
|
+
// (update-notify)라 전진 버전에서 구 notified 는 항상 신 latest 와 달라 재고지가 정상 발화하고,
|
|
173
|
+
// count-default-on 은 이 훅만·npm 배포는 update-fetch 만 써 같은 캐시를 겹쳐 쓰지 않는다.
|
|
174
|
+
async function refreshUpdateCache(responseBody) {
|
|
182
175
|
const latest = extractLatest(responseBody);
|
|
183
|
-
if (latest)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
176
|
+
if (!latest) return;
|
|
177
|
+
// 개인화용: 변경-스킬 매니페스트를 best-effort GET(실패 시 changedSkills 생략, 기존 값 보존).
|
|
178
|
+
const changesUrl = process.env.BANKER_SKILL_CHANGES_URL || SKILL_CHANGES_URL; // 테스트 주입용 override.
|
|
179
|
+
const map = await fetchSkillChangesMap(changesUrl);
|
|
180
|
+
const patch = { latest, checkedAt: Date.now() };
|
|
181
|
+
if (map) patch.changedSkills = changedSkillsBetween(map, installedVersion(), latest);
|
|
182
|
+
try { writeUpdateCache(patch); } catch { /* best-effort */ }
|
|
183
|
+
}
|
|
191
184
|
|
|
192
|
-
|
|
185
|
+
// 전송 시도 후(성공/실패 무관) 로그를 비워 24h 윈도우로 상한(배치 유실 허용).
|
|
186
|
+
function resetLog() {
|
|
193
187
|
try { writeFileSync(USAGE_LOG_PATH, ''); } catch { /* best-effort */ }
|
|
194
188
|
try { writeFileSync(LAST_FLUSH_PATH, new Date().toISOString()); } catch { /* best-effort */ }
|
|
195
189
|
}
|
|
196
190
|
|
|
191
|
+
async function main() {
|
|
192
|
+
if (!countingActive()) return; // 미활성 - 무동작(로그 미변경).
|
|
193
|
+
const url = endpoint();
|
|
194
|
+
if (!url) return; // 엔드포인트 없음 - 무동작(로그 미변경).
|
|
195
|
+
const responseBody = await post(url, checkinBody());
|
|
196
|
+
await refreshUpdateCache(responseBody);
|
|
197
|
+
resetLog();
|
|
198
|
+
}
|
|
199
|
+
|
|
197
200
|
main()
|
|
198
201
|
.catch(() => {}) // 어떤 예외도 삼킨다.
|
|
199
202
|
.finally(() => process.exit(0));
|
package/hooks/update-fetch.mjs
CHANGED
|
@@ -19,9 +19,11 @@ import { readFileSync } from 'node:fs';
|
|
|
19
19
|
import http from 'node:http';
|
|
20
20
|
import https from 'node:https';
|
|
21
21
|
|
|
22
|
-
import { UPDATE_CHECK_PATH, UPDATE_THROTTLE_MS, NPM_LATEST_URL, writeUpdateCache } from '../bin/lib/telemetry-config.mjs';
|
|
22
|
+
import { UPDATE_CHECK_PATH, UPDATE_THROTTLE_MS, NPM_LATEST_URL, writeUpdateCache, collectBody, netDeadlineMs } from '../bin/lib/telemetry-config.mjs';
|
|
23
23
|
|
|
24
24
|
const NET_TIMEOUT_MS = 10_000;
|
|
25
|
+
const NET_DEADLINE_MS = netDeadlineMs(); // 교환 전체 마감(위 값은 무활동 기준).
|
|
26
|
+
const MAX_BODY_BYTES = 256 * 1024; // npm /latest 응답은 수 KB 다.
|
|
25
27
|
|
|
26
28
|
// loopback 호스트만 평문 http 를 허용한다(로컬 테스트 mock 전용). update-checkin.mjs 와 동일 판별:
|
|
27
29
|
// URL.hostname 은 IPv6 를 대괄호로 감싸므로([::1]) 벗겨서 비교한다.
|
|
@@ -45,7 +47,8 @@ function readCache() {
|
|
|
45
47
|
function fetchLatestVersion(url) {
|
|
46
48
|
return new Promise((resolvePromise) => {
|
|
47
49
|
let done = false;
|
|
48
|
-
|
|
50
|
+
let deadline = null;
|
|
51
|
+
const finish = (result) => { if (!done) { done = true; clearTimeout(deadline); resolvePromise(result); } };
|
|
49
52
|
let parsed;
|
|
50
53
|
try {
|
|
51
54
|
parsed = new URL(url);
|
|
@@ -67,21 +70,19 @@ function fetchLatestVersion(url) {
|
|
|
67
70
|
res.resume();
|
|
68
71
|
return finish(null);
|
|
69
72
|
}
|
|
70
|
-
|
|
71
|
-
res.on('data', (c) => { data += c; });
|
|
72
|
-
res.on('end', () => {
|
|
73
|
+
collectBody(res, MAX_BODY_BYTES, (data) => {
|
|
73
74
|
try {
|
|
74
|
-
const obj = JSON.parse(data);
|
|
75
|
+
const obj = JSON.parse(data); // data null(한도 초과, 스트림 오류)은 null 로 읽혀 version 이 없다.
|
|
75
76
|
const v = obj && typeof obj === 'object' ? obj.version : undefined;
|
|
76
77
|
finish((typeof v === 'string' && v) ? v : null);
|
|
77
78
|
} catch {
|
|
78
79
|
finish(null); // 빈/malformed 본문.
|
|
79
80
|
}
|
|
80
81
|
});
|
|
81
|
-
res.on('error', () => finish(null));
|
|
82
82
|
});
|
|
83
83
|
req.on('error', () => finish(null)); // 연결 거부/리셋 등은 즉시 여기로.
|
|
84
84
|
req.setTimeout(NET_TIMEOUT_MS, () => req.destroy());
|
|
85
|
+
deadline = setTimeout(() => { req.destroy(); finish(null); }, NET_DEADLINE_MS);
|
|
85
86
|
req.end(); // GET - 요청 본문 없음.
|
|
86
87
|
} catch {
|
|
87
88
|
finish(null);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaydash9999/banker-plugins",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.1",
|
|
4
4
|
"description": "banker — Claude Code + Codex CLI plugin (QA, audit, docs, architecture, wiki skills). Install via Claude Code marketplace, or `npm i -g @kaydash9999/banker-plugins` then `banker setup`.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"banker": "bin/banker.js"
|
package/skills/anti-drm/SKILL.md
CHANGED
|
@@ -43,9 +43,9 @@ argument-hint: "on | off | status | config"
|
|
|
43
43
|
|
|
44
44
|
| `- 설정:` 줄 | 다음 |
|
|
45
45
|
|---|---|
|
|
46
|
-
| `없음` | 아래 "질문" 을 한 뒤 `on --runtime <런타임> --
|
|
46
|
+
| `없음` | 아래 "질문" 을 한 뒤 "설정 넘기기" 대로 `on --runtime <런타임> --stdin` 실행 |
|
|
47
47
|
| 파일 경로 | `on --runtime <런타임>` |
|
|
48
|
-
| `올바르지 않음` | 이유를 전하고 `
|
|
48
|
+
| `올바르지 않음` | 이유를 전하고 설정을 다시 정할지 물음. 정하면 "질문" 뒤 `없음` 행과 같은 명령 실행. 그 파일은 새 파일로 바뀌고(그 자리가 폴더나 특수 파일이거나, 64KiB 보다 크거나, 읽을 수 없는 파일이면 바꾸지 않고 거부함. 링크와 하드 링크(이름이 둘 이상인 일반 파일)는 거부하지 않고 그 이름만 일반 파일로 바꾸며, 가리키던 파일은 그대로 두고 `.bak` 에 남기지 않음), anti-drm 형식이 아니면 `anti-drm.json.bak` 에 한 번 남음. 에이전트가 그 파일을 직접 지우거나 옮기지 않음 |
|
|
49
49
|
|
|
50
50
|
3. 성공하면 출력의 `적용할 규칙:` 아래 규칙을 이 세션에 바로 적용. 다음 세션부터는 자동 적용
|
|
51
51
|
|
|
@@ -63,7 +63,7 @@ argument-hint: "on | off | status | config"
|
|
|
63
63
|
|
|
64
64
|
1. `status` 로 지금 설정을 봄
|
|
65
65
|
2. 지금 값을 함께 보이며 아래 "질문" 을 함
|
|
66
|
-
3.
|
|
66
|
+
3. "설정 넘기기" 대로 `config --stdin` 실행
|
|
67
67
|
4. 이 런타임이 켜져 있으면 출력의 `적용할 규칙:` 아래 규칙을 이 세션에 바로 적용
|
|
68
68
|
|
|
69
69
|
## 질문
|
|
@@ -100,12 +100,31 @@ argument-hint: "on | off | status | config"
|
|
|
100
100
|
2. 직접 입력은 쉼표나 공백으로 나눔
|
|
101
101
|
3. 낱말마다 `^\.?[A-Za-z0-9]+$` 를 만족해야 함. 아니면 그 값을 보이고 다시 물음
|
|
102
102
|
4. 금지와 대체에 같은 확장자가 있으면 다시 물음
|
|
103
|
-
5.
|
|
103
|
+
5. 정규화한 확장자만 넘김
|
|
104
104
|
- 소문자로 바꿈
|
|
105
105
|
- 앞에 점이 없으면 붙임
|
|
106
|
-
- 쉼표로 이어
|
|
106
|
+
- 쉼표로 이어 "설정 넘기기" 의 `deny=`, `alt=` 줄에 씀
|
|
107
107
|
6. 스크립트가 거부하면 그 메시지를 전하고 다시 물음
|
|
108
108
|
|
|
109
|
+
### 설정 넘기기
|
|
110
|
+
|
|
111
|
+
- 설정 값은 명령줄 인자가 아니라 표준 입력으로 넘김. 따옴표 친 heredoc 안의 글은 셸이 해석하지 않음
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
node "<이 스킬 디렉터리 절대경로>/scripts/anti-drm.mjs" config --stdin <<'ANTI_DRM_SETTINGS'
|
|
115
|
+
deny=.txt,.pdf
|
|
116
|
+
alt=.md,.html,.tsv
|
|
117
|
+
tsv=tab
|
|
118
|
+
ANTI_DRM_SETTINGS
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
- `on` 은 `config` 자리에 `on --runtime <런타임>` 을 씀
|
|
122
|
+
- PowerShell 은 `@'` 와 `'@` 사이에 같은 세 줄을 두고 `| node "<경로>/scripts/anti-drm.mjs" config --stdin` 으로 넘김
|
|
123
|
+
- 넘기기 전에 heredoc 안의 줄마다 `^(deny|alt|tsv)=[a-z0-9., ]*$` 에 맞는지 확인. 하나라도 맞지 않으면 실행하지 않고 "질문" 으로 돌아감
|
|
124
|
+
- "답 처리" 의 단어 검사와 겹치는 두 번째 방벽. 끝 표시(`ANTI_DRM_SETTINGS`, PowerShell 의 `'@`)는 이 꼴에 맞을 수 없어 값이 heredoc 을 일찍 닫지 못함
|
|
125
|
+
- 줄은 `deny=`, `alt=`, `tsv=` 를 하나씩. `tsv=` 는 대체 확장자에 `.tsv` 가 있을 때만 씀
|
|
126
|
+
- `--stdin` 은 입력이 끝날 때까지 기다림. 늘 heredoc 이나 파이프로 넘김
|
|
127
|
+
|
|
109
128
|
## 종료 코드
|
|
110
129
|
|
|
111
130
|
| 코드 | 뜻 | 처리 |
|
|
@@ -194,9 +213,10 @@ argument-hint: "on | off | status | config"
|
|
|
194
213
|
- `off` 는 지우지 않음
|
|
195
214
|
- `.md` 와 `.json` 은 금지할 수 없음. 규칙 파일과 설정 파일의 형식
|
|
196
215
|
- 목록은 각각 64개까지
|
|
197
|
-
- 읽는 파일: 64KiB 이하의 일반
|
|
198
|
-
- 폴더, FIFO, 64KiB 를 넘는 파일, 읽을 수 없는 파일은 덮어쓰지 않음
|
|
199
|
-
-
|
|
216
|
+
- 읽는 파일: 64KiB 이하의 일반 파일만(링크면 가리키는 파일을 읽음). 소유자는 이 계정, 또는 root 만 쓸 수 있는 root
|
|
217
|
+
- 폴더, FIFO, 64KiB 를 넘는 파일, 읽을 수 없는 파일은 덮어쓰지 않음(링크와 하드 링크는 다음 줄)
|
|
218
|
+
- 저장할 때 링크와 하드 링크(이름이 둘 이상인 일반 파일)는 그 이름만 새 파일로 바꿈. 가리키던 파일은 읽지 않고 그대로 둠
|
|
219
|
+
- anti-drm 이 쓰지 않은 파일이 그 자리에 있으면 `anti-drm.json.bak` 에 한 번 남김 (이 계정만 읽기 가능). 링크와 하드 링크는 남기지 않음
|
|
200
220
|
- 설정 폴더
|
|
201
221
|
- Claude Code: `$CLAUDE_CONFIG_DIR`, 없으면 `~/.claude`
|
|
202
222
|
- Codex: `$CODEX_HOME`, 없으면 `~/.codex`
|
|
@@ -206,7 +226,7 @@ argument-hint: "on | off | status | config"
|
|
|
206
226
|
- Codex 블록은 `USER:OMX:POLICY` 표시로 감쌈
|
|
207
227
|
- 블록이 남음: `omx setup --merge-agents`, 기본 `omx setup`(team 모드 켜짐)
|
|
208
228
|
- 블록이 사라짐: `omx setup --force`, 덮어쓰기 확인, team 모드를 끈 `omx setup`. 그 뒤 `on` 다시 실행
|
|
209
|
-
- Codex 파일 변경 전 내용: `<파일>.anti-drm.bak` (이 계정만 읽기 가능)
|
|
229
|
+
- Codex 파일 변경 전 내용: `<파일>.anti-drm.bak` (이 계정만 읽기 가능). `off` 결과에 그 경로를 알림
|
|
210
230
|
- `tone-compact` 블록과 같은 파일에 있어도 서로 건드리지 않음
|
|
211
231
|
- `on`, `off` 는 그 런타임만 바꿈
|
|
212
232
|
- 설정 값을 준 `on` 과 `config` 는 규칙이 들어 있는 다른 런타임도 새 규칙으로 바꿈
|
|
@@ -214,17 +234,28 @@ argument-hint: "on | off | status | config"
|
|
|
214
234
|
|
|
215
235
|
## 문제 해결
|
|
216
236
|
|
|
237
|
+
- 아래 표에서 파일을 보인다는 것은 `ls -l` 로 그 이름의 종류와 링크 대상 경로를 보이는 것이다. 링크가 아닌 일반 파일임을 본 뒤에만 내용을 연다. 심어 둔 링크가 가리키는 파일(키 등)이 세션에 오르지 않게 한다.
|
|
238
|
+
- `.bak` 파일(`anti-drm.json.bak`, `<파일>.anti-drm.bak`)은 내용을 열지 않고 경로만 알린다. 링크가 가리키던 파일(키 등)의 사본일 수 있다. 0.19.0 까지는 설정 파일 자리의 링크도 그 대상을 남겼다.
|
|
239
|
+
|
|
217
240
|
| 메시지 | 조치 |
|
|
218
241
|
|---|---|
|
|
219
242
|
| 설정이 없습니다 | "질문" 으로 설정을 정해 `on` 에 넘김 |
|
|
220
|
-
| 설정
|
|
221
|
-
|
|
|
222
|
-
| 64KiB 보다
|
|
243
|
+
| 표준 입력에 설정 줄이 없습니다 | heredoc 이 비었음. "설정 넘기기" 대로 줄을 넣어 다시 실행 |
|
|
244
|
+
| 표준 입력이 64KiB 보다 큽니다 | "답 처리" 대로 정규화한 값만 넘김 |
|
|
245
|
+
| 설정 파일이 올바르지 않습니다 | 이유를 전하고 설정을 다시 정할지 물은 뒤 진행. 정하면 "질문" 뒤 켜는 중이면 `on --runtime <런타임> --stdin`, 설정만 바꿀 때는 `config --stdin` 실행. 그 파일은 새 파일로 바뀌고(그 자리가 폴더나 특수 파일이거나, 64KiB 보다 크거나, 읽을 수 없는 파일이면 바꾸지 않고 거부함. 링크와 하드 링크(이름이 둘 이상인 일반 파일)는 거부하지 않고 그 이름만 일반 파일로 바꾸며, 가리키던 파일은 그대로 두고 `.bak` 에 남기지 않음), anti-drm 형식이 아니면 `anti-drm.json.bak` 에 한 번 남음(먼저 남긴 파일이나 일반 파일이 아닌 것이 그 자리에 있으면 남기지 않고 결과에 알림). 에이전트가 그 파일을 직접 지우거나 옮기지 않음 |
|
|
246
|
+
| 일반 파일이 아니라 설정을 저장하지 않았습니다 | 설정 경로의 폴더나 특수 파일은 지우지 않음. 무엇인지 보이고, 옮길지 다른 경로(`BANKER_ANTI_DRM_CONFIG`)를 쓸지 물은 뒤 다시 실행 |
|
|
247
|
+
| 64KiB 보다 큰 파일이라, 읽을 수 없는 파일이라 설정을 저장하지 않았습니다 | 그 파일이 무엇인지 보이고, 권한을 고칠지 옮길지 물은 뒤 다시 실행 |
|
|
248
|
+
| 확인하는 사이에 바뀐 자리라 설정을 저장하지 않았습니다 | 설정 파일을 연 사이에 다른 프로그램이 그 자리를 바꿈(Windows, 링크일 수 있음). 지우거나 바꾸지 않음. 무엇인지 보이고(링크면 `ls -l` 로 링크와 대상 경로만 보이고 대상 내용은 열지 않음) 어떻게 할지 물은 뒤 다시 실행 |
|
|
223
249
|
| anti-drm 이 쓰는 형식이라 금지할 수 없습니다 | 금지 목록에서 `.md`, `.json` 을 뺌 |
|
|
224
|
-
| 같은 이름의 다른 파일이 있음 | `rules/banker-anti-drm.md` 가 banker 파일이 아님.
|
|
225
|
-
| 표시의 짝이 맞지 않음 | 지침 파일에 anti-drm 표시 줄이 한쪽만 있거나 문장 속에 있음. 또는 블록 안에 다른 표시 줄이 있음. 짝을 새로 맞추지
|
|
250
|
+
| 같은 이름의 다른 파일이 있음 | `rules/banker-anti-drm.md` 가 banker 파일이 아님. 지우거나 이름을 바꾸지 않음. 내용을 보이고(링크면 `ls -l` 로 링크와 대상 경로만 보이고 대상 내용은 열지 않음) 어떻게 할지 물은 뒤 다시 실행 |
|
|
251
|
+
| 표시의 짝이 맞지 않음 | 지침 파일에 anti-drm 표시 줄이 한쪽만 있거나 문장 속에 있음. 또는 블록 안에 다른 표시 줄이 있음. 짝을 새로 맞추지 않음. 남은 표시 줄을 보이고 지울지 물은 뒤 다시 실행 |
|
|
226
252
|
| 다른 banker 블록만 있어 Codex 가 AGENTS.md 를 읽지 않음 | 메시지가 말한 스킬에서 `on` 실행 |
|
|
227
253
|
| 설정 폴더가 없음 | 해당 런타임 미설치. 또는 설정 폴더 환경 변수 값 확인 |
|
|
228
254
|
| 규칙이 지금 설정이나 이 버전과 다름 | `on` 한 번 실행 |
|
|
229
|
-
| UTF-8 이 아닌 파일 | 지침 파일을 UTF-8 로
|
|
255
|
+
| UTF-8 이 아닌 파일 | 지침 파일을 바꾸지 않음. 인코딩을 보이고, 백업을 만든 뒤 UTF-8 로 바꿀지 물은 뒤 다시 실행 |
|
|
256
|
+
| 끊어진 링크라 그대로 두었습니다 | AGENTS.md 가 가리키는 파일이 없음. 링크를 지우거나 바꾸지 않음. 링크와 대상을 보이고 어떻게 할지 물은 뒤 다시 실행 |
|
|
257
|
+
| AGENTS.md 가 끊어진 링크라 on 이 블록을 옮기지 못함 | AGENTS.override.md 에 블록만 남았고 AGENTS.md 가 가리키는 파일이 없음. 링크를 지우거나 바꾸지 않음. 링크와 대상을 보이고 어떻게 할지 물은 뒤 `on` 실행 |
|
|
258
|
+
| 쓰는 사이에 같은 이름이 생겨 그대로 두었습니다 | 다른 프로그램이 그 사이에 같은 이름을 만들었음(링크일 수 있음). 지우거나 바꾸지 않음. 무엇인지 보이고(링크면 `ls -l` 로 링크와 대상 경로만 보이고 대상 내용은 열지 않음) 어떻게 할지 물은 뒤 다시 실행 |
|
|
259
|
+
| 일반 파일이 아님 | 지침 파일 자리(AGENTS.md, AGENTS.override.md)의 폴더나 특수 파일은 지우지 않음. 무엇인지 사용자에게 보이고, 옮기거나 이름을 바꿀지 물은 뒤 다시 실행 |
|
|
260
|
+
| 다른 banker 지침 작업이 끝나지 않아 그대로 두었습니다 | 다른 banker 스킬의 `on`, `off` 가 도는 중. 잠시 뒤 다시 실행. 끝나지 않은 작업이 남긴 잠금은 1분 뒤 저절로 넘어감. 1분이 지나도 같거나 잠금 자리가 폴더면 잠금 경로를 보이고 어떻게 할지 물은 뒤 다시 실행. 잠금을 임의로 지우지 않음 |
|
|
230
261
|
| 쓸 권한이 없음 | 해당 파일과 폴더 권한 확인 |
|