@kaydash9999/banker-plugins 0.13.0 → 0.14.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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +35 -0
- package/README.md +30 -9
- package/codex/manifest.json +7 -4
- package/codex/transform-matrix.md +14 -2
- package/commands/front-qa.md +6 -3
- package/package.json +1 -1
- package/skills/all-in-one/SKILL.md +160 -55
- package/skills/compact-copy/SKILL.md +14 -13
- package/skills/curation/SKILL.md +36 -3
- package/skills/graceful_pause/SKILL.md +95 -0
- package/skills/omc-reference/SKILL.md +67 -32
- package/skills/payload-mon/SKILL.md +66 -0
- package/skills/payload-mon/scripts/payload-mon.mjs +377 -0
- package/skills/payload-mon/scripts/payload-size.mjs +238 -0
- package/skills/ready-compact/SKILL.md +114 -67
- package/skills/refresh-readme/SKILL.md +2 -2
- package/skills/rfp-author/SKILL.md +2 -2
- package/skills/setup-omc/SKILL.md +10 -3
- package/skills/setup-omc-hud/SKILL.md +11 -0
- package/skills/smart-compact/SKILL.md +10 -9
- package/skills/tone-compact/SKILL.md +203 -0
- package/skills/tone-compact/scripts/tone-compact.mjs +499 -0
- package/skills/ultra-init/SKILL.md +53 -42
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Estimated API request payload of a Claude Code session, for the HUD.
|
|
3
|
+
*
|
|
4
|
+
* Claude Code refuses a request over the API's 32MB limit ("Request too large
|
|
5
|
+
* (max 32MB)") and measures it as the JSON size of the messages it sends
|
|
6
|
+
* ("request_body_over_limit: body=…B (messages only)"). This applies the same
|
|
7
|
+
* measure to the session transcript: everything Claude Code would send since the
|
|
8
|
+
* last compact boundary (images and tool results included), picked with the same
|
|
9
|
+
* filter it uses to build a request (see sentPart).
|
|
10
|
+
*
|
|
11
|
+
* Known gaps, all small next to the 8MB threshold in the sessions measured:
|
|
12
|
+
* - the system prompt and tool schemas are not in the transcript, so the real
|
|
13
|
+
* request is a few hundred KB larger;
|
|
14
|
+
* - after a rewind (Esc Esc) the abandoned branch stays counted until the next
|
|
15
|
+
* compaction;
|
|
16
|
+
* - the few messages a compaction keeps verbatim before its boundary are not
|
|
17
|
+
* added back (13KB or less in each of the 53 compactions measured);
|
|
18
|
+
* - tool results Claude Code clears at request time (microcompact, not seen in
|
|
19
|
+
* these transcripts) stay counted.
|
|
20
|
+
*
|
|
21
|
+
* The transcript only grows, so the scanned offset and running total are cached
|
|
22
|
+
* per transcript under $TMPDIR/omc-hud-payload-<uid>/ and each render reads only
|
|
23
|
+
* what was appended since the last one. A first render (or a rewritten
|
|
24
|
+
* transcript) skims for the last compact boundary and parses only what follows it.
|
|
25
|
+
*
|
|
26
|
+
* On Linux $TMPDIR is usually the shared /tmp, where any account can create a
|
|
27
|
+
* folder first. The uid in the folder name keeps accounts apart, and the cache is
|
|
28
|
+
* used only while that folder is a real directory this account owns and no other
|
|
29
|
+
* account can write to; otherwise every render rescans. macOS and Windows already
|
|
30
|
+
* give each account its own temp folder.
|
|
31
|
+
*
|
|
32
|
+
* When a Claude Code update changes the transcript format or the request filter,
|
|
33
|
+
* fix sentPart and bump CACHE_VERSION, so totals cached under the old rules are
|
|
34
|
+
* rebuilt.
|
|
35
|
+
*/
|
|
36
|
+
import { createHash } from "node:crypto";
|
|
37
|
+
import {
|
|
38
|
+
closeSync,
|
|
39
|
+
fstatSync,
|
|
40
|
+
lstatSync,
|
|
41
|
+
mkdirSync,
|
|
42
|
+
openSync,
|
|
43
|
+
readFileSync,
|
|
44
|
+
readSync,
|
|
45
|
+
renameSync,
|
|
46
|
+
rmSync,
|
|
47
|
+
writeFileSync,
|
|
48
|
+
} from "node:fs";
|
|
49
|
+
import { tmpdir } from "node:os";
|
|
50
|
+
import { dirname, join } from "node:path";
|
|
51
|
+
|
|
52
|
+
export const REQUEST_LIMIT_BYTES = 32 * 1024 * 1024;
|
|
53
|
+
// Shown from 25% of the limit (8MB) on, as an early warning like ctx.
|
|
54
|
+
export const SHOW_FROM_BYTES = REQUEST_LIMIT_BYTES / 4;
|
|
55
|
+
|
|
56
|
+
const MB = 1024 * 1024;
|
|
57
|
+
// The transcript is read in pieces of this size (exported for the tests).
|
|
58
|
+
export const CHUNK_BYTES = 8 * MB;
|
|
59
|
+
const NL = 0x0a;
|
|
60
|
+
const BOUNDARY_MARK = Buffer.from('"compact_boundary"');
|
|
61
|
+
// This account's uid, or null where there is none (Windows).
|
|
62
|
+
const UID = typeof process.getuid === "function" ? process.getuid() : null;
|
|
63
|
+
// Per-transcript estimate cache, one folder per account; payload-mon off deletes it
|
|
64
|
+
// when this account controls the folder (clearCache).
|
|
65
|
+
export const CACHE_DIR = join(tmpdir(), UID === null ? "omc-hud-payload" : `omc-hud-payload-${UID}`);
|
|
66
|
+
// Bump whenever sentPart changes, so cached totals from older rules are rebuilt.
|
|
67
|
+
const CACHE_VERSION = 2;
|
|
68
|
+
// The model Claude Code stamps on the API-error rows it shows but never sends.
|
|
69
|
+
const SYNTHETIC_MODEL = "<synthetic>";
|
|
70
|
+
|
|
71
|
+
const parseLine = (text) => {
|
|
72
|
+
try {
|
|
73
|
+
return JSON.parse(text);
|
|
74
|
+
} catch {
|
|
75
|
+
return null; // torn or foreign line: nothing to count
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const isBoundary = (e) => e?.type === "system" && e.subtype === "compact_boundary";
|
|
80
|
+
|
|
81
|
+
// Rows Claude Code drops from a request: virtual rows and API-error stand-ins.
|
|
82
|
+
const isDropped = (e) => e.isVirtual === true || (e.isApiErrorMessage === true && e.message?.model === SYNTHETIC_MODEL);
|
|
83
|
+
|
|
84
|
+
// An attachment sends its rendered text (system reminders, CLAUDE.md, file
|
|
85
|
+
// mentions). An image @-mention is stored without one, since Claude Code renders
|
|
86
|
+
// it again for each request, so its base64 stands in. A PDF mention sends only a
|
|
87
|
+
// short note, and hook results and snapshots send nothing.
|
|
88
|
+
function attachmentPart(e) {
|
|
89
|
+
if (e.rendered !== undefined) return e.rendered;
|
|
90
|
+
const { type, content } = e.attachment ?? {};
|
|
91
|
+
return type === "file" && content?.type === "image" ? content.file?.base64 : undefined;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// The part of an entry that goes into the request, mirroring Claude Code's own
|
|
95
|
+
// filter: user/assistant content (the compact summary included), local command
|
|
96
|
+
// output and attachments. Sidechains are subagents' own loops.
|
|
97
|
+
function sentPart(e) {
|
|
98
|
+
if (!e || e.isSidechain) return undefined;
|
|
99
|
+
if (e.type === "user" || e.type === "assistant") return isDropped(e) ? undefined : e.message?.content;
|
|
100
|
+
if (e.type === "system") return e.subtype === "local_command" ? e.content : undefined;
|
|
101
|
+
return e.type === "attachment" ? attachmentPart(e) : undefined;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const entryBytes = (e) => {
|
|
105
|
+
const sent = sentPart(e);
|
|
106
|
+
return sent == null ? 0 : Buffer.byteLength(JSON.stringify(sent));
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// Reads [from, size) in chunks and hands each run of complete lines to
|
|
110
|
+
// onLines(buf, base): buf ends in "\n" and starts at file offset base. A last
|
|
111
|
+
// line still being written is left for the next render. Returns the offset just
|
|
112
|
+
// past the last complete line.
|
|
113
|
+
function readCompleteLines(fd, from, size, onLines) {
|
|
114
|
+
let pos = from;
|
|
115
|
+
let base = from;
|
|
116
|
+
let carry = Buffer.alloc(0);
|
|
117
|
+
while (pos < size) {
|
|
118
|
+
const chunk = Buffer.allocUnsafe(Math.min(CHUNK_BYTES, size - pos));
|
|
119
|
+
const n = readSync(fd, chunk, 0, chunk.length, pos);
|
|
120
|
+
if (n === 0) break;
|
|
121
|
+
pos += n;
|
|
122
|
+
const data = carry.length ? Buffer.concat([carry, chunk.subarray(0, n)]) : chunk.subarray(0, n);
|
|
123
|
+
const end = data.lastIndexOf(NL) + 1;
|
|
124
|
+
if (end > 0) onLines(data.subarray(0, end), base);
|
|
125
|
+
base += end;
|
|
126
|
+
carry = data.subarray(end);
|
|
127
|
+
}
|
|
128
|
+
return base;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Offset just past the last real compact boundary, 0 when there is none. Only
|
|
132
|
+
// lines holding the marker are parsed, so a 70MB transcript is skimmed in ~0.2s.
|
|
133
|
+
// Exported so the tests can pin where the count starts.
|
|
134
|
+
export function lastBoundaryEnd(fd, size) {
|
|
135
|
+
let found = 0;
|
|
136
|
+
readCompleteLines(fd, 0, size, (buf, base) => {
|
|
137
|
+
for (let k = buf.indexOf(BOUNDARY_MARK); k !== -1; ) {
|
|
138
|
+
const end = buf.indexOf(NL, k);
|
|
139
|
+
if (isBoundary(parseLine(buf.toString("utf8", buf.lastIndexOf(NL, k) + 1, end)))) found = base + end + 1;
|
|
140
|
+
k = buf.indexOf(BOUNDARY_MARK, end);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
return found;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Running total over the complete lines in [from, size). A compact boundary
|
|
147
|
+
// starts it over: compaction replaces everything sent before it.
|
|
148
|
+
function sumEntries(fd, from, size, bytes) {
|
|
149
|
+
let total = bytes;
|
|
150
|
+
const offset = readCompleteLines(fd, from, size, (buf) => {
|
|
151
|
+
for (let start = 0, end; (end = buf.indexOf(NL, start)) !== -1; start = end + 1) {
|
|
152
|
+
const e = parseLine(buf.toString("utf8", start, end));
|
|
153
|
+
total = isBoundary(e) ? 0 : total + entryBytes(e);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
return { offset, bytes: total };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const cacheFile = (dir, transcriptPath) =>
|
|
160
|
+
join(dir, createHash("sha1").update(transcriptPath).digest("hex").slice(0, 16) + ".json");
|
|
161
|
+
|
|
162
|
+
// Whether dir is a real folder (not a link) that this account owns and no other
|
|
163
|
+
// account can write to. Windows has no uid and gives each account its own temp.
|
|
164
|
+
function ownedDir(dir) {
|
|
165
|
+
try {
|
|
166
|
+
const st = lstatSync(dir);
|
|
167
|
+
return st.isDirectory() && (UID === null || (st.uid === UID && (st.mode & 0o022) === 0));
|
|
168
|
+
} catch {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const loadCache = (file) => {
|
|
174
|
+
if (!ownedDir(dirname(file))) return null;
|
|
175
|
+
try {
|
|
176
|
+
return JSON.parse(readFileSync(file, "utf8"));
|
|
177
|
+
} catch {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
// Write then rename, so a render running at the same time never reads half a
|
|
183
|
+
// file. The temp file is created fresh ("wx"), never written through whatever
|
|
184
|
+
// already sits at its name.
|
|
185
|
+
function saveCache(file, state) {
|
|
186
|
+
try {
|
|
187
|
+
const dir = dirname(file);
|
|
188
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
189
|
+
if (!ownedDir(dir)) return; // a folder this account does not control: no cache
|
|
190
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
191
|
+
rmSync(tmp, { force: true });
|
|
192
|
+
writeFileSync(tmp, JSON.stringify(state), { flag: "wx", mode: 0o600 });
|
|
193
|
+
renameSync(tmp, file);
|
|
194
|
+
} catch {
|
|
195
|
+
/* the cache only saves time; the estimate stands without it */
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Deletes the estimate cache at dir, but only a folder this account controls:
|
|
201
|
+
* one another account created first is left alone, as it was never used.
|
|
202
|
+
*/
|
|
203
|
+
export function clearCache(dir = CACHE_DIR) {
|
|
204
|
+
if (ownedDir(dir)) rmSync(dir, { recursive: true, force: true });
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Estimated request payload, in bytes, of the session whose transcript is at
|
|
209
|
+
* transcriptPath. Throws when the transcript cannot be read.
|
|
210
|
+
*/
|
|
211
|
+
export function estimatePayloadBytes(transcriptPath, cacheDir = CACHE_DIR) {
|
|
212
|
+
const fd = openSync(transcriptPath, "r");
|
|
213
|
+
try {
|
|
214
|
+
const { size, ino } = fstatSync(fd);
|
|
215
|
+
const file = cacheFile(cacheDir, transcriptPath);
|
|
216
|
+
const c = loadCache(file);
|
|
217
|
+
// Resume only a cache of these rules, for this file, which has not shrunk since.
|
|
218
|
+
const resume = c?.v === CACHE_VERSION && c.path === transcriptPath && c.ino === ino && c.offset <= size;
|
|
219
|
+
const state = resume
|
|
220
|
+
? c
|
|
221
|
+
: { v: CACHE_VERSION, path: transcriptPath, ino, offset: lastBoundaryEnd(fd, size), bytes: 0 };
|
|
222
|
+
const next = { ...state, ...sumEntries(fd, state.offset, size, state.bytes) };
|
|
223
|
+
if (!resume || next.offset !== state.offset) saveCache(file, next);
|
|
224
|
+
return next.bytes;
|
|
225
|
+
} finally {
|
|
226
|
+
closeSync(fd);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* The HUD segment, "payload:28%/9.0MB" (share of the 32MB limit / size), in the
|
|
232
|
+
* 5h/wk layout the wrapper colors like ctx; "" below 8MB.
|
|
233
|
+
*/
|
|
234
|
+
export function payloadSegment(bytes) {
|
|
235
|
+
if (!(bytes >= SHOW_FROM_BYTES)) return "";
|
|
236
|
+
const pct = Math.floor((bytes / REQUEST_LIMIT_BYTES) * 100);
|
|
237
|
+
return `payload:${pct}%/${(bytes / MB).toFixed(1)}MB`;
|
|
238
|
+
}
|
|
@@ -1,67 +1,114 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: ready-compact
|
|
3
|
-
description: "(banker)
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
##
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
###
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
###
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
1
|
+
---
|
|
2
|
+
name: ready-compact
|
|
3
|
+
description: "(banker) 진행 상태를 저장하고 이어갈 resume 프롬프트만 출력(설명 없이 프롬프트 본문만이라 /copy 한 번이면 복사). 기본은 같은 세션의 /compact 뒤, --hand-off 는 새 세션에서 처음부터 이어가기. 'ready-compact'/'compact 준비'/'이어서 하게 준비'/'이어갈 프롬프트'/'새 세션으로 넘겨'/'핸드오프' 시 사용."
|
|
4
|
+
argument-hint: "[--hand-off] [토픽 힌트]"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# ready-compact — 이어가기 상태 저장 + resume 프롬프트
|
|
8
|
+
|
|
9
|
+
진행 중인 작업을 끊었다가 이어갈 수 있게 준비한다.
|
|
10
|
+
(1) 이어가기 노트를 내구 저장소에 기록하고, (2) 붙여넣기용 resume 프롬프트를 **최종 메시지 전체로** 내놓는다.
|
|
11
|
+
|
|
12
|
+
## 모드
|
|
13
|
+
|
|
14
|
+
| 모드 | 호출 | 이어 가는 곳 | 그 세션에 이미 있는 것 |
|
|
15
|
+
|---|---|---|---|
|
|
16
|
+
| compact (기본) | `ready-compact` | 같은 세션, `/compact` 뒤 | compaction 요약, 메모리, CLAUDE.md |
|
|
17
|
+
| hand-off | `ready-compact --hand-off` | 같은 머신의 새 세션(`/clear` 뒤, 새 터미널) | 메모리, CLAUDE.md, 저장소뿐. 이번 대화는 없음 |
|
|
18
|
+
|
|
19
|
+
- 인자에서 `--hand-off` 를 떼고 남은 말은 토픽·슬러그 힌트다. 없으면 대화에서 추론한다.
|
|
20
|
+
- 사용자가 "새 세션에서", "핸드오프", "다른 세션으로 넘겨" 처럼 말하면 hand-off 로 본다.
|
|
21
|
+
- 다른 머신이나 다른 사람에게 넘길 때: 노트는 이 머신의 메모리 폴더나 git 무시 폴더에 있어 그쪽에 없다. 결정과 이유, 하지 말 것까지 프롬프트에 직접 넣는다(노트 경로는 참고용).
|
|
22
|
+
|
|
23
|
+
## 언제 쓰나
|
|
24
|
+
- 컨텍스트가 한계에 가까워 곧 compaction 될 때(또는 사용자가 미리 준비를 요청할 때) — compact.
|
|
25
|
+
- 세션을 닫고 새 세션에서 이어 가려 할 때 — hand-off.
|
|
26
|
+
- 사용자가 "ready-compact", "compact 준비", "이어서 할 수 있게 준비" 등으로 요청할 때.
|
|
27
|
+
|
|
28
|
+
## 쓰지 않을 때
|
|
29
|
+
- 작업이 이미 끝났고 이어갈 게 없을 때(그냥 마무리 보고로 충분).
|
|
30
|
+
- 코드/깃/CLAUDE.md/메모리가 그대로 담는 사실의 단순 복제(중복).
|
|
31
|
+
|
|
32
|
+
## 워크플로우
|
|
33
|
+
|
|
34
|
+
### 1) 상태 스냅샷 수집
|
|
35
|
+
지금 대화에서 아래를 추린다 — **메모리/플랜에 이미 있는 건 링크만**, 없는 것만 본문에:
|
|
36
|
+
- **목표(Goal)**: 사용자의 원 요청 한 줄.
|
|
37
|
+
- **현재 단계(Phase)**: 전체 흐름 중 지금 위치.
|
|
38
|
+
- **완료(Done)**: 커밋 해시 + 핵심 산출물(파일/마이그레이션/모니터). 가능하면 `git log --oneline`로 확정.
|
|
39
|
+
- **현재 상태(State)**: 서버/DB/테스트의 *검증된* 상태(예: "37 테스트 PASS, 서버 재기동 정상, 모니터 8/8 PASS").
|
|
40
|
+
- **다음 한 수(Next)**: 이어받자마자 실행할 **구체적** 액션 1~3개(명령/파일/대상 포함). 사용자 결정 대기면 그 사실을 명시.
|
|
41
|
+
- **미결 결정(Open)**: 사용자 판단이 필요한 분기(있으면).
|
|
42
|
+
- **함정·제약(Gotchas)**: 이 작업에서만 비자명한 것(세션 한정 명령, 순서 의존, 미커밋 여부, 운영 미반영 등).
|
|
43
|
+
- **검증 명령(Verify)**: 이어받은 쪽이 현 상태를 즉시 재확인할 복붙 명령.
|
|
44
|
+
|
|
45
|
+
**hand-off 는 여기에 더한다.** 새 세션에는 이 대화가 없으므로, 대화에만 있던 것을 옮긴다:
|
|
46
|
+
- **작업 위치**: 저장소 절대경로, 브랜치, 워크트리 여부, 마지막 커밋 해시.
|
|
47
|
+
- **배경과 결정**: 사용자가 이번 대화에서 정한 것과 그 이유(승인한 설계, 고른 선택지, 거절한 대안).
|
|
48
|
+
- **진행 중인 것**: 켜져 있는 모드(ralph·autopilot·ultragoal·team 등)와 상태 파일 경로, 실행 중인 백그라운드 작업과 출력 파일. 이 세션이 끝나면 백그라운드 작업은 함께 멈출 수 있다는 점.
|
|
49
|
+
- **모드 다시 켜기**: PRD 와 상태 파일은 세션별 경로라 새 세션이 스스로 찾지 못한다. 경로(예: `.omc/state/sessions/<id>/prd.json`, `.omc/plans/…`)와 다시 켜는 방법(예: 새 세션에서 `ralph` 에 그 PRD 경로를 넘김)을 적는다.
|
|
50
|
+
- **하지 말 것**: 이미 끝낸 단계, 사용자가 금지한 동작, 승인을 기다리는 행위(커밋·push·게시 등).
|
|
51
|
+
|
|
52
|
+
**켜져 있는 지속 모드(ralph·autopilot·ultragoal·team 등)가 있으면 먼저 처리한다.** 그 모드의 Stop 훅은 응답이 끝날 때 "계속하라"는 메시지를 넣어, 프롬프트가 마지막 메시지로 남지 못하게 한다.
|
|
53
|
+
- hand-off: 노트를 쓰기 전에 모드를 유지할지(새 세션에서 다시 켬) 지금 cancel 할지 묻고(Claude Code 는 `AskUserQuestion`), 답을 노트에 적는다.
|
|
54
|
+
- Codex: OMX 지속 모드가 켜져 있으면 응답을 끝내도 훅이 계속 다시 시작하게 해, 프롬프트만 남기는 것을 보장할 수 없다. 이 점을 알리고 모드를 끌지 먼저 묻는다.
|
|
55
|
+
|
|
56
|
+
### 2) resume 프롬프트 작성 (저장보다 먼저)
|
|
57
|
+
그대로 붙여넣으면 작업이 이어지는 자급식 프롬프트를 만든다. 3단계에서 노트 끝에 이 프롬프트를 붙이므로 저장보다 먼저 쓴다.
|
|
58
|
+
아래 템플릿은 읽기 쉽게 펜스로 보였을 뿐이다. **프롬프트에는 어디에도 코드 펜스(```)를 넣지 않는다**(4단계). 명령은 두 칸 들여쓰기로 적는다.
|
|
59
|
+
|
|
60
|
+
compact:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
[RESUME] <목표 한 줄>. 진행 메모리: <노트 경로> (+ MEMORY.md, [[관련 slug]]).
|
|
64
|
+
현재까지: <완료 요약 + 커밋 해시>. 상태: <검증된 상태>.
|
|
65
|
+
다음 할 일: <구체 액션 1~3, 또는 "사용자 결정 대기: <옵션들>">.
|
|
66
|
+
미결: <사용자 판단 분기 / 없으면 생략>.
|
|
67
|
+
먼저 현 상태 확인:
|
|
68
|
+
<verify 명령 복붙>
|
|
69
|
+
제약: <환경/순서/미커밋/운영미반영 등 핵심 함정>. (상세는 위 메모리 파일 참조.)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
hand-off:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
[HANDOFF] <목표 한 줄>. 이전 세션의 작업을 새 세션에서 이어 간다.
|
|
76
|
+
작업 폴더: <절대경로> (브랜치 <이름>, 마지막 커밋 <해시>). 이 폴더에서 연 세션이 아니면 사용자에게 이 폴더에서 새 세션을 열어 달라고 요청.
|
|
77
|
+
먼저 읽을 것: <노트 경로> (배경, 결정, 함정 전부).
|
|
78
|
+
현재까지: <완료 요약>. 상태: <검증된 상태>. 미커밋: <파일 목록 / 없음>.
|
|
79
|
+
진행 중이던 것: <모드와 상태 파일, 다시 켜는 방법, 백그라운드 작업과 출력 파일 / 없음>.
|
|
80
|
+
다음 할 일: <구체 액션 1~3, 또는 "사용자 결정 대기: <옵션들>">.
|
|
81
|
+
미결: <사용자 판단 분기 / 없으면 생략>.
|
|
82
|
+
먼저 현 상태 확인:
|
|
83
|
+
<verify 명령 복붙>
|
|
84
|
+
제약: <핵심 함정, 하지 말 것>. 이미 끝난 단계는 다시 하지 않는다.
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 3) 내구 저장
|
|
88
|
+
|
|
89
|
+
| 런타임 | 노트 위치 |
|
|
90
|
+
|---|---|
|
|
91
|
+
| Claude Code | 자동 메모리 폴더 `<memory>/resume-<topic-slug>.md`(frontmatter `type: project`) + `MEMORY.md` 한 줄 포인터 추가/갱신. 자동 메모리가 꺼져 있어 폴더를 모르면 작업 폴더의 `.omc/handoffs/resume-<topic-slug>.md` |
|
|
92
|
+
| Codex | 작업 폴더의 `.omx/handoffs/resume-<topic-slug>.md` (Codex 에는 자동 메모리 폴더가 없다) |
|
|
93
|
+
|
|
94
|
+
- **기존 메모리/플랜과 중복은 피하고**, 관련 메모리는 `[[slug]]`로 링크(Claude Code).
|
|
95
|
+
- compact 노트는 휘발성 위주로 응축한다. hand-off 노트는 **그 파일 하나만 읽어도** 이어갈 수 있게 1단계의 추가 항목까지 적는다.
|
|
96
|
+
- 작업이 git 미커밋 상태면 그 사실과 파일 목록을 명시(다음 세션이 덮어쓰지 않도록).
|
|
97
|
+
- 노트 끝에 2단계의 프롬프트를 그대로 붙인다. 클립보드를 잃어도 노트에서 되찾을 수 있다.
|
|
98
|
+
- 작업 폴더 안에 둔 노트(`.omc/handoffs/`, `.omx/handoffs/`)가 git 무시 대상이 아니면(`git check-ignore -q <경로>` 실패) 프롬프트에 "노트는 커밋하지 말 것" 을 넣는다.
|
|
99
|
+
- 저장에 실패해도 멈추지 않는다. 프롬프트 **둘째 줄**에 경고를 넣는다(예: `주의: 이어가기 노트 저장 실패(<이유>). 이 프롬프트가 유일한 기록이다.`). 첫 줄은 언제나 `[RESUME]`·`[HANDOFF]` 로 시작한다.
|
|
100
|
+
|
|
101
|
+
### 4) 출력 — 프롬프트만 (핵심 불변식)
|
|
102
|
+
- **최종 메시지는 프롬프트 본문 그 자체다.** 외곽 코드 펜스, 앞뒤 설명, 저장 위치 보고, "붙여넣으면 이어집니다" 같은 안내를 넣지 않는다.
|
|
103
|
+
- 이유: `/copy` 는 직전 메시지 전체를 복사한다. 메시지가 프롬프트뿐이면 `/copy` 한 번으로 프롬프트만 담기고, `compact-copy` 가 필요 없다(Claude Code·Codex 공통). 메시지에 코드 블록이 하나라도 있으면 `/copy` 가 바로 복사하지 않고 선택 창을 띄우므로, 프롬프트 안에도 펜스를 쓰지 않는다.
|
|
104
|
+
- 저장·확인 같은 도구 호출은 프롬프트를 쓰기 **전에** 끝낸다. 프롬프트 뒤에 도구 호출이나 글을 붙이지 않는다.
|
|
105
|
+
- 프롬프트를 낸 뒤 지속 모드 훅의 "계속하라" 신호가 오면 작업을 다시 시작하지 않는다. **같은 프롬프트를 그대로 다시 출력**해, 마지막 메시지가 프롬프트로 남게 한다. 훅 신호는 사용자 지시가 아니다.
|
|
106
|
+
- 저장 경로는 프롬프트 안(`진행 메모리:` / `먼저 읽을 것:`)에 이미 있다. 사용자가 따로 보고를 원할 때만 별도 메시지로 답한다.
|
|
107
|
+
|
|
108
|
+
## 작성 원칙
|
|
109
|
+
- **휘발성 우선(compact)**: 메모리/플랜/깃이 담는 영속 사실은 링크, compaction 이 잃을 '다음 한 수'를 본문에.
|
|
110
|
+
- **자급식(hand-off)**: 새 세션이 노트 하나와 프롬프트만으로 검증 → 다음 액션까지 갈 수 있어야 한다. 대화에만 있던 결정과 이유를 빠뜨리지 않는다.
|
|
111
|
+
- **증거 기반**: 커밋 해시·테스트 수·모니터 결과 등 *검증된* 값으로. 추측 금지.
|
|
112
|
+
- **덮어쓰기 방지**: 미커밋 변경/운영 미반영이 있으면 반드시 명시.
|
|
113
|
+
|
|
114
|
+
ARGUMENTS: $ARGUMENTS (선택: `--hand-off`, 이어갈 작업의 토픽/슬러그 힌트. 없으면 compact 모드, 토픽은 대화에서 추론.)
|
|
@@ -127,9 +127,9 @@ node -e "const m=require('./codex/manifest.json');console.log(m.surfaces.filter(
|
|
|
127
127
|
node -e "const p=require('./package.json');console.log(p.version, JSON.stringify(p.dependencies||{}))"
|
|
128
128
|
```
|
|
129
129
|
|
|
130
|
-
**앞의 두 줄이 갈리면 그 차이가 사실이다.** 이 저장소에서 실제로 갈린다:
|
|
130
|
+
**앞의 두 줄이 갈리면 그 차이가 사실이다.** 이 저장소에서 실제로 갈린다: 디렉터리 수가 `SKILL.md` 보유 수보다 하나 많다.
|
|
131
131
|
`skills/ultra-init-workspace/` 는 런타임 산출물 디렉터리라 `SKILL.md` 가 없고, 그래서 배포 매니페스트에도 없고 `package.json` `files[]` 도 negation 으로 뺀다.
|
|
132
|
-
즉 "디렉터리를 세면 스킬 수" 라는 그럴듯한 가정이 **여기서 1 을 더 센다.** 세 곳(매니페스트·`files[]`·테스트의 `SKILL.md` 필터)이 이미
|
|
132
|
+
즉 "디렉터리를 세면 스킬 수" 라는 그럴듯한 가정이 **여기서 1 을 더 센다.** 세 곳(매니페스트·`files[]`·테스트의 `SKILL.md` 필터)이 이미 같은 수를 말하는데 디렉터리 카운트만 하나 더 크다면, 틀린 쪽은 카운트다.
|
|
133
133
|
|
|
134
134
|
**README 는 어떤 경우에도 사실이 아니다. 그리고 사실을 세는 명령도 틀릴 수 있다. 세 소스가 같은 값을 말할 때만 통과다.**
|
|
135
135
|
|
|
@@ -39,7 +39,7 @@ description: "(banker) 소프트웨어 외주 제안요청서(RFP)를 한국 공
|
|
|
39
39
|
## 워크플로우 (도구 오케스트레이션)
|
|
40
40
|
RFP 저작은 **저작 lane과 검수 lane을 분리**(자기승인 금지). 권장 순서:
|
|
41
41
|
|
|
42
|
-
1. **과업내용 추출** — 현 코드/spec → 요구사항. `deep-dive`
|
|
42
|
+
1. **과업내용 추출** — 현 코드/spec → 요구사항. `research`(OMC 5 에서 삭제된 `deep-dive` 의 대체) 또는 agent `feature-dev:code-explorer` 로 화면·API·데이터·외부연계를 SFR/INR/DAR로 도출 → `references/this-project-scope.md` 채움(file:LINE 동반). 디자인은 PDF/이미지 추출 도구로 `<DesignRef(page-section)>` 형태 인용키 추출.
|
|
43
43
|
2. **구조·범위·배점 합의** — `ralplan --deliberate`로 RFP 구조·15유형 범위·평가 정성/정량 배점을 Planner→Architect→Critic 합의(Planner는 SoT word-for-word 인용 의무). broad/risky 결정만.
|
|
44
44
|
3. **섹션 병렬 작성** — 5+ 섹션이면 `team`(워커별 절 담당), 소규모는 agent `oh-my-claudecode:writer`. 각 절은 `templates/rfp-skeleton.md`를 채우고 `references/`를 인용.
|
|
45
45
|
4. **미검증 보강** — OPEN 항목(특히 망분리/PIPA/보안성심의/secure-coding)은 `autoresearch`/`deep-research` 또는 agent `document-specialist`로 **추가 리서치 후** SER에 반영. 미보강 시 〈OPEN〉 유지.
|
|
@@ -48,7 +48,7 @@ RFP 저작은 **저작 lane과 검수 lane을 분리**(자기승인 금지). 권
|
|
|
48
48
|
|
|
49
49
|
| 작업 | 권장 도구 |
|
|
50
50
|
|---|---|
|
|
51
|
-
| 과업내용 추출(코드→요구) | `deep-dive` / `feature-dev:code-explorer` / PDF·이미지 추출 도구 |
|
|
51
|
+
| 과업내용 추출(코드→요구) | `research`(구 `deep-dive`) / `feature-dev:code-explorer` / PDF·이미지 추출 도구 |
|
|
52
52
|
| 구조·배점 합의 | `ralplan --deliberate` |
|
|
53
53
|
| 섹션 병렬 저작 | `team` / `oh-my-claudecode:writer` |
|
|
54
54
|
| OPEN 추가 리서치 | `autoresearch` / `deep-research` / `document-specialist` |
|
|
@@ -6,21 +6,28 @@ description: "(banker) all-in-one·ultra-init·front-qa 가 의존하는 oh-my-c
|
|
|
6
6
|
# setup-omc: oh-my-claudecode(OMC) 설치/갱신
|
|
7
7
|
|
|
8
8
|
banker의 오케스트레이터(`all-in-one`·`ultra-init`)와 `/banker:front-qa` 커맨드는 OMC의
|
|
9
|
-
`ralplan`·`ralph`·`
|
|
9
|
+
`ralplan`·`ralph`·`verify` 와 `omc` CLI(`omc ralph verify`)에 의존한다. OMC 5부터 `ralph` 가 첫 반복에 `omc ralph verify` 를 직접 부르므로, 플러그인만 새것이고 전역 `omc` CLI 가 낡으면(4.x) `ralph` 가 시작하자마자 멈춘다. 이 스킬은 OMC를 설치하거나 최신화한다(이미 있으면 갱신만; 멱등). 답변은 한글.
|
|
10
10
|
|
|
11
11
|
## 0. 감지 (먼저, 추정 금지)
|
|
12
12
|
```bash
|
|
13
13
|
command -v omc >/dev/null && omc --version || echo "omc: 미설치"
|
|
14
|
+
omc ralph verify --help 2>&1 | grep -q 'Usage: omc ralph verify' && echo "omc CLI: ralph verify 있음" || echo "omc CLI: ralph verify 없음 (미설치 또는 4.x)"
|
|
14
15
|
command -v claude >/dev/null || echo "claude: 미설치"
|
|
15
16
|
```
|
|
17
|
+
- `ralph verify` 는 종료 코드가 아니라 **출력 문구로 판정**한다. 4.x CLI 는 모르는 명령에 `--help` 를 붙이면 전체 도움말을 찍고 0 으로 끝난다. `--help` 없이 부르면 Claude 실행으로 넘어가므로 점검에는 반드시 붙인다.
|
|
16
18
|
|
|
17
19
|
## Claude Code · OMC
|
|
18
20
|
- **이미 설치(`omc` 존재)** 면 최신화만 한다:
|
|
19
21
|
```bash
|
|
20
22
|
omc update # 플러그인·npm 패키지·CLAUDE.md 동기화
|
|
21
23
|
```
|
|
24
|
+
- `omc update` 가 중간에 실패하거나 끝난 뒤에도 `ralph verify` 가 없으면, CLI 만 직접 올린다:
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g oh-my-claude-sisyphus@latest
|
|
27
|
+
```
|
|
28
|
+
- 네이티브 모듈(`better-sqlite3`) 빌드가 낡은 기본 컴파일러 때문에 실패하는 배포판(예: RHEL·Rocky 8)은 새 gcc 를 켠 셸에서 같은 명령을 실행한다(예: `source /opt/rh/gcc-toolset-14/enable`).
|
|
22
29
|
- **미설치** 면 공식 배포처 절차를 따른다(일반적으로 npm 전역 설치 후 `omc setup`). 정확한 설치 명령이 불명확하면 추정하지 말고 사용자에게 확인한다.
|
|
23
|
-
- 확인: `omc --version`
|
|
30
|
+
- 확인: `omc --version`, 위 `ralph verify` 점검 통과, Claude 재시작·`/reload-plugins` 후 `/oh-my-claudecode:*` 노출.
|
|
24
31
|
|
|
25
32
|
## Codex CLI · OMX (oh-my-codex)
|
|
26
33
|
Codex에서의 대응 프레임워크는 OMX다.
|
|
@@ -30,7 +37,7 @@ command -v omx >/dev/null && omx setup # 유저/프로젝트 레벨 OMX 구
|
|
|
30
37
|
- 미설치면 OMX 배포처 안내대로 설치 후 `omx setup`.
|
|
31
38
|
|
|
32
39
|
## 검증·보고
|
|
33
|
-
- OMC: `omc --version` / OMX: `omx --version`. 반영엔 재시작·`/reload-plugins`(Claude)가 필요할 수 있다.
|
|
40
|
+
- OMC: `omc --version` + `ralph verify` 점검 / OMX: `omx --version`. 반영엔 재시작·`/reload-plugins`(Claude)가 필요할 수 있다.
|
|
34
41
|
- 실패·불명확은 정직 보고(가짜 성공 금지).
|
|
35
42
|
|
|
36
43
|
## 함정
|
|
@@ -13,6 +13,14 @@ description: "(banker) omc_hud(Claude Code 상태표시줄)를 OS별 apply 스
|
|
|
13
13
|
```bash
|
|
14
14
|
case "$(uname -s)" in Darwin) OS=mac;; Linux) OS=linux;; *) OS=windows;; esac; echo "OS=$OS"
|
|
15
15
|
command -v wget >/dev/null && echo "dl=wget" || { command -v curl >/dev/null && echo "dl=curl" || echo "dl=none(설치 필요)"; }
|
|
16
|
+
# 적용 스크립트가 래퍼를 덮어쓰면 payload-mon 표시 블록이 빠진다. 지금 켜져 있는지 기억해 둔다(3단계에서 사용).
|
|
17
|
+
HUD_FILE="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/hud/omc-hud-custom.mjs"
|
|
18
|
+
grep -qF '// >>> payload-mon >>>' "$HUD_FILE" 2>/dev/null && echo "payload-mon=on" || echo "payload-mon=off"
|
|
19
|
+
```
|
|
20
|
+
Windows(PowerShell)에서는 같은 확인을 이렇게 한다:
|
|
21
|
+
```powershell
|
|
22
|
+
$cfg = if ($env:CLAUDE_CONFIG_DIR) { $env:CLAUDE_CONFIG_DIR } else { "$env:USERPROFILE\.claude" }
|
|
23
|
+
if (Select-String -Quiet -SimpleMatch -LiteralPath "$cfg\hud\omc-hud-custom.mjs" -Pattern '// >>> payload-mon >>>' -ErrorAction SilentlyContinue) { "payload-mon=on" } else { "payload-mon=off" }
|
|
16
24
|
```
|
|
17
25
|
|
|
18
26
|
## 1. mac / linux — apply 스크립트 적용
|
|
@@ -41,6 +49,9 @@ git 없으면 GitHub "Download ZIP" → 해제 → 동봉 적용 스크립트
|
|
|
41
49
|
- 적용 스크립트가 `~/.claude/settings.json` 의 statusLine 등을 갱신했는지(스크립트 출력 확인).
|
|
42
50
|
- HUD는 **다음 프롬프트/세션**부터 반영될 수 있음 → 안 보이면 재시작 안내.
|
|
43
51
|
- `~/dummy` 임시파일 정리 확인. 이미 적용돼 있으면 재적용 불필요.
|
|
52
|
+
- **payload-mon 복구**: 0단계에서 `payload-mon=on` 이었다면, 적용 스크립트가 래퍼를 덮어써 payload 표시 블록이 빠진 상태다.
|
|
53
|
+
payload-mon 스킬(Claude Code `/banker:payload-mon`, Codex `banker-payload-mon`)을 `on` 으로 실행해 다시 켜고, 그 결과를 함께 보고한다.
|
|
54
|
+
`payload-mon=off` 였다면 아무것도 하지 않는다(사용자가 켠 적 없는 기능을 켜지 않는다).
|
|
44
55
|
|
|
45
56
|
## 함정
|
|
46
57
|
- `curl` 다운로드는 **대문자 `-O`**(원격 파일명 유지). 소문자 `-o`는 출력명 지정이라 다름.
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: smart-compact
|
|
3
|
-
description: "(banker) 컨텍스트 임계(기본 50%) 초과 시 append-wiki→ready-compact
|
|
3
|
+
description: "(banker) 컨텍스트 임계(기본 50%) 초과 시 append-wiki→ready-compact 자동 실행(마지막 메시지가 resume 프롬프트뿐) + /copy·/compact·paste 유저 핸드오프 게이트. 'smart-compact' 활성화 / '--cancel' 해제."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# smart-compact — 컨텍스트 위생 자동 게이트
|
|
7
7
|
|
|
8
8
|
긴 세션에서 컨텍스트가 임계(기본 **50%**)를 넘으면, compaction 전에 상태를 안전하게 보존하는
|
|
9
|
-
리추얼을 **자동 발동**한다: `append-wiki` → `ready-compact` →
|
|
9
|
+
리추얼을 **자동 발동**한다: `append-wiki` → `ready-compact` → *(유저)* `/copy`
|
|
10
10
|
→ `/compact` → paste. `smart-compact` 로 무장, `smart-compact --cancel` 로 해제한다.
|
|
11
|
+
`ready-compact` 는 0.14.0 부터 마지막 메시지를 resume 프롬프트만으로 내므로, 예전처럼 `compact-copy` 를 거치지 않는다.
|
|
11
12
|
|
|
12
13
|
## ⚠️ 정직한 실현 한계 (Claude Code 실측)
|
|
13
14
|
"컨텍스트 50%에서 완전 무인 자동"은 **부분만 가능**하다 — 근거:
|
|
14
15
|
- **감지**: 컨텍스트 사용률은 **statusLine stdin** 의 `context_window.used_percentage` 로만 실시간
|
|
15
16
|
노출된다(hook은 이 값을 못 받음; auto-compact은 ~95%에서만, 50% 이벤트 없음). → statusLine으로
|
|
16
17
|
**정확히 50% 감지 가능**.
|
|
17
|
-
- **자동 실행 가능(어시스턴트)**: `append-wiki` · `ready-compact`
|
|
18
|
+
- **자동 실행 가능(어시스턴트)**: `append-wiki` · `ready-compact` — 스킬/도구
|
|
18
19
|
작업이라 어시스턴트가 수행.
|
|
19
20
|
- **자동 불가(TUI 전용)**: `/copy` · `/compact` · **paste** 는 인터랙티브 TUI 동작이라 hook·스킬이
|
|
20
21
|
구동할 수 없다(hook은 슬래시명령 호출 불가, `additionalContext` 주입만 가능). → **이 3단은 유저가
|
|
@@ -35,7 +36,7 @@ description: "(banker) 컨텍스트 임계(기본 50%) 초과 시 append-wiki→
|
|
|
35
36
|
2. **hook 브리지**: `UserPromptSubmit`(또는 `PreToolUse`) hook이 신호 파일을 읽어 무장·미처리 상태면
|
|
36
37
|
`additionalContext` 로 "smart-compact: 컨텍스트 ≥임계 — 위생 체인 실행" 을 주입한다(hook은 명령을
|
|
37
38
|
못 부르므로 어시스턴트에게 **지시만** 한다).
|
|
38
|
-
3. **게이트 동작(어시스턴트)**: 주입을 받으면
|
|
39
|
+
3. **게이트 동작(어시스턴트)**: 주입을 받으면 자동파트를 실행한다. TUI 3단 안내는 `ready-compact` **전에** 한 줄로 하고, 마지막 메시지는 `ready-compact` 의 프롬프트로 끝낸다(안내를 뒤에 붙이면 `/copy` 가 안내문을 복사한다).
|
|
39
40
|
|
|
40
41
|
**Codex (OMX):**
|
|
41
42
|
- Codex가 statusline/hook에 컨텍스트%를 노출하는지 **미확인**(문서 부재). 노출되면 위와 동형으로 구성
|
|
@@ -46,13 +47,13 @@ description: "(banker) 컨텍스트 임계(기본 50%) 초과 시 append-wiki→
|
|
|
46
47
|
무장 후 임계 초과가 감지되면 순서대로:
|
|
47
48
|
|
|
48
49
|
1. **`append-wiki`** — 이번 작업의 비자명 지식을 wiki에 적재(휘발 방지). *(banker `append_wiki`, both)*
|
|
49
|
-
2.
|
|
50
|
-
3. **`compact
|
|
50
|
+
2. *(한 줄 안내)* 다음 메시지가 resume 프롬프트이며, 그 뒤 `/copy` → `/compact` → 붙여넣기 순서임을 알린다.
|
|
51
|
+
3. **`ready-compact`** — 내구 메모리 기록 + resume 프롬프트. 마지막 메시지가 프롬프트뿐이다. *(banker `ready-compact`, both)*
|
|
51
52
|
4. *(유저 · TUI)* **`/copy`** → **`/compact`** → **paste**(복사된 resume 프롬프트 입력).
|
|
52
53
|
|
|
53
|
-
1~3은 어시스턴트가 자동 수행. 4는
|
|
54
|
-
(Claude=`/banker:append_wiki`·`/banker:ready-compact
|
|
55
|
-
Codex=`$banker-append_wiki`·`$banker-ready-compact
|
|
54
|
+
1~3은 어시스턴트가 자동 수행. 4는 유저가 실행한다. 안내는 2에서 끝내고 3 뒤에는 아무것도 붙이지 않는다.
|
|
55
|
+
(Claude=`/banker:append_wiki`·`/banker:ready-compact`,
|
|
56
|
+
Codex=`$banker-append_wiki`·`$banker-ready-compact`; `/copy`·compaction은 양쪽 TUI 내장.)
|
|
56
57
|
|
|
57
58
|
## 활성화 (idempotent · compose-safe)
|
|
58
59
|
`smart-compact [--threshold N]` (기본 N=50):
|