LLM WikiAccess-protected knowledge portal

WIKI

2026-W27 Worklog

AI Summary Purpose Tracks development work across repositories for this week. Key points Add coding work entries here after meaningful agent sessions. Keep entries concise. Promote durable knowledge to ai/repo notes/ or ai/wiki/ . 2026 07 0

경로ai/worklog/2026/2026-W27.md
카테고리Worklog
태그#ai-review #airflow #crawler #infra #notetaker #portfolio #report #spm #ssl #swift #w27 #worklog

# 2026-W27 Worklog

AI Summary

Purpose:

Key points:

Relevant when:

Do not read full document unless:

Linked documents:

Work Items

개선 이력 12종 접두사 ENHC·표 개편 + Jira DAT-3295 하위 작업 12개 (2026-07-03)

- 방식 메모: getConfluencePage는 markdown만 반환해 번호열/스타일 확인 불가 → contentFormat: "adf"로 읽어 검증. update는 HTML로 재구성(본문 markdown → 원 스타일 HTML 복원).

- Jira 제약 2건: (1) 원격 웹 링크(Links 패널) 생성 API 미제공 → 설명 본문 스마트링크로 대체. (2) 하위 작업 워크플로가 해야 할 일→완료 직행 불가라 진행 중(21)→작업 완료(3) 2단계. 부모는 Open PR(7)→CD Complete(2). (3) 부모 제목이 외부에서 [TRBL|LIB][DOC|LIB]로 변경돼 있었음(확인 대기).

언어별 크롤러 "개선 이력" Confluence 12종 생성 (2026-07-03)

labrador-data-platform(dat-3258/lib_crawlermain 46e876f). 둘 다 커밋·푸시·main ff-merge 완료.

SSLError(SSLCertVerificationError(… unable to get local issuer certificate)). traceback 이 항상 util/detail_parser.py:63scraper.get(...)`(cloudscraper 폴백)에서 끝남.

cloudscraper 폴백 진입. cloudscraper 는 브라우저 ja3 흉내용 자체 SSLContext(CipherSuiteAdapter) 를 쓰는데, urllib3 에 커스텀 ssl_context 를 넘기면 CA 번들 경로를 명시 안 하는 한 certifi 를 안 싣고 컨테이너 시스템 CA(python:3.12-slim-bullseye, 불완전)에 의존 → issuer 검증 실패. requests 는 기본이 certifi 라 line 51 은 통과(traceback 이 line 51 에서 안 끝나는 게 결정적 단서).

(self._ca_bundle_path = certifi.where(), requests/cloudscraper/curl_cffi 전 경로에 verify= 전달, SSL 실패 시 verify=False 1회 폴백). 주석에 "use certifi bundle explicitly to avoid missing system CAs in runtime". detail_parser._fetch_text 만 이 수정을 못 받은 옛 fetch 경로였음(중복 구현 2벌).

공용 httpClient._request_with_retries(url, retries, wait_time, headers=_HTML_HEADERS) 호출 → .text 반환으로 대체(−56/+27). HTML Accept 헤더만 override(httpClient 기본은 sitemap XML 지향). 전 코드베이스 관례가 httpClient._request_with_retries(...)(underscore 가 사실상 공개 API, CollectTarget/LibrarySpmModelCrawler/spm_build_processor 모두 동일 사용). py_compile 통과.

(spm_build_processor._should_skip_incremental: sitemap lastmod ≤ DB LAST_UPDATED 면 detail fetch·태그·clone 전부 skip; self.incremental True 일 때만). 단 스케줄 실행이 증분을 한 번도 안 켬: dags/spm_crawler.pyincremental Param 기본값 = False → 매일 --no-incremental(전체 resync). 전체 모드라 매번 전 product 의 detail 페이지를 fetch → 위 SSL 에러 최대 노출. (DAG task = spiProduct, spiVulnerability 둘뿐; spiVersion 은 product_process 내부 처리, spmModel 은 main.py 주석 처리.)

- dags/spm_crawler.py: schedule 0 20 * * *0 20 * * 1-6(월~토 증분), incremental Param 기본 FalseTrue. arg 템플릿(--incremental if params.incremental else --no-incremental) 유지 → 수동 트리거로 full 강제 가능. - 신규 dags/spm_resync_crawler.py: 일요일 0 20 * * 0 전체 resync(--no-incremental 하드코딩), spm_crawler 구조 그대로 미러(같은 image/태스크/db param). 일요일 단독 실행이라 월~토 증분과 시각 겹침 없음. - 의도: 평일 증분으로 부하·SSL 에러 최소화 + 주 1회 full 로 누락(SPI 삭제 패키지, lastmod 갱신 없는 변경) 보정. 다른 크롤러(npm/pypi/vcpkg) "스케줄 full resync 부재 → 누락" 함정을 SPM 은 회피.

로컬 venv 로 실제 검사 재현 — scrapers detail_parser: black/isort/docstring 통과(mypy 3건은 미수정 extract_package_details 의 기존 에러, HEAD 동일 → --no-verify). platform DAG 2개: black/isort/ pylint 10.00/mypy 전부 통과(prepare-commit-msg 의 bash3.2 ${VAR^^} 미호환 → hooksPath 우회, pre-push astro dev parse 는 astro/Docker 없어 미실행 → --no-verify).

미설치) — 새 DAG 는 동작 중인 spm_crawler.py 구조 동일 + 정적검사 통과로 위험 낮춤, Airflow 가 파일별 파싱오류 격리하므로 영향범위는 SPM DAG 2개 한정. (2) 컨테이너 런타임 SSL 실증은 spm_scraper 이미지 빌드/배포 후 확인 필요(아직 미배포).

남은 일: spm_scraper 이미지 빌드/배포 → 런타임 SSL 해소·증분 스케줄 동작 실측.

SPM 증분을 LIST 테이블(TB_COMP_LIB_SPM_LIST) 기반으로 전환 + clone 스톨/중복키 수정

product마다 git clone에서 메인 스레드 stall(로그가 10초 flush 하트비트만) + 일부 product Duplicate entry … PRIMARY(1062) 에러.

sitemap lastmod를 비교했는데, 그 컬럼이 timestamp … on update CURRENT_TIMESTAMP라 코드가 넣는 sitemap lastmod가 매 write마다 처리 시각으로 덮어써짐 → "지난번 lastmod" 신호 소실. 게다가 SPI sitemap lastmod는 페이지 재생성마다 갱신(churn)돼 항상 최신 → 절대 skip 안 됨. (의도된 LIST 테이블 인프라 TB_COMP_LIB_SPM_LIST 모델·gathering_db 메서드는 있었으나 main.py에서 주석처리되고 테이블도 DB에 없던 상태.)

EXISTS, PATH PK), count_spm_list, get_spm_processed_paths(PROCESSED=1 PATH를 소문자 set), upsert_spm_list, seed_spm_list_from_products(기존 product 전부 INSERT IGNORE + PROCESSED=1) 추가. set_gatheringdb에서 테이블 보장 + LIST 비었으면 최초 1회 시딩. product_process의 skip을 self.incremental and product_key.lower() in processed_set 로 교체(신규/미수집만 수집, 기존 PROCESSED=1은 skip). 수집 성공/무버전 평가 후 upsert_spm_list(...,1). 사용자 요청대로 기존 데이터는 시딩으로 PROCESSED=1 → 증분에서 제외. 기존 패키지 신버전은 주1회 full resync가 흡수 (lastmod churn 우회). 결정: 증분 skip = PROCESSED 플래그만(사용자 선택).

PK 콜레이션 utf8mb4_0900_ai_ci(대소문자 무시)에서 충돌하나, 캐시(Python, 대소문자 구분)는 못 찾아 INSERT 분기로 가 1062. insert_into_product_queryON DUPLICATE KEY UPDATE(upsert) 로 바꿔 full resync에서도 안전(컬럼·포맷 불변). 증분에선 해당 패키지가 PROCESSED=1이라 애초에 skip.

partial, 태그/히스토리 보존 — --depth 1은 태그 checkout/getTagDates를 깨므로 불가) + timeout=180, getGITSwitchtimeout=120. timeout 시 정리/False 반환. 영구 clone 캐시(/resources PVC 재사용)는 용량캡·LRU 필요라 다음 단계로 보류**(사용자 선택). 클론은 여전히 /workspace/output(휘발).

깔끔; spm_build_processor는 HEAD가 non-black-clean → 전체 재포맷 churn 방지 위해 로직만 적용, diff 31줄). mypy 신규 에러 0(HEAD 22=현재 22). DB·컨테이너 실행 검증은 이미지 빌드/배포 후 필요.

version_process_async는 여전히 _should_skip_incremental 사용(DAG 미스케줄이라 보류).

spm_scraper 이미지 재빌드/배포 후 첫 실행(LIST 테이블 자동 생성 + 기존 product PROCESSED=1 시딩).

SPM 증분 전환 회귀: SpiVulnerabilityIncrementalCrawler __init__ TypeError 수정

spiVulnerability 태스크가 매 실행 TypeError: SpiVulnerabilityIncrementalCrawler.__init__() takes 1 positional argument but 2 were given(main.py:234 scraper_class(target_db))로 죽음.

(Product/Version 은 (self, target_db, **kwargs)). --no-incremental 시절엔 base 클래스만 써서 안 터지다가, DAG 증분 기본 전환(이번 주 작업)으로 노출된 잠복 버그 = 자기-회귀.

vulnerability_process 는 self.incremental 미사용이라 set_incremental 추가 안 함(동작 불변). py_compile OK. push + main ff-merge 완료(scrapers main 67d3736). 적용은 이미지 재빌드 후.

생성자 시그니처까지 점검 필요(여기선 Vulnerability 만 시그니처 불일치).

SPM 표준 [total summary] 출력 + 로그 이중 출력 근본 수정

(product insert/update 구분 없음)라 npm/pypi/go의 표준 [total summary] product insert=.. update=.., version insert=.. update=..와 불일치(모니터링 파싱 일관성).

insert/update = merge 직전 PK 존재 여부(read-only SELECT)로 카운트, version 은 기존 누적 재사용. 기존 COLLECTED summary 로그 유지. product/version 테이블·포맷 불변.

INFO:name:msg). 원인 = root 로거 핸들러 2개(setup_logger_config 리치 핸들러 + setup 이전 root 로깅으로 자동 트리거된 basicConfig 기본포맷 핸들러). main._dedupe_root_log_handlers로 setup 직후 logging.BASIC_FORMAT 핸들러만 제거 → root 에 리치 하나만. 이후 root 에 핸들러가 있어 basicConfig 재트리거 없음. 처음엔 npm/pypi 처럼 print()로 우회했으나(중복 회피 목적), 사용자 요청대로 logger 사용 + 근본 원인(이중 핸들러) 제거로 전환.

(main +23, spm +9). 실로그 1줄 확인은 이미지 빌드/배포 후.

(SSL 8d700ce / LIST·clone·dupkey fe4a9a6 / vuln init 67d3736 / total summary 90907ae / 로그수정 b04eecb)는 spm_scraper 이미지 재빌드 시 함께 적용.

Go 누락 CSV(2026-07-01, 1,155건) 확인 + 백필 + 제외 + 크롤러 버그 발견

사용자 제공 2026-07-01T00-08_export.csv(1,155 index path). 도구 ~/labrador/tool/golang_missing_products. 크롤러 crawler-lib-golang(미수정). DB gatheringdb TB_COMP_LIB_PRODUCT_GOLANG/TB_COMP_LIB_GOLANG_LIST_V2.

#### [후속] Go 크롤러 version-escape 버그 수정 + 45,508 재큐 (2026-07-01)

#### [후속] Go 큐 claim 락 경합 → FOR UPDATE SKIP LOCKED 재작성 (2026-07-01)

npm "누락" CSV(13건) 검증 → 실제 누락 0 + NAME 오염 크롤러 버그 수정 (2026-07-01)

사용자 제공 CSV 13건(대부분 scoped @scope/name + funky-sdk/ql-lib/scanrook-mcp/tryversion/vulms-sdk). 크롤러 labrador-scrapers/etl_components/npm_crawler(브랜치 dat-3257/lib_crawler). DB gatheringdb TB_COMP_LIB_JAVASCRIPT_LIST(work-queue, cols path/url/last_updated/processed) / TB_COMP_LIB_VERSION_JAVASCRIPT / labradordb TB_COMP_LIB_PRODUCT(PRODUCT_KEY = AES-CBC, key=IV=NPMNPMNPMNPMNPMN, 결정적).

SPM "누락" CSV(21건) 재확인 → 실누락 0 (2건 기수집 + 19 tagless 제외) (2026-07-01)

사용자 제공 21건(owner/repo). 도구 ~/labrador/tool/spm_missing_products, workdir 2026-07-01. DB gatheringdb TB_COMP_LIB_PRODUCT_SPI/TB_COMP_LIB_VERSION_SPI(swift/SPM, PRODUCT_KEY=owner/repo, PK collation ai_ci=case-insensitive).

php(composer) 크롤러: zero-version feed-ahead-of-meta 재시도 ladder 추가 (2026-07-01, 미커밋)

#### [후속] 앞선 php CSV 8건 백필 완료 (2026-07-01)

#### [후속] all-dev 패키지 dependabot 브랜치 노이즈 제거 (2026-07-01, crawler-lib-php master 5a6792d)

comp_lib_vuln_processor: golang PRODUCT_KEY JOIN collation(1267) 수정 (2026-07-02, 미커밋)

[진단+설계] vuln processor가 go product를 labradordb(구 테이블)에 쓰는 문제 (2026-07-01)

1. 단일 리졸버 도입 — repository→FQ product 테이블 매핑을 한 곳(예: base_mapper 상수/헬퍼 resolve_comp_lib_product_table(repository))에 두고 4곳 ad-hoc 분기를 전부 이걸로 교체. 매핑: conan/vcpkg/hunter → gatheringdb.TB_COMP_LIB_PRODUCT / golang → gatheringdb.TB_COMP_LIB_PRODUCT_GOLANG / spm → gatheringdb.TB_COMP_LIB_PRODUCT_SPI(검증 후) / 그 외(maven/npm/pypi/composer/rubygems/cocoapods/nuget) → labradordb.TB_COMP_LIB_PRODUCT(현행). 2. UPSERT((LANGUAGE,REPOSITORY,PRODUCT_KEY,VULN_RANGE) ON DUP KEY)·JOIN 로직 불변 — 테이블명만 리졸버 경유. 데이터 포맷/컬럼 무변경. 3. as_cs 매칭 주의: go/spm 대상은 케이스구분 매칭(vuln 소스 product_key가 정확한 케이스여야 매칭 — 정상, go 케이스구분 정체성). 4. 옵션 일회성 백필: 기존 labradordb go 행 VULN_RANGE를 매칭키로 PRODUCT_GOLANG에 복사(다음 vuln 런에서 어차피 재적용되나 즉시 반영용). 5. 테스트: 리졸버 매핑 단위테스트(golang→_GOLANG, conan→gatheringdb PRODUCT, npm→labradordb PRODUCT).

[정정] golang_excluded.tsv 재정의 — "이미 있는 것"이 아니라 "없는 것"만 (2026-07-01)

[재정정] 제외목록 정의 확정 — "index name ≠ product_key" 전부 (2026-07-01)

- listv2_alias_resolved 154,168 (go.mod 선언경로≠index, 크롤러가 PROCESSED=6로 타 키 정리) - case_only 50,651 (index 케이스≠저장 product_key 케이스) - subpackage 30,927 (index=하위경로, product_key=모듈 root) - proxy_gone_404 979 (product_key 자체 없음/삭제) - git_alias 495 (index=x.git, product_key=x) - listv2_collected 265 (다른 키 형태로 수집됨)

[백필] 진짜 누락 99건 처리 결과 (2026-07-01)

- github.com/jarrahg/buffalocli → go.mod 선언 github.com/gobuffalo/cli(인기 모듈, 이미 DB 존재) — 크롤러가 그 hot row를 계속 잠가 alias 마크만 timeout(실데이터 손실 없음). - github.com/javadkavossi/golang_learning → 선언 myproject(도메인 없는 쓰레기 모듈명, 수집대상 아님). - 둘 다 index≠product_key → 제외목록에 proxy_declared_diff로 추가(golang_excluded.tsv 237,485→237,487). 애초 alive(proxy 200)로 잡혔으나 declared-path 해석 시 alias였음(빠른 proxy @latest 체크의 한계).

Go missing CSV check (2026-07-02 export, 5,472 rows)

[진단+백필] Conan "누락" 25건 = _CONAN엔 있으나 공용 TB_COMP_LIB_PRODUCT 미전파 (2026-07-01)

라이브러리 크롤러 온보딩 문서 12종 Confluence 발행 (2026-07-02)

폴더에 크롤러별 온보딩 가이드 생성. 제목 규격 [GUID|LIB] <언어>(<레지스트리>) 크롤러 온보딩 가이드. 각 문서 = 한국어 8섹션(개요/저장소/파이프라인/데이터모델/시퀀스다이어그램/스케줄운영/이슈/참고) + mermaid 시퀀스 다이어그램. superloopy(light) evidence loop로 진행 관리.

labrador-data-platform/dags/ 대조로 초안 HTML + mmd 생성 → mermaid escape 주입 → MCP로 발행.

com.atlassian.ecosystem / .../static/mermaid-diagram. HTML 바디엔 language-mermaid 코드블록만 넣으면 claude.ai Atlassian MCP의 HTML→ADF 변환기가 diagram 매크로를 자동 삽입(guestParams.index = N번째 mermaid). 익스텐션 div를 손으로 넣거나 <details>로 감싸면 매크로 중복/중첩 발생(conan v1에서 실측 → v2에서 바디 코드블록만 남겨 수정). 규격은 ai/wiki/projects/confluence-lib-onboarding-docs.md에 정리.

golang 4156227631, vcpkg 4156096559, spm 4156227651, swift(CocoaPods) 4156424213, ruby 4156129314, hunter 4156260364, java 4156260412, dotnet 4156620917. (전부 EN 스페이스, 각 언어 폴더 하위)

(INSERT ... ON DUPLICATE KEY UPDATE, SELECT ... WHERE ... 등 SQL 유사 문자열이 대용량 POST에서 트리거). 인용부호 치환·SQL 키워드 전량 서술화(java 20건/dotnet 22건 재작성)해도 IP 평판 누적으로 계속 차단. Codex가 Atlassian Rovo Markdown create/update 경로로 우선 발행한 뒤, 사용자 요청에 따라 Rovo ADF update로 재정리 완료. ADF 재조회 검증: 두 페이지 모두 native TOC macro, Forge Mermaid diagram extension (.../static/mermaid-diagram), expand("Diagram") 내부 codeBlock(language=mermaid) 존재. 저장소 표기는 SSH 주소가 아니라 실제 Bitbucket URL로 교체했고, 본문은 긴 SQL/운영 세부를 줄여 사람이 처음 읽기 쉬운 8섹션 온보딩 틀로 맞춤. 이후 표 가독성 요청에 따라 ADF table attrs를 추가 조정: 2열 표는 width=1200(190/1010 또는 360/840), 4열 파이프라인 표는 java width=1260, dotnet width=1280로 고정하고 모든 셀에 colwidth를 지정. Confluence ADF 재조회로 두 페이지 모두 layout=center, width, colwidth 저장 확인.

(ConanProductCreator MAX(SORT_ORDER) vs SORT_ORDER=0=최신 반전; boost 1.78.0/openssl 3.0.20 실측). vcpkg/hunter product 단계 동일 구조 → 점검 권장. spm/hunter util에 하드코딩 GitHub 토큰(값 미기록, 정리 필요).

라이브러리 크롤러 온보딩 문서 Rovo ADF 재정리 + DB 스키마 삽입 (2026-07-02)

- npm 4155375649, pypi 4155375669, php 4155506704, golang 4156227631, ruby 4156129314, swift(CocoaPods) 4156424213, spm 4156227651, conan 4155572232, vcpkg 4156096559, hunter 4156260364를 Atlassian Rovo ADF로 재작성. - Java 4156260412, dotnet 4156620917은 직전 작업에서 이미 같은 ADF 구조와 wide table sizing까지 반영된 상태라 유지.

- npm/pypi/php/golang은 상세 schema block, ruby/swift/spm/conan/vcpkg/hunter는 page size를 줄이기 위해 live DB column summary schema block으로 삽입. - gatheringdb.TB_COMP_LIB_SWIFT_LIST는 코드에서 참조되지만 2026-07-02 live DB metadata에 없음. Swift(CocoaPods) 페이지에 "Missing or not readable in live DB metadata"로 명시.

- 각 updateConfluencePage 호출은 version 응답으로 저장 확인. - 대표 재조회: vcpkg 4156096559 ADF에서 native TOC macro, expand("테이블 스키마 (DB 확인 결과)") + codeBlock(language=sql), Forge .../static/mermaid-diagram extension, expand("Diagram") + codeBlock(language=mermaid) 확인. - Hunter 4156260364는 첫 update/read가 504였으나 최소 ADF 재시도 후 version 3 저장 응답 확인. 후속 ADF read는 504가 발생해 대표 구조 검증은 vcpkg로 대체.

언어별 크롤러 "개선 이력" Confluence 12종 생성 (2026-07-03)

라이브러리 누락 개선 작업 repo별 문서화 (2026-07-03)

일부(conan/golang/vcpkg/spm/swift/ruby/hunter)는 산문/불릿 + column summary만, 시퀀스는 전부 generic placeholder였다. 사용자 요청: 에이전트 하나가 JavaScript(npm) 4155375649 포맷을 기준으로 전 페이지를 통일하고, 시퀀스 다이어그램은 Java 온보딩 스타일(실제 테이블/레지스트리 참여자 + 실제 동작)로.

vcpkg 4156096559, spm 4156227651, swift(CocoaPods) 4156424213, ruby 4156129314, hunter 4156260364. 유지(참조/모범) 3종: npm(포맷 기준), java 4156260412(다이어그램 스타일 기준), dotnet 4156620917(이미 표+specific 다이어그램). — 세 좋은 페이지는 손대지 않아 회귀 위험 제거.

(2) 시퀀스 다이어그램을 Java 스타일로 재작성 = 참여자 = <레지스트리> + 실제 DB 테이블명, 화살표에 실제 동작(예: golang list_v2 upsert (id=sha256(path@version)), conan recipe raw upsert (UNIQUE library/recipe/name)). (3) SQL 스키마 expand를 live DB SHOW CREATE TABLE 실측 DDL로 교체(컬럼 + PRIMARY/UNIQUE, 2차 ix_* 인덱스는 가독성 위해 트림). 공용 TB_LICENSE_V2는 표에만 표기하고 DDL 덤프는 생략.

labradordb 크로스). 접속정보는 MCP 연결에만 쓰고 Confluence/위키에 복사하지 않음.

본문 9건 모두 성공(Cloudflare WAF 차단 없음). HTML→ADF 변환기가 bare <pre><code class="language-mermaid"> 블록에서 Forge mermaid-diagram extension + expand("Diagram")을 자동 삽입하고, guestParams.index를 페이지 내 모든 코드블록 중 mermaid 블록의 0-based 위치로 설정한다. SQL expand(코드블록 0) → mermaid (코드블록 1) 순서라 자동으로 index:1이 맞게 들어감(수작업 extension 노드 불필요). 코드블록 안에서는 <>&만 escape(mermaid ->>-&gt;&gt;).

Forge mermaid(index:1)/expand("Diagram")까지 구조 검증. Confluence 외 코드/데이터 변경 없음.

Personal Tiro-like AI notetaker plan

- ai/sources/tiro-ai-notetaker-research-2026-07-01.md - ai/wiki/projects/personal-ai-notetaker.md - ai/wiki/projects/index.md - ONBOARDING.md