Skip to content

fix(wiki,ingest): P83 — wiki 호출이 만든 codex/claude 세션 self-ingest 루프 차단 (#82)#85

Merged
hang-in merged 1 commit into
mainfrom
fix/p83-wiki-self-ingest-loop
May 19, 2026
Merged

fix(wiki,ingest): P83 — wiki 호출이 만든 codex/claude 세션 self-ingest 루프 차단 (#82)#85
hang-in merged 1 commit into
mainfrom
fix/p83-wiki-self-ingest-loop

Conversation

@hang-in
Copy link
Copy Markdown
Owner

@hang-in hang-in commented May 18, 2026

Summary

Issue #82 (dicebattle 보고) 의 wiki self-ingest 루프 차단.

  • wiki::WIKI_INVOCATION_MARKER (<!-- secall:wiki-update -->) 상수 신설.
  • wiki/codex.rs + wiki/claude.rsgenerate() 가 prompt 앞에 marker prefix.
  • ingest::is_noise_session() 에 marker 검출 룰 추가 — 첫 user turn 의 content 에 marker 포함 시 "secall wiki invocation" 사유로 skip.
  • 기존 P49 (SECALL_SUMMARY_PROMPT_PREFIX) 와 동일 메커니즘이라 parser 시그니처 변경 없음.
  • 신규 unit test 3건 (marker at start / in middle / absent).

Why

secall wiki updatecodex exec subprocess → codex CLI 가 ~/.codex/sessions/... 에 새 세션 jsonl 생성 → secall sync 가 그 세션을 일반 사용자 세션과 동일하게 ingest → 다음 wiki 실행 시 그 세션도 분석 대상에 포함 → 무한 wiki 재생성 / 중복 항목. claude 백엔드 (claude -p) 도 동일.

다른 백엔드 (haiku, ollama, lmstudio) 는 HTTP API 라 영향 없음.

조사 결과 기존 ingest/mod.rs::is_noise_session() (P49) 이 이미 tmpdir cwd + SECALL_SUMMARY_PROMPT_PREFIX 검출로 self-ingest 패턴을 차단 중. wiki marker 룰 한 줄 추가만으로 동일 메커니즘 확장 가능.

Test plan

  • cargo fmt --all -- --check clean
  • cargo clippy --workspace --all-targets -- -D warnings clean
  • cargo test -p secall-core --lib ingest:: 110 passed (신규 3건 포함)
  • cargo test --workspace --no-fail-fast all green (lib 421 + integration)

Out of scope

본 PR 머지 전 이미 ingest 된 wiki invocation 세션은 marker 가 없음. 사용자가 secall list --recent + secall archive <id> 또는 ~/.codex/sessions/ 직접 삭제로 수동 정리. 자동 일괄 정리는 별도 fast-follow PR 검토.

Closes #82

🤖 Generated with Claude Code

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements a fix for issue #82 to prevent self-ingest loops during wiki generation by introducing a WIKI_INVOCATION_MARKER. This marker is prepended to prompts in the Claude and Codex backends, and the is_noise_session function is updated to detect it and skip these sessions. Documentation and unit tests for this feature are also included. A review comment suggests improving the consistency of the is_noise_session function by using the trimmed content variable for both the summary prompt and wiki invocation checks.

Comment on lines +62 to 71
let content_trimmed = first_user.content.trim_start();
if content_trimmed.starts_with(SECALL_SUMMARY_PROMPT_PREFIX) {
return Some("secall summary prompt");
}
if first_user
.content
.trim_start()
.starts_with(SECALL_SUMMARY_PROMPT_PREFIX)
.contains(crate::wiki::WIKI_INVOCATION_MARKER)
{
return Some("secall summary prompt");
return Some("secall wiki invocation");
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

is_noise_session 함수 내에서 SECALL_SUMMARY_PROMPT_PREFIXstarts_with를 사용하고, WIKI_INVOCATION_MARKERcontains를 사용하는 등 검사 방식에 차이가 있습니다.

이미 상단에서 content_trimmed를 계산했으므로 두 번째 조건문에서도 이를 활용하여 일관성을 유지하는 것이 좋으며, 만약 백엔드가 시스템 프롬프트를 앞에 붙이는 경우를 대비해 contains를 사용하신 것이라면 SECALL_SUMMARY_PROMPT_PREFIX 또한 동일한 로직을 적용하는 것을 고려해 보시기 바랍니다.

Suggested change
let content_trimmed = first_user.content.trim_start();
if content_trimmed.starts_with(SECALL_SUMMARY_PROMPT_PREFIX) {
return Some("secall summary prompt");
}
if first_user
.content
.trim_start()
.starts_with(SECALL_SUMMARY_PROMPT_PREFIX)
.contains(crate::wiki::WIKI_INVOCATION_MARKER)
{
return Some("secall summary prompt");
return Some("secall wiki invocation");
}
let content_trimmed = first_user.content.trim_start();
if content_trimmed.starts_with(SECALL_SUMMARY_PROMPT_PREFIX) {
return Some("secall summary prompt");
}
if content_trimmed.contains(crate::wiki::WIKI_INVOCATION_MARKER) {
return Some("secall wiki invocation");
}

…#82)

Issue #82 (dicebattle): `secall wiki update` 가 codex 백엔드 호출 시, codex CLI
가 자체 세션 파일 (`~/.codex/sessions/...`) 을 생성하고, secall sync 가 그
세션을 일반 사용자 세션과 동일하게 ingest 해 무한 wiki 재생성 / 중복 항목 발생.
claude 백엔드 (`claude -p` subprocess) 도 동일 문제.

Fix:
- `wiki::WIKI_INVOCATION_MARKER` (`<!-- secall:wiki-update -->`) 상수 신설.
- `wiki/codex.rs` + `wiki/claude.rs` 의 generate() 가 prompt 앞에 marker prefix.
- `ingest::is_noise_session()` 에 marker 검출 룰 추가 — 첫 user turn 의 content
  에 marker 가 있으면 "secall wiki invocation" 사유로 skip 처리. 기존 P49
  (`SECALL_SUMMARY_PROMPT_PREFIX`) 와 동일 메커니즘 (parser 시그니처 변경 없음).
- `ingest/mod.rs::tests` 에 신규 unit test 3건.

검증:
- cargo fmt --check: clean
- cargo clippy --workspace --all-targets -D warnings: clean
- cargo test -p secall-core --lib ingest::: 110 passed (신규 3건 포함)
- cargo test --workspace --no-fail-fast: all green (lib 421 + integration)

비목표: 본 PR 머지 전 이미 ingest 된 wiki invocation 세션은 사용자가 `secall
archive <id>` 로 수동 정리. 자동 일괄 정리는 별도 fast-follow PR 검토.

Closes #82

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@hang-in hang-in force-pushed the fix/p83-wiki-self-ingest-loop branch from 0458a3c to e90e0da Compare May 18, 2026 23:54
@hang-in
Copy link
Copy Markdown
Owner Author

hang-in commented May 18, 2026

Gemini 리뷰 1건 반영 (commit e90e0da) — is_noise_session() 의 두 번째 검사도 content_trimmed 재사용해 일관성 유지. main 머지로 발생한 docs/plans/index.md conflict 도 함께 해소 (P82 → P83 순서 보존). rebase + force-with-lease push.

@hang-in hang-in merged commit 3b73dd8 into main May 19, 2026
3 checks passed
@hang-in hang-in deleted the fix/p83-wiki-self-ingest-loop branch May 19, 2026 00:04
hang-in added a commit that referenced this pull request May 19, 2026
…ingest cleanup (#82 follow-up) (#86)

* feat(lint): P84 — `lint --fix-wiki-invocations` for legacy wiki self-ingest cleanup (#82 follow-up)

P83 (#85) 머지 후 신규 wiki invocation 세션은 marker 검사로 차단되지만, 머지 전
ingest 된 legacy 세션에는 marker 가 없어 자동 정리가 안 된다. 사용자가 한 번
실행해 일괄 archive 할 수 있는 lint 옵션 추가.

- `ingest/lint.rs`: `check_wiki_invocations()` 함수 추가 (L011 신규).
  cwd 가 `[vault].path` 와 일치하는 codex/claude 세션을 Info 레벨로 finding.
- `commands/lint.rs`: `--fix-wiki-invocations` flag 처리하는
  `run_fix_wiki_invocations()` 추가. SessionRepo::archive_session 호출.
- `main.rs`: clap arg + call site 갱신.
- 신규 unit test 5건 (codex/claude detect, archived skip, cwd outside vault,
  non-codex/claude agents).

사용:
- `secall lint` → L011 finding 표시
- `secall lint --fix-wiki-invocations` → 일괄 archive
- 의도와 다르면 `secall unarchive <id>` 로 복원 (reversible)

검증:
- cargo fmt --check: clean
- cargo clippy --workspace --all-targets -D warnings: clean
- cargo test -p secall-core --lib ingest::lint: 18 passed
- cargo test --workspace --no-fail-fast: all green (lib 426 + integration)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(lint): P84 follow-up — Gemini 리뷰 반영 (SQL 에서 cwd 직접 필터링)

`check_wiki_invocations()` 의 cwd 매치를 SQL WHERE 절로 옮김 — DB level 에서
필터링해 불필요한 row 전송/순회 회피. Rust loop 의 조건문 제거로 가독성 ↑.

검증:
- cargo fmt --check: clean
- cargo clippy --workspace --all-targets -D warnings: clean
- cargo test -p secall-core --lib ingest::lint: 18 passed

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: d9ng <d9ng@outlook.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

LLM 요약을 위한 세션도 위키 요약에 들어가는것 같은데, 제가 잘못 쓰고있는걸까요?

1 participant