Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions FALSE-POSITIVES.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
| `write-return-value-is-read` | 쓰기만 하는 컬렉션 | `if (skipExit.delete(node)) return` — `delete` 는 있었는지를 돌려주고 그 불리언이 곧 조회다 | tailwind | 값이 버려지는 호출(`ExpressionStatement`)일 때만 쓰기로 센다 | `write-only-collection.ts` |
| `same-name-twice` | 쓰기만 하는 컬렉션 | 다른 스코프의 동명 변수를 한 덩어리로 봤다 | 코퍼스 검증 | 같은 이름이 두 번 선언되면 그 이름은 통째로 포기(미탐을 산다) | `write-only-collection.ts` |
| `write-only-read-commented-out` | 쓰기만 하는 컬렉션 | 읽는 코드를 주석으로 꺼 둔 자리 — 지우자는 PR 은 다시 켤 계획으로 닫힌다 | react devtools `fiber/renderer.js:792` `hideElementsWithPaths` (`/* DISABLED: …/pull/28417 */`, 10-09) | 같은 파일 주석 안에 `이름.size/has/get/forEach…`·`of 이름` 이 있으면 제외 | `write-only-collection.ts` |
| `write-only-gc-retention` | 쓰기만 하는 컬렉션 | 객체가 수거되지 않게 참조만 들고 있는 보관용 Set — 읽지 않는 게 정상이다(Electron `Notification` 은 참조를 잃으면 수거돼 클릭 핸들러가 사라진다) | cindy `desktop/src/main/notificationService.ts:101` `liveNotifications` · oh-my-pi `coding-agent/src/exec/bash-executor.ts:208` `retainedShells` (10-10 사냥터) | 이름이 retain·alive·live*·hold·pinned 류면 제외 | `write-only-collection.ts` |
| `awaited-custom-foreach` | forEach 안 await | `await x.forEach(async …)` 는 프라미스를 돌려주는 자체 forEach 라 기다린다 | crawlee `dataset.ts:572` `Dataset.forEach` (10-07) | forEach 호출 자체가 `await` 되면 제외 | `await-in-foreach.ts` |
| `floating-other-class-member` | floating promise | `this.x()` 의 x 를 같은 파일 다른 클래스의 async x 로 오인 | mastra `agent-controller/session.ts:831` `SessionThread.set` (10-08) | 감싸는 클래스가 x 를 직접 선언했으면 그 선언의 async 여부로 판정 | `floating-promise.ts` |
| `floating-benign-callee` | floating promise | 버려도 잃는 게 없는 async 함수 — 자기 본문에 await 가 없거나 본문 전체가 catch 있는 try 하나 | slidev `saveSnapshot` · Trilium `openInWindowCommand` · serverless `#streamContainerLogs` · kilocode `optimizeTable` (10-08) | 같은 이름의 선언이 전부 무해하면 제외 | `floating-promise.ts` |
Expand Down
3 changes: 3 additions & 0 deletions bin/fixearly.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2397,6 +2397,9 @@ function collectWriteOnly(ts, sf, file, lineOf, out) {
if (reads.has(name)) continue; // 한 군데라도 읽으면 아니다
if (new RegExp(`\\b${name}\\s*(\\.(size|has|get|forEach|keys|values|entries)\\b|\\))|\\bof\\s+${name}\\b`).test(commented)) continue;
if (!writes.has(name)) continue; // 만들기만 하고 안 건드리는 건 다른 문제(미사용 변수)
// [FP:write-only-gc-retention] 객체가 수거되지 않게 참조만 들고 있는 보관용 컬렉션이다 — 읽지 않는 게 정상이다.
// Electron Notification 은 참조를 잃으면 수거돼 클릭 핸들러가 사라진다(cindy `liveNotifications`), oh-my-pi `retainedShells`.
if (/retain|alive|keepalive|^live[A-Z]|hold|pinned|strongRef/i.test(name)) continue;
out.push({ file, line: lineOf(d.node), name, ctor: d.ctor, writes: writes.get(name) });
}
}
Expand Down
2 changes: 1 addition & 1 deletion bin/selftest.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ if (generatedSrc) {
key: "writeOnlyCollection",
label: "쓰기만 하는 컬렉션",
hit: ["seen", "audit"],
miss: ["known", "bag", "passed", "built", "registry", "later", "skip", "chained", "parked"],
miss: ["known", "bag", "passed", "built", "registry", "later", "skip", "chained", "parked", "liveNotifications"],
// 출력 줄: ` seen = new Set() — ...`
namePattern: /^\s{4}([A-Za-z_$][\w$]*) = new (?:Map|Set)\(\)/gm,
},
Expand Down
3 changes: 2 additions & 1 deletion data/repo-gates.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"pinojs/pino": "게이트 0 — CONTRIBUTING: 사람 없는 순수 AI 기여 거절 (2026-10-09 확인)",
"langgenius/dify": "게이트 0 — CONTRIBUTING: 문제·해법·테스트 결과를 '자기 말로' 쓰라 · 에이전트 PR 은 'From <Tool>' 표기 (2026-10-09 확인)",
"styled-components/styled-components": "AGENTS.md: PR·커밋에 'Generated by'·귀속 꼬리말 금지 — 세션 링크 뺀다",
"facebook/lexical": "AGENTS.md: 에이전트 세션 URL 금지 — 세션 링크 뺀다"
"facebook/lexical": "AGENTS.md: 에이전트 세션 URL 금지 — 세션 링크 뺀다",
"can1357/oh-my-pi": "게이트 0 — CONTRIBUTING 'Pull request requirements': PR 본문에 제출자가 직접 쓴 문장 1개 이상 필수 · 변경 경로를 직접 실행해 재현·확인 보고 필수 · 관련 없는 정리·곁가지 리팩터 금지 · 외부 PR 은 '시험 개방' 중(vouch 제도 복귀 가능). 사람 확인 없이는 못 낸다 (10-10, 후보 seenNames·openToolCalls 쓰기만)"
}
}
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ <h1 class="en">Rules strangers merged.<br>The lines to fix in yours.</h1>
</div>
<div class="heroart">
<div class="glow"></div>
<div class="loopfig"><!--auto:loop--><img src="loop.jpg" width="900" height="900" alt="" loading="eager"><span class="lc c1"><i class="lpn">1</i><span class="ko">배운다 · 고칠 규칙</span><span class="en">Learn · fix rules</span><b>6</b></span><span class="lc c2"><i class="lpn">2</i><span class="ko">고친다 · PR</span><span class="en">Fix · PRs</span><b>84</b></span><span class="lc c3"><i class="lpn">3</i><span class="ko">판정 · 머지</span><span class="en">Verdict · merged</span><b>36</b></span><span class="lc c4"><i class="lpn">4</i><span class="ko">다진다 · 오탐 가드</span><span class="en">Sharpen · FP guards</span><b>44</b></span><div class="lcen"><svg viewBox="0 0 140 140" aria-hidden="true"><circle r="60" cx="70" cy="70" class="trk"/><circle r="60" cx="70" cy="70" stroke="#2563eb" stroke-dasharray="154.08 376.99" stroke-dashoffset="-0.00" style="--d:0.00s"><title>쓰기만 하는 컬렉션 15</title></circle><circle r="60" cx="70" cy="70" stroke="#0f7a63" stroke-dasharray="122.66 376.99" stroke-dashoffset="-157.08" style="--d:0.12s"><title>O(n²) 조회 12</title></circle><circle r="60" cx="70" cy="70" stroke="#60a5fa" stroke-dasharray="38.89 376.99" stroke-dashoffset="-282.74" style="--d:0.24s"><title>불필요한 순차 I/O 4</title></circle><circle r="60" cx="70" cy="70" stroke="#d97706" stroke-dasharray="17.94 376.99" stroke-dashoffset="-324.63" style="--d:0.36s"><title>버려진 Promise 2</title></circle><circle r="60" cx="70" cy="70" stroke="#7c8899" stroke-dasharray="17.94 376.99" stroke-dashoffset="-345.58" style="--d:0.48s"><title>버린 반환값 2</title></circle><circle r="60" cx="70" cy="70" stroke="#a78bfa" stroke-dasharray="7.47 376.99" stroke-dashoffset="-366.52" style="--d:0.60s"><title>전역 정규식 상태 1</title></circle></svg><div class="lnum"><b>36</b><span class="ko">PR 머지됨</span><span class="en">PRs merged</span><em><span class="ko">규칙 6개가 찾아냄</span><span class="en">found by 6 rules</span></em></div></div><p class="lcap"><span class="lleg"><span class="ko"><span><i style="background:#2563eb"></i>쓰기만 하는 컬렉션 15</span><span><i style="background:#0f7a63"></i>O(n²) 조회 12</span><span><i style="background:#60a5fa"></i>불필요한 순차 I/O 4</span><span><i style="background:#d97706"></i>버려진 Promise 2</span><span><i style="background:#7c8899"></i>버린 반환값 2</span><span><i style="background:#a78bfa"></i>전역 정규식 상태 1</span></span><span class="en"><span><i style="background:#2563eb"></i>Write-only collection 15</span><span><i style="background:#0f7a63"></i>O(n²) lookup 12</span><span><i style="background:#60a5fa"></i>Needless sequential I/O 4</span><span><i style="background:#d97706"></i>Floating promise 2</span><span><i style="background:#7c8899"></i>Discarded pure call 2</span><span><i style="background:#a78bfa"></i>Stateful /g regex 1</span></span></span><span class="ko">남의 저장소에서 머지된 PR 과 남의 코드에서 고칠 규칙을 뽑고, 그 규칙으로 다른 저장소를 고쳐 PR 을 낸다. 머지·거절이 다시 규칙을 다듬는다 — 규칙 6개 중 6개가 머지로 검증 · 저장소 26곳 · 거절 26 · 대기 22. </span><span class="en">Fix rules come from PRs strangers merged and from strangers' code; we apply them to other repos as PRs, and merges and rejections sharpen them again — 6 of 6 rules verified by a merge · 26 projects · closed 26 · open 22. </span><a href="#impact"><span class="ko">전체 기록 →</span><span class="en">Full record →</span></a></p><!--/auto:loop--></div>
<div class="loopfig"><!--auto:loop--><img src="loop.jpg" width="900" height="900" alt="" loading="eager"><span class="lc c1"><i class="lpn">1</i><span class="ko">배운다 · 고칠 규칙</span><span class="en">Learn · fix rules</span><b>6</b></span><span class="lc c2"><i class="lpn">2</i><span class="ko">고친다 · PR</span><span class="en">Fix · PRs</span><b>84</b></span><span class="lc c3"><i class="lpn">3</i><span class="ko">판정 · 머지</span><span class="en">Verdict · merged</span><b>36</b></span><span class="lc c4"><i class="lpn">4</i><span class="ko">다진다 · 오탐 가드</span><span class="en">Sharpen · FP guards</span><b>45</b></span><div class="lcen"><svg viewBox="0 0 140 140" aria-hidden="true"><circle r="60" cx="70" cy="70" class="trk"/><circle r="60" cx="70" cy="70" stroke="#2563eb" stroke-dasharray="154.08 376.99" stroke-dashoffset="-0.00" style="--d:0.00s"><title>쓰기만 하는 컬렉션 15</title></circle><circle r="60" cx="70" cy="70" stroke="#0f7a63" stroke-dasharray="122.66 376.99" stroke-dashoffset="-157.08" style="--d:0.12s"><title>O(n²) 조회 12</title></circle><circle r="60" cx="70" cy="70" stroke="#60a5fa" stroke-dasharray="38.89 376.99" stroke-dashoffset="-282.74" style="--d:0.24s"><title>불필요한 순차 I/O 4</title></circle><circle r="60" cx="70" cy="70" stroke="#d97706" stroke-dasharray="17.94 376.99" stroke-dashoffset="-324.63" style="--d:0.36s"><title>버려진 Promise 2</title></circle><circle r="60" cx="70" cy="70" stroke="#7c8899" stroke-dasharray="17.94 376.99" stroke-dashoffset="-345.58" style="--d:0.48s"><title>버린 반환값 2</title></circle><circle r="60" cx="70" cy="70" stroke="#a78bfa" stroke-dasharray="7.47 376.99" stroke-dashoffset="-366.52" style="--d:0.60s"><title>전역 정규식 상태 1</title></circle></svg><div class="lnum"><b>36</b><span class="ko">PR 머지됨</span><span class="en">PRs merged</span><em><span class="ko">규칙 6개가 찾아냄</span><span class="en">found by 6 rules</span></em></div></div><p class="lcap"><span class="lleg"><span class="ko"><span><i style="background:#2563eb"></i>쓰기만 하는 컬렉션 15</span><span><i style="background:#0f7a63"></i>O(n²) 조회 12</span><span><i style="background:#60a5fa"></i>불필요한 순차 I/O 4</span><span><i style="background:#d97706"></i>버려진 Promise 2</span><span><i style="background:#7c8899"></i>버린 반환값 2</span><span><i style="background:#a78bfa"></i>전역 정규식 상태 1</span></span><span class="en"><span><i style="background:#2563eb"></i>Write-only collection 15</span><span><i style="background:#0f7a63"></i>O(n²) lookup 12</span><span><i style="background:#60a5fa"></i>Needless sequential I/O 4</span><span><i style="background:#d97706"></i>Floating promise 2</span><span><i style="background:#7c8899"></i>Discarded pure call 2</span><span><i style="background:#a78bfa"></i>Stateful /g regex 1</span></span></span><span class="ko">남의 저장소에서 머지된 PR 과 남의 코드에서 고칠 규칙을 뽑고, 그 규칙으로 다른 저장소를 고쳐 PR 을 낸다. 머지·거절이 다시 규칙을 다듬는다 — 규칙 6개 중 6개가 머지로 검증 · 저장소 26곳 · 거절 26 · 대기 22. </span><span class="en">Fix rules come from PRs strangers merged and from strangers' code; we apply them to other repos as PRs, and merges and rejections sharpen them again — 6 of 6 rules verified by a merge · 26 projects · closed 26 · open 22. </span><a href="#impact"><span class="ko">전체 기록 →</span><span class="en">Full record →</span></a></p><!--/auto:loop--></div>
</div>
</div>
</header>
Expand Down
6 changes: 6 additions & 0 deletions tools/fixtures/write-only-collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,9 @@ export function filterFibers(filters: string[]) {
*/
return false;
}

// 수거 방지용 보관 — 읽지 않는 게 정상이다 · cindy notificationService
const liveNotifications = new Set<object>();
export function notify(n: object): void {
liveNotifications.add(n);
}
Loading