@tienne/gestalt 0.115.0 → 0.117.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 (85) hide show
  1. package/README.ko.md +1 -1
  2. package/README.md +1 -1
  3. package/dist/package.json +1 -1
  4. package/dist/plugin/role-agents/lens-reader/AGENT.md +22 -1
  5. package/dist/plugin/skills/_shared/proactive-routing.md +1 -1
  6. package/dist/plugin/skills/lens/SKILL.md +114 -8
  7. package/dist/plugin/skills/share/SKILL.md +39 -6
  8. package/dist/plugin/skills/share/agents/openai.yaml +1 -1
  9. package/dist/plugin/skills/video-digest/SKILL.md +4 -2
  10. package/dist/plugin/skills/video-digest/templates/comments.md +1 -0
  11. package/dist/src/cli/commands/digest.d.ts +1 -0
  12. package/dist/src/cli/commands/digest.d.ts.map +1 -1
  13. package/dist/src/cli/commands/digest.js +15 -4
  14. package/dist/src/cli/commands/digest.js.map +1 -1
  15. package/dist/src/cli/commands/peer.d.ts +11 -1
  16. package/dist/src/cli/commands/peer.d.ts.map +1 -1
  17. package/dist/src/cli/commands/peer.js +113 -5
  18. package/dist/src/cli/commands/peer.js.map +1 -1
  19. package/dist/src/cli/index.d.ts.map +1 -1
  20. package/dist/src/cli/index.js +7 -3
  21. package/dist/src/cli/index.js.map +1 -1
  22. package/dist/src/digest/render-blocks.d.ts +5 -0
  23. package/dist/src/digest/render-blocks.d.ts.map +1 -1
  24. package/dist/src/digest/render-blocks.js +2 -2
  25. package/dist/src/digest/render-blocks.js.map +1 -1
  26. package/dist/src/digest/render-html.d.ts +2 -2
  27. package/dist/src/digest/render-html.d.ts.map +1 -1
  28. package/dist/src/digest/render-html.js +20 -3
  29. package/dist/src/digest/render-html.js.map +1 -1
  30. package/dist/src/digest/render-md.d.ts.map +1 -1
  31. package/dist/src/digest/render-md.js +9 -2
  32. package/dist/src/digest/render-md.js.map +1 -1
  33. package/dist/src/digest/server.d.ts +46 -1
  34. package/dist/src/digest/server.d.ts.map +1 -1
  35. package/dist/src/digest/server.js +213 -10
  36. package/dist/src/digest/server.js.map +1 -1
  37. package/dist/src/digest/session-request.d.ts +78 -0
  38. package/dist/src/digest/session-request.d.ts.map +1 -0
  39. package/dist/src/digest/session-request.js +105 -0
  40. package/dist/src/digest/session-request.js.map +1 -0
  41. package/dist/src/digest/svg.d.ts +5 -0
  42. package/dist/src/digest/svg.d.ts.map +1 -1
  43. package/dist/src/digest/svg.js +19 -9
  44. package/dist/src/digest/svg.js.map +1 -1
  45. package/dist/src/digest/templates.d.ts +9 -0
  46. package/dist/src/digest/templates.d.ts.map +1 -1
  47. package/dist/src/digest/templates.js +12 -0
  48. package/dist/src/digest/templates.js.map +1 -1
  49. package/dist/src/digest/viewer-js.d.ts.map +1 -1
  50. package/dist/src/digest/viewer-js.js +534 -46
  51. package/dist/src/digest/viewer-js.js.map +1 -1
  52. package/dist/src/digest/viewer-logic.d.ts +26 -5
  53. package/dist/src/digest/viewer-logic.d.ts.map +1 -1
  54. package/dist/src/digest/viewer-logic.js +44 -7
  55. package/dist/src/digest/viewer-logic.js.map +1 -1
  56. package/dist/src/mcp/tools/peer.d.ts.map +1 -1
  57. package/dist/src/mcp/tools/peer.js +18 -18
  58. package/dist/src/mcp/tools/peer.js.map +1 -1
  59. package/dist/src/peer/client.d.ts +5 -1
  60. package/dist/src/peer/client.d.ts.map +1 -1
  61. package/dist/src/peer/client.js +6 -2
  62. package/dist/src/peer/client.js.map +1 -1
  63. package/dist/src/peer/detach.d.ts +114 -0
  64. package/dist/src/peer/detach.d.ts.map +1 -0
  65. package/dist/src/peer/detach.js +339 -0
  66. package/dist/src/peer/detach.js.map +1 -0
  67. package/dist/src/peer/locate.d.ts +15 -0
  68. package/dist/src/peer/locate.d.ts.map +1 -1
  69. package/dist/src/peer/locate.js +43 -0
  70. package/dist/src/peer/locate.js.map +1 -1
  71. package/dist/src/peer/lock.d.ts +6 -0
  72. package/dist/src/peer/lock.d.ts.map +1 -1
  73. package/dist/src/peer/lock.js +17 -1
  74. package/dist/src/peer/lock.js.map +1 -1
  75. package/package.json +1 -1
  76. package/plugin/.codex-plugin/plugin.json +1 -1
  77. package/plugin/.mcp.json +1 -1
  78. package/plugin/mcp.json +1 -1
  79. package/plugin/role-agents/lens-reader/AGENT.md +22 -1
  80. package/plugin/skills/_shared/proactive-routing.md +1 -1
  81. package/plugin/skills/lens/SKILL.md +114 -8
  82. package/plugin/skills/share/SKILL.md +39 -6
  83. package/plugin/skills/share/agents/openai.yaml +1 -1
  84. package/plugin/skills/video-digest/SKILL.md +4 -2
  85. package/plugin/skills/video-digest/templates/comments.md +1 -0
@@ -0,0 +1,339 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { closeSync, constants, fchmodSync, fstatSync, ftruncateSync, openSync, readSync, writeSync, } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { request } from './client.js';
5
+ import { lockPath, processAlive, readLockPid } from './lock.js';
6
+ import { plainLabel } from './message.js';
7
+ import { ensurePrivateDir, socketPath } from './paths.js';
8
+ /**
9
+ * 떨어져 뜬 데몬의 로그 상한. 데몬은 뜰 때 안내 몇 줄과 실패만 적어서 평소에는 거의 안 는다. 넘으면 지금 로그를
10
+ * `daemon.log.1`로 복사하고 비운다. 그래서 디스크에 남는 건 상한의 두 배 남짓이다
11
+ */
12
+ export const DAEMON_LOG_MAX_BYTES = 1024 * 1024;
13
+ /** 떨어져 뜬 데몬이 로그 크기를 보는 간격 */
14
+ export const DAEMON_LOG_CHECK_MS = 60_000;
15
+ /** `--detach`가 소켓 답을 기다리는 시간과 `--stop`이 프로세스가 끝나길 기다리는 시간의 기본값 */
16
+ export const DEFAULT_DAEMON_WAIT_MS = 10_000;
17
+ /**
18
+ * `--detach`가 자식에 거는 환경 변수. 자식은 이걸 보고 로그 크기를 챙기고 안내 문구를 바꾼 뒤 지운다.
19
+ * 멈추는 길이나 잠금 규칙은 이 값과 상관없이 같다
20
+ */
21
+ export const DETACHED_ENV = 'GESTALT_PEER_DETACHED';
22
+ /** 이번 기동부터 로그 꼬리를 자르는 표시 줄의 앞머리 */
23
+ const MARKER = '=== gestalt peer daemon --detach';
24
+ const POLL_MS = 100;
25
+ /** 데몬에 넘기지 않는 Node 옵션. 디버거 포트가 겹치거나 파일이 바뀔 때마다 데몬이 다시 뜬다 */
26
+ const DEV_FLAG = /^--(inspect|debug|watch)/;
27
+ export function daemonLogPath(root) {
28
+ return join(root, 'daemon.log');
29
+ }
30
+ /**
31
+ * 로그가 상한을 넘었으면 `.1`로 복사하고 비운다. 이름을 옮기지 않는 건 떠 있는 데몬이 열어 둔 파일을
32
+ * 계속 쓰기 때문이다. 옮기면 데몬은 `.1`에 쓰고 원래 이름의 파일은 다시 안 큰다. 열 때 `O_APPEND`라서
33
+ * 비운 뒤에 쓰는 줄은 파일 앞에서부터 다시 쌓인다. 복사와 비우기 사이에 쓰인 줄은 잃을 수 있다.
34
+ *
35
+ * 두 파일 다 `O_NOFOLLOW`로 열어 연 fd로만 읽고 쓰고 비운다. 경로로 다시 열면 확인한 파일과 쓰는 파일이
36
+ * 다를 수 있다. 원본이 없거나 심링크면 아무것도 안 하고 false다. `.1`이 심링크면 던진다.
37
+ */
38
+ export function rotateDaemonLog(path, max = DAEMON_LOG_MAX_BYTES) {
39
+ let src;
40
+ try {
41
+ src = openSync(path, constants.O_RDWR | constants.O_NOFOLLOW | constants.O_NONBLOCK);
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ try {
47
+ const st = fstatSync(src);
48
+ if (!st.isFile() || st.size <= max)
49
+ return false;
50
+ const old = `${path}.1`;
51
+ const dst = openSync(old, constants.O_WRONLY |
52
+ constants.O_CREAT |
53
+ constants.O_TRUNC |
54
+ constants.O_NOFOLLOW |
55
+ constants.O_NONBLOCK, 0o600);
56
+ try {
57
+ if (!fstatSync(dst).isFile())
58
+ throw new Error(`peer 로그 자리에 다른 파일이 있어요: ${old}`);
59
+ fchmodSync(dst, 0o600);
60
+ const buf = Buffer.alloc(64 * 1024);
61
+ for (let pos = 0;;) {
62
+ const n = readSync(src, buf, 0, buf.length, pos);
63
+ if (n === 0)
64
+ break;
65
+ writeSync(dst, buf, 0, n);
66
+ pos += n;
67
+ }
68
+ }
69
+ finally {
70
+ closeSync(dst);
71
+ }
72
+ ftruncateSync(src, 0);
73
+ return true;
74
+ }
75
+ finally {
76
+ closeSync(src);
77
+ }
78
+ }
79
+ /**
80
+ * 로그를 덧붙이기로 연다. 없으면 0600으로 만들고 있으면 권한을 다시 0600으로 좁힌다. 심링크면 따라가지
81
+ * 않고 실패한다. 디렉토리가 0700이라 남이 링크를 걸 수는 없지만 내가 실수로 둔 링크로 남의 파일을 쓰지
82
+ * 않게 한다
83
+ */
84
+ export function openDaemonLog(path) {
85
+ const fd = openSync(path, constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | constants.O_NOFOLLOW, 0o600);
86
+ try {
87
+ if (!fstatSync(fd).isFile())
88
+ throw new Error(`peer 로그 자리에 다른 파일이 있어요: ${path}`);
89
+ fchmodSync(fd, 0o600);
90
+ }
91
+ catch (err) {
92
+ closeSync(fd);
93
+ throw err;
94
+ }
95
+ return fd;
96
+ }
97
+ /**
98
+ * 이번 기동의 표시 줄 뒤에서 마지막 몇 줄. 표시 줄이 없으면 끝에서 센다. 데몬 오류에는 릴레이나 팀원이
99
+ * 보낸 글자가 섞일 수 있어서 터미널과 모델에 그대로 내지 않고 줄마다 한 줄 라벨로 정리한다
100
+ */
101
+ export function logTail(path, lines = 20) {
102
+ let text;
103
+ try {
104
+ const fd = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW);
105
+ try {
106
+ const size = fstatSync(fd).size;
107
+ const len = Math.min(size, 64 * 1024);
108
+ const buf = Buffer.alloc(len);
109
+ readSync(fd, buf, 0, len, size - len);
110
+ text = buf.toString('utf8');
111
+ }
112
+ finally {
113
+ closeSync(fd);
114
+ }
115
+ }
116
+ catch {
117
+ return [];
118
+ }
119
+ const at = text.lastIndexOf(MARKER);
120
+ if (at !== -1)
121
+ text = text.slice(text.indexOf('\n', at) + 1);
122
+ return text
123
+ .split('\n')
124
+ .map((l) => plainLabel(l, 300))
125
+ .filter((l) => l !== undefined && l.trim() !== '')
126
+ .slice(-lines);
127
+ }
128
+ /**
129
+ * 자식으로 띄울 명령. 지금 프로세스와 같은 Node와 실행 인자에 같은 스크립트를 주고 `peer daemon`만
130
+ * 붙인다. `pnpm tsx bin/gestalt.ts`로 불렀으면 tsx가 건 `--require`, `--import`가 실행 인자에 들어 있어서
131
+ * 그대로 따라간다. 설치본이면 실행 인자는 비고 스크립트가 `dist/bin/gestalt.js`다. 디버거와 감시 옵션
132
+ * (`DEV_FLAG`)은 데몬에 넘기지 않는다
133
+ */
134
+ export function daemonCommand(argv = process.argv, execArgv = process.execArgv, execPath = process.execPath) {
135
+ const script = argv[1];
136
+ if (!script)
137
+ throw new Error('gestalt 실행 경로를 못 찾았어요');
138
+ const flags = execArgv.filter((a) => !DEV_FLAG.test(a));
139
+ return [execPath, ...flags, script, 'peer', 'daemon'];
140
+ }
141
+ /** 소켓에 답한 데몬 pid. 안 떠 있거나 시한(기본 1초) 안에 안 답하면 undefined다 */
142
+ export async function answeringDaemonPid(sock, timeoutMs = 1_000) {
143
+ try {
144
+ const res = await request(sock, { op: 'status' }, timeoutMs);
145
+ return res.ok ? res.result.pid : undefined;
146
+ }
147
+ catch {
148
+ return undefined;
149
+ }
150
+ }
151
+ /** 떨어진 데몬이 시한 안에 안 떴을 때. 로그 꼬리를 같이 들고 간다 */
152
+ export class DaemonDetachError extends Error {
153
+ log;
154
+ tail;
155
+ child;
156
+ constructor(message, log, tail,
157
+ /** 띄운 자식 pid. 시한이 지났으면 SIGTERM을 보냈다 */
158
+ child) {
159
+ super(message);
160
+ this.log = log;
161
+ this.tail = tail;
162
+ this.child = child;
163
+ this.name = 'DaemonDetachError';
164
+ }
165
+ }
166
+ function sleep(ms) {
167
+ return new Promise((r) => setTimeout(r, ms));
168
+ }
169
+ /**
170
+ * 자식에 넘길 환경. 부른 셸의 환경을 그대로 물려주되 세 가지만 바꾼다. 루트는 부모가 쓴 값으로 고정한다.
171
+ * 부른 Claude Code 세션 표시(`CLAUDE_PID`, `CLAUDE_CODE_SESSION_ID`)는 뺀다. 데몬은 그 세션보다 오래 살아서
172
+ * 그 값이 곧 틀린 값이 된다. `NODE_OPTIONS`에서는 실행 인자처럼 `DEV_FLAG`에 걸리는 옵션을 뺀다.
173
+ *
174
+ * 허용 목록으로 좁히지 않는 건 데몬이 `CLAUDE_CONFIG_DIR`, `CODEX_HOME`, `HOME`, CA 설정 같은 값으로 세션과
175
+ * 릴레이를 찾기 때문이다. 빠뜨리면 다른 설정 디렉토리를 보고 조용히 엉뚱하게 돈다
176
+ */
177
+ export function detachedEnv(env, root) {
178
+ const out = { ...env, GESTALT_PEER_HOME: root, [DETACHED_ENV]: '1' };
179
+ delete out['CLAUDE_PID'];
180
+ delete out['CLAUDE_CODE_SESSION_ID'];
181
+ const nodeOptions = out['NODE_OPTIONS'];
182
+ if (nodeOptions !== undefined) {
183
+ const kept = nodeOptions
184
+ .split(/\s+/)
185
+ .filter((t) => t !== '' && !DEV_FLAG.test(t))
186
+ .join(' ');
187
+ if (kept === '')
188
+ delete out['NODE_OPTIONS'];
189
+ else
190
+ out['NODE_OPTIONS'] = kept;
191
+ }
192
+ return out;
193
+ }
194
+ export function assertDetachSupported(platform = process.platform) {
195
+ // 데몬이 유닉스 소켓과 0700 디렉토리 권한에 기대고 훅도 bash다. Windows에서는 데몬 자체가 안 돈다
196
+ if (platform === 'win32') {
197
+ throw new Error('peer 데몬은 macOS와 Linux에서만 떠요. Windows는 지원하지 않아요');
198
+ }
199
+ }
200
+ /**
201
+ * 데몬을 이 프로세스와 떨어진 새 프로세스 세션으로 띄우고 소켓이 답할 때까지 기다린다.
202
+ *
203
+ * 이미 떠 있는지는 소켓 답으로 본다. 둘이 동시에 불러 둘 다 자식을 띄워도 잠금(`peer.lock`)을 하나만
204
+ * 잡으므로 데몬은 하나다. 진 자식은 "이미 떠 있어요"로 끝나고 그 부모는 이긴 데몬의 pid를 `already`로
205
+ * 받는다. 시한이 지나면 아직 살아 있는 내 자식에 SIGTERM을 보내고 로그 꼬리와 함께 던진다. 늦게라도
206
+ * 뜬 데몬이 실패 보고 뒤에 남지 않게 하려는 것이다.
207
+ */
208
+ export async function detachDaemon(options) {
209
+ assertDetachSupported();
210
+ const { root } = options;
211
+ const waitMs = options.waitMs ?? DEFAULT_DAEMON_WAIT_MS;
212
+ ensurePrivateDir(root);
213
+ const sock = socketPath(root);
214
+ const log = daemonLogPath(root);
215
+ const running = await answeringDaemonPid(sock);
216
+ if (running !== undefined)
217
+ return { pid: running, log, already: true };
218
+ // 로그 크기 챙기기는 곁다리다. 실패해도 띄우고 이유만 돌려준다. 아래 openDaemonLog가 심링크는 따로 막는다
219
+ let rotateError;
220
+ try {
221
+ rotateDaemonLog(log);
222
+ }
223
+ catch (err) {
224
+ rotateError = err instanceof Error ? err.message : String(err);
225
+ }
226
+ const [cmd, ...args] = options.command ?? daemonCommand();
227
+ if (!cmd)
228
+ throw new Error('띄울 명령이 비었어요');
229
+ const fd = openDaemonLog(log);
230
+ let child;
231
+ try {
232
+ writeSync(fd, `${MARKER} ${new Date().toISOString()} ===\n`);
233
+ child = spawn(cmd, args, {
234
+ detached: true,
235
+ stdio: ['ignore', fd, fd],
236
+ // 데몬은 부른 워크트리보다 오래 산다. 그 디렉토리를 붙잡지 않게 데몬 루트에서 띄운다
237
+ cwd: root,
238
+ env: detachedEnv(options.env ?? process.env, root),
239
+ });
240
+ }
241
+ finally {
242
+ // 자식이 제 사본을 들고 있다. 부모 것은 닫아야 부모가 끝날 때 붙잡는 게 없다
243
+ closeSync(fd);
244
+ }
245
+ child.unref();
246
+ let exited = false;
247
+ let spawnError;
248
+ child.once('exit', () => {
249
+ exited = true;
250
+ });
251
+ child.once('error', (err) => {
252
+ spawnError = err;
253
+ exited = true;
254
+ });
255
+ const fail = (message) => {
256
+ throw new DaemonDetachError(message, log, logTail(log), child.pid);
257
+ };
258
+ const deadline = Date.now() + waitMs;
259
+ while (Date.now() < deadline) {
260
+ // 묻는 시한을 남은 시간으로 줄여 --wait를 넘기지 않는다
261
+ const pid = await answeringDaemonPid(sock, Math.max(1, Math.min(1_000, deadline - Date.now())));
262
+ if (pid !== undefined) {
263
+ // 자식이 곧 데몬이라는 가정이다(DetachOptions.command). 다르면 다른 데몬이 잠금을 먼저 잡은 것이다
264
+ return {
265
+ pid,
266
+ log,
267
+ already: pid !== child.pid,
268
+ ...(child.pid ? { spawned: child.pid } : {}),
269
+ ...(rotateError !== undefined ? { rotateError } : {}),
270
+ };
271
+ }
272
+ if (spawnError)
273
+ fail(`peer 데몬을 못 띄웠어요: ${spawnError.message}`);
274
+ if (exited) {
275
+ // 다른 데몬이 잠금을 쥐고 뜨는 중이면 그 소켓을 마저 기다린다
276
+ const holder = readLockPid(root);
277
+ if (holder === undefined || holder === child.pid || !processAlive(holder)) {
278
+ fail('peer 데몬이 뜨다가 끝났어요');
279
+ }
280
+ }
281
+ await sleep(POLL_MS);
282
+ }
283
+ if (!exited && child.pid !== undefined) {
284
+ try {
285
+ process.kill(child.pid, 'SIGTERM');
286
+ }
287
+ catch {
288
+ // 그새 끝났다
289
+ }
290
+ }
291
+ const holder = readLockPid(root);
292
+ const secs = Math.round(waitMs / 100) / 10;
293
+ if (exited && holder !== undefined && holder !== child.pid && processAlive(holder)) {
294
+ fail(`peer 데몬이 ${secs}초 안에 안 떴어요. 잠금(${lockPath(root)})을 쥔 pid ${holder}가 소켓에 답하지 않아요`);
295
+ }
296
+ return fail(`peer 데몬이 ${secs}초 안에 안 떴어요`);
297
+ }
298
+ /**
299
+ * 데몬에 SIGTERM을 보내고 끝나길 기다린다. 신호를 보내기 전에 소켓에 답한 데몬 pid와 잠금 파일의 pid가
300
+ * 같은지 본다. 잠금 pid만 믿으면 데몬이 죽고 그 pid를 받은 다른 프로세스를 끌 수 있다. 소켓 답만 믿지
301
+ * 않는 건 잠금을 안 쥔 프로세스가 소켓 자리에 답하는 경우를 막으려는 것이다.
302
+ *
303
+ * 데몬의 SIGTERM 처리는 옵션 없이 띄운 `peer daemon`의 Ctrl+C와 같다. 정리 중에 신호를 한 번 더 받으면 기다리지 않고
304
+ * 끝난다. 시한 안에 안 끝나면 그 pid를 알려 주고 실패한다. `--stop`을 다시 불러도 소켓은 이미 닫혀 있어서
305
+ * 신호를 안 보낸다.
306
+ */
307
+ export async function stopDaemon(options) {
308
+ const { root } = options;
309
+ const waitMs = options.waitMs ?? DEFAULT_DAEMON_WAIT_MS;
310
+ const pid = await answeringDaemonPid(socketPath(root));
311
+ if (pid === undefined) {
312
+ const holder = readLockPid(root);
313
+ return holder !== undefined && processAlive(holder)
314
+ ? { pid: null, stopped: false, lockPid: holder }
315
+ : { pid: null, stopped: false };
316
+ }
317
+ const holder = readLockPid(root);
318
+ if (holder !== pid) {
319
+ throw new Error(`소켓에 답한 데몬(pid ${pid})과 잠금 파일(${lockPath(root)})의 pid(${holder ?? '없음'})가 달라서 신호를 안 보냈어요`);
320
+ }
321
+ try {
322
+ process.kill(pid, 'SIGTERM');
323
+ }
324
+ catch (err) {
325
+ // 확인한 뒤 그새 끝났다. 바라던 상태다
326
+ if (err.code === 'ESRCH')
327
+ return { pid, stopped: true };
328
+ throw err;
329
+ }
330
+ const deadline = Date.now() + waitMs;
331
+ while (Date.now() < deadline) {
332
+ if (!processAlive(pid))
333
+ return { pid, stopped: true };
334
+ await sleep(POLL_MS);
335
+ }
336
+ const secs = Math.round(waitMs / 100) / 10;
337
+ throw new Error(`peer 데몬(pid ${pid})이 ${secs}초 안에 안 멈췄어요. \`kill ${pid}\`로 신호를 한 번 더 보내면 정리를 기다리지 않고 끝나요`);
338
+ }
339
+ //# sourceMappingURL=detach.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detach.js","sourceRoot":"","sources":["../../../src/peer/detach.ts"],"names":[],"mappings":"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"}
@@ -36,6 +36,21 @@ export declare function isSessionId(value: string): boolean;
36
36
  export declare function readSessionFile(path: string): SessionRecord | null;
37
37
  /** 부모 pid로 세션을 찾는다. MCP 서버처럼 세션의 자식이 쓴다 */
38
38
  export declare function findSessionByPid(pid: number, configDir?: string): SessionRecord | null;
39
+ /** pid의 부모 pid. 못 읽었거나 init(1)이면 undefined */
40
+ export declare function parentPid(pid: number): number | undefined;
41
+ export interface AncestorLookup {
42
+ /** 몇 대 위까지 볼지. `npx`나 셸이 여러 겹 끼어도 세션까지 닿을 만큼 둔다 */
43
+ maxDepth?: number;
44
+ env?: NodeJS.ProcessEnv;
45
+ /** 테스트가 ps 대신 넣는다 */
46
+ parentOf?: (pid: number) => number | undefined;
47
+ }
48
+ /**
49
+ * startPid부터 부모를 따라 올라가며 `sessions/<pid>.json`이 있는 첫 세션을 찾는다. Bash 도구로 띄운
50
+ * `gestalt digest serve`처럼 세션과 사이에 셸이 몇 겹 낀 프로세스가 쓴다. Claude Code가 자식에게 주는
51
+ * `CLAUDE_PID`가 있으면 그걸 먼저 본다. pid 1에 닿거나 같은 pid를 다시 만나면 멈춘다.
52
+ */
53
+ export declare function findSessionInAncestors(startPid: number, configDir?: string, opts?: AncestorLookup): SessionRecord | null;
39
54
  /**
40
55
  * 명령을 친 Claude Code 세션의 id. Bash 도구가 띄운 셸은 `CLAUDE_PID`와 `CLAUDE_CODE_SESSION_ID`를 물려받는다.
41
56
  * `/clear`나 다시 이어 받기로 세션 id가 바뀌면 `sessions/<pid>.json`이 따라 바뀌므로 그쪽을 먼저 본다.
@@ -1 +1 @@
1
- {"version":3,"file":"locate.d.ts","sourceRoot":"","sources":["../../../src/peer/locate.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9E;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzE,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,2DAA2D;AAC3D,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAI5E;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE3C;AAKD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,kDAAkD;AAClD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAgBlE;AAED,2CAA2C;AAC3C,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,SAAoB,GAAG,aAAa,GAAG,IAAI,CAGjG;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,SAAS,SAAuB,EAChC,KAAK,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAiB,GACxC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAajE;AAYD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAc1F;AAED,mDAAmD;AACnD,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,EAAE,CAY/D;AAUD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,SAAoB,GAAG,YAAY,CAoC/F"}
1
+ {"version":3,"file":"locate.d.ts","sourceRoot":"","sources":["../../../src/peer/locate.ts"],"names":[],"mappings":"AAKA;;;;;;GAMG;AAEH,MAAM,MAAM,YAAY,GACpB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9E;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzE,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,2DAA2D;AAC3D,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAI5E;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE3C;AAKD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,kDAAkD;AAClD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAgBlE;AAED,2CAA2C;AAC3C,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,SAAoB,GAAG,aAAa,GAAG,IAAI,CAGjG;AAED,8CAA8C;AAC9C,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAYzD;AAED,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAChD;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,SAAS,SAAoB,EAC7B,IAAI,GAAE,cAAmB,GACxB,aAAa,GAAG,IAAI,CAkBtB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,SAAS,SAAuB,EAChC,KAAK,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAiB,GACxC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAajE;AAYD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAc1F;AAED,mDAAmD;AACnD,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,EAAE,CAY/D;AAUD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,SAAoB,GAAG,YAAY,CAoC/F"}
@@ -1,3 +1,4 @@
1
+ import { execFileSync } from 'node:child_process';
1
2
  import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
2
3
  import { homedir } from 'node:os';
3
4
  import { isAbsolute, join } from 'node:path';
@@ -47,6 +48,48 @@ export function findSessionByPid(pid, configDir = claudeConfigDir()) {
47
48
  return null;
48
49
  return readSessionFile(join(configDir, 'sessions', `${pid}.json`));
49
50
  }
51
+ /** pid의 부모 pid. 못 읽었거나 init(1)이면 undefined */
52
+ export function parentPid(pid) {
53
+ try {
54
+ const out = execFileSync('ps', ['-o', 'ppid=', '-p', String(pid)], {
55
+ encoding: 'utf8',
56
+ stdio: ['ignore', 'pipe', 'ignore'],
57
+ timeout: 500,
58
+ });
59
+ const n = Number(out.trim());
60
+ return Number.isInteger(n) && n > 1 ? n : undefined;
61
+ }
62
+ catch {
63
+ return undefined;
64
+ }
65
+ }
66
+ /**
67
+ * startPid부터 부모를 따라 올라가며 `sessions/<pid>.json`이 있는 첫 세션을 찾는다. Bash 도구로 띄운
68
+ * `gestalt digest serve`처럼 세션과 사이에 셸이 몇 겹 낀 프로세스가 쓴다. Claude Code가 자식에게 주는
69
+ * `CLAUDE_PID`가 있으면 그걸 먼저 본다. pid 1에 닿거나 같은 pid를 다시 만나면 멈춘다.
70
+ */
71
+ export function findSessionInAncestors(startPid, configDir = claudeConfigDir(), opts = {}) {
72
+ const env = opts.env ?? process.env;
73
+ const parentOf = opts.parentOf ?? parentPid;
74
+ const fromEnv = Number(env['CLAUDE_PID']);
75
+ if (Number.isInteger(fromEnv) && fromEnv > 1) {
76
+ const hit = findSessionByPid(fromEnv, configDir);
77
+ if (hit)
78
+ return hit;
79
+ }
80
+ const seen = new Set();
81
+ let pid = startPid;
82
+ for (let depth = 0; depth <= (opts.maxDepth ?? 8); depth++) {
83
+ if (pid === undefined || !Number.isInteger(pid) || pid <= 1 || seen.has(pid))
84
+ return null;
85
+ seen.add(pid);
86
+ const hit = findSessionByPid(pid, configDir);
87
+ if (hit)
88
+ return hit;
89
+ pid = parentOf(pid);
90
+ }
91
+ return null;
92
+ }
50
93
  /**
51
94
  * 명령을 친 Claude Code 세션의 id. Bash 도구가 띄운 셸은 `CLAUDE_PID`와 `CLAUDE_CODE_SESSION_ID`를 물려받는다.
52
95
  * `/clear`나 다시 이어 받기로 세션 id가 바뀌면 `sessions/<pid>.json`이 따라 바뀌므로 그쪽을 먼저 본다.
@@ -1 +1 @@
1
- {"version":3,"file":"locate.js","sourceRoot":"","sources":["../../../src/peer/locate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"locate.js","sourceRoot":"","sources":["../../../src/peer/locate.ts"],"names":[],"mappings":"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"}
@@ -29,4 +29,10 @@ export declare function lockPath(root: string): string;
29
29
  export declare function acquireDaemonLock(root: string, sock: string): Promise<DaemonLock>;
30
30
  /** 내 잠금일 때만 지운다. 이미 다른 데몬이 그 자리를 잡았으면 안 건드린다 */
31
31
  export declare function releaseDaemonLock(lock: DaemonLock): void;
32
+ /**
33
+ * 잠금 파일에 적힌 pid. 파일이 없거나 pid 꼴이 아니면 undefined다. `peer daemon --detach`와 `--stop`이
34
+ * 소켓 답과 맞춰 볼 때 쓴다. 잠금을 쥐거나 치우지는 않는다
35
+ */
36
+ export declare function readLockPid(root: string): number | undefined;
37
+ export declare function processAlive(pid: number): boolean;
32
38
  //# sourceMappingURL=lock.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../../src/peer/lock.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,QAAS,CAAC;AAEpC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAqBvF;AAED,gDAAgD;AAChD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CASxD"}
1
+ {"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../../src/peer/lock.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,QAAS,CAAC;AAEpC,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAqBvF;AAED,gDAAgD;AAChD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CASxD;AAkDD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAU5D;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQjD"}
@@ -116,7 +116,23 @@ async function clearStaleLock(path, sock) {
116
116
  }
117
117
  unlinkSync(aside);
118
118
  }
119
- function processAlive(pid) {
119
+ /**
120
+ * 잠금 파일에 적힌 pid. 파일이 없거나 pid 꼴이 아니면 undefined다. `peer daemon --detach`와 `--stop`이
121
+ * 소켓 답과 맞춰 볼 때 쓴다. 잠금을 쥐거나 치우지는 않는다
122
+ */
123
+ export function readLockPid(root) {
124
+ let text;
125
+ try {
126
+ text = readFileSync(lockPath(root), 'utf8');
127
+ }
128
+ catch {
129
+ return undefined;
130
+ }
131
+ const line = text.split('\n')[0] ?? '';
132
+ const pid = Number(line);
133
+ return line !== '' && Number.isSafeInteger(pid) && pid > 0 ? pid : undefined;
134
+ }
135
+ export function processAlive(pid) {
120
136
  try {
121
137
  process.kill(pid, 0);
122
138
  return true;
@@ -1 +1 @@
1
- {"version":3,"file":"lock.js","sourceRoot":"","sources":["../../../src/peer/lock.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lock.js","sourceRoot":"","sources":["../../../src/peer/lock.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tienne/gestalt",
3
- "version": "0.115.0",
3
+ "version": "0.117.0",
4
4
  "description": "TypeScript AI Development Harness - Gestalt psychology-driven requirement clarification",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gestalt",
3
- "version": "0.115.0",
3
+ "version": "0.117.0",
4
4
  "description": "Gestalt psychology-driven AI development harness. Transforms scattered requirements into structured, validated specifications through interactive interviews.",
5
5
  "author": {
6
6
  "name": "tienne"
package/plugin/.mcp.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "gestalt": {
4
4
  "command": "npx",
5
- "args": ["-y", "@tienne/gestalt@0.115.0", "serve"],
5
+ "args": ["-y", "@tienne/gestalt@0.117.0", "serve"],
6
6
  "startup_timeout_sec": 180,
7
7
  "tool_timeout_sec": 900
8
8
  }
package/plugin/mcp.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "gestalt": {
4
4
  "command": "npx",
5
- "args": ["-y", "@tienne/gestalt@0.115.0", "serve"],
5
+ "args": ["-y", "@tienne/gestalt@0.117.0", "serve"],
6
6
  "startup_timeout_sec": 180,
7
7
  "tool_timeout_sec": 900
8
8
  }
@@ -28,6 +28,7 @@ You are the Lens Reader role agent.
28
28
  - `source.json` 경로. `tables[]`마다 `id`(`table-4`), `number`, `caption`, `rows`(머리줄을 포함한 칸 글자 그대로), `grid`가 있다. `figures[]`마다 `id`(`figure-1`), `caption`, `image`, `panels`(원문 그림 장면 수, 없을 수 있음)가 있다.
29
29
  - 리포트를 쓸 경로(`report.draft.json`). 스킬이 절대 경로로 넘긴다. 다른 자리에는 쓰지 않는다.
30
30
  - 결과 언어 `lang`. 안 넘겼으면 `ko`다.
31
+ - 쉬운 리포트를 쓸 때만 보통 리포트 경로(`report.base.json`)를 함께 받는다. 그때 쓰는 법은 아래 "쉬운 리포트로 풀어 쓸 때" 절에 있다.
31
32
 
32
33
  맥락 카드와 노트 연결 카드는 이 에이전트가 쓰지 않는다. 리포트가 merge를 통과한 뒤 `lens-context`가 맥락 카드를, `lens-link`가 연결 카드를 따로 쓰고 스킬이 `gestalt lens attach`로 붙인다. 이 리포트에는 `cards`와 `links`를 넣지 않는다.
33
34
 
@@ -249,6 +250,26 @@ video-digest 리포트와 같은 꼴에 렌즈 칸을 더한다. 영상 칸 `fra
249
250
  - "주소", "배달 기능"처럼 일상어는 고르지 않는다. 조사가 붙은 말("캔버스에서")도 고르지 않는다. 그 분야 사람이 아니면 모를 말(CSP, NMI, DIFUSCO)만 고른다.
250
251
  - 본문 문장에서 `{{kw:<id>|표시어}}`로 적는다. id는 `keywords`에 있어야 한다.
251
252
 
253
+ ## 쉬운 리포트로 풀어 쓸 때
254
+
255
+ 스킬이 보통 리포트 경로를 같이 넘기면 원문을 처음부터 다시 읽어 쓰지 않는다. 보통 리포트를 바탕으로 `difficulty: easy` 리포트 한 벌을 쓴다. 뷰어의 쉽게 보기 토글이 두 리포트를 오간다. 뼈대를 같게 두면 출처 칩이 같은 문단을 열고 보통 리포트에서 merge로 확인한 의심 표시와 표 칸도 그대로 쓴다.
256
+
257
+ - `options`는 보통 리포트 것을 그대로 옮기고 `difficulty`만 `easy`로 바꾼다.
258
+ - 대섹션과 소섹션의 `id`와 `cite`, `skipped`는 그대로 옮긴다. 소섹션 `tables`와 `figures`는 `ref`를 그대로 두고 `note`만 쉬운 말로 바꾼다. 인터랙티브 그림(`widgets`)은 통째로 그대로 옮긴다.
259
+ - 제목과 장 도입(`intro`), 결론, 불릿, 도입 세 문장, 한눈에 보기 칸의 `text`를 풀어 쓴다. 전문 용어는 처음 나올 때 한 번 풀어 주고 문장을 짧게 끊는다.
260
+ - 1단 불릿 수는 계층 규칙 범위를 지킨다. 풀어 쓴 설명이 길어지면 2단 불릿으로 내린다.
261
+ - 불릿을 나누거나 새로 쓰면 그 문장이 기댄 문단 범위로 `cite`를 단다. 범위는 원문 문단을 다시 읽어 확인한다. 보통 리포트의 출처를 짐작으로 옮겨 붙이지 않는다.
262
+ - 키워드는 `id`와 `term`, `firstCite`를 그대로 두고 `explanation`만 풀어 쓴다. 본문의 `{{kw:}}` id도 보통 리포트와 같게 둔다.
263
+ - 대섹션 도식은 라벨만 쉬운 말로 바꿔 옮긴다. 쉬운 리포트는 대섹션마다 도식 하나를 권하니 도식이 없는 대섹션에 단계나 견주기가 있으면 더한다.
264
+ - 보통 리포트에 없는 내용을 더하지 않고 있는 내용을 빼지도 않는다.
265
+
266
+ 렌즈 칸은 쉬운 말로 바꿔도 근거가 흔들리면 안 된다. 아래를 더 지킨다.
267
+
268
+ - 의심 표시(`doubt`)는 새로 달거나 빼지 않는다. 달려 있던 불릿에 그대로 단다. 불릿을 나누면 원문 주장을 옮긴 쪽 불릿에 단다.
269
+ - `doubt.note`와 한계 단락(`limits`)의 `text`는 말만 풀어 쓴다. 숫자는 보통 리포트에 적힌 원문 꼴 그대로 옮긴다. `0.2862`를 `0.29`나 "약 0.3"으로 줄이지 않고 숫자를 더하거나 빼지 않는다. "0.04 떨어진다"처럼 차이를 계산해 넣지도 않는다. merge가 보통 리포트와 같은 대조를 돌려 `DOUBT_NUMBER_UNKNOWN`, `LIMIT_NUMBER_UNKNOWN`으로 막는다.
270
+ - 의심 표시의 `evidence`와 `direction`, 한계 줄의 `evidence`, 한눈에 보기 칸의 `kind`와 `cite`는 글자 하나 바꾸지 않고 옮긴다. 표 칸 출처(`{ "table", "row", "col" }`)를 다른 칸으로 옮기지 않는다.
271
+ - `cards`와 `links`, `card`가 달린 한계 줄은 쓰지 않는다. 스킬이 보통 리포트의 카드를 그대로 붙인다.
272
+
252
273
  ## 문체 규칙
253
274
 
254
275
  - 원문이 영어여도 리포트는 `options.lang`(기본 한국어)으로 쓴다.
@@ -263,7 +284,7 @@ video-digest 리포트와 같은 꼴에 렌즈 칸을 더한다. 영상 칸 `fra
263
284
 
264
285
  ## 끝내기 전
265
286
 
266
- 리포트를 쓴 뒤 스킬이 `gestalt digest merge`로 합치며 검사한다. 오류 목록을 돌려받으면 `path`가 가리키는 자리만 고쳐 다시 쓴다. path 앞의 `reports.<n>.`은 합친 뒤의 자리라 리포트 파일에서는 그 뒤부터 찾는다. 숫자 오류(`DOUBT_NUMBER_UNKNOWN`, `LIMIT_NUMBER_UNKNOWN`)는 `source.json`의 그 칸을 다시 열어 원문 꼴로 고친다. 계산한 값이면 지운다.
287
+ 리포트를 쓴 뒤 스킬이 `gestalt digest merge`로 합치며 검사한다. 오류 목록을 돌려받으면 `path`가 가리키는 자리만 고쳐 다시 쓴다. path 앞의 `reports.<n>.`은 합친 뒤의 자리라 리포트 파일에서는 그 뒤부터 찾는다. 숫자 오류(`DOUBT_NUMBER_UNKNOWN`, `LIMIT_NUMBER_UNKNOWN`)는 `source.json`의 그 칸을 다시 열어 원문 꼴로 고친다. 계산한 값이면 지운다. 쉬운 리포트에서 나온 숫자 오류는 보통 리포트의 같은 자리 숫자를 그대로 옮겨 고친다.
267
288
 
268
289
  ## Output Format
269
290