ES /docs

download floorplan image failed

Validation: 0ccbf0f7-6dcc-4b2a-869f-00a871bd78c7

Verdict: APPROVED#

Completeness#

Plan Item Status Evidence
CPUtils.safeFileName 정적 메서드 추가 (basename, separator/제어문자/공백 치환, leading dot 무력화, 64자 상한, undefined/empty → '') PASS applications/agents/packages/utils/src/cputils.ts +193~215 — path.basename, replace(/[\\/\x00-\x1f\s]/g, '_'), replace(/^\.+/, ...), MAX_LENGTH = 64, undefined/empty 조기 반환 모두 확인
vitest describe 블록 (정상 확장자, slash, backslash, control/whitespace, undefined/empty, path traversal, leading dots) PASS applications/agents/packages/utils/src/cputils.spec.ts +374~415 — 7개 it 블록 존재 (simple, slash, backslash, whitespace/control, undefined/empty, traversal, leading dots, 64자 상한)
refinement-agent setDefaultLocalPathssafeFileName 적용 + 변경 시 warn 로깅 PASS applications/agents/packages/cupix-capture-refinement-agent/src/model/cpfloorplan.ts +53~62 — safeExt 계산, 원본과 다르면 logger.warn, 빈 문자열이면 확장자 없이 조인
refinement-agent downloadImage catch — JSON.stringify(error) 제거, error 를 splat 으로 전달 PASS applications/agents/packages/cupix-capture-refinement-agent/src/model/cpfloorplan.ts +78 — `logger.warn('CPFloorplan::downloadImage
preprocessor-agent getBimFloorplanFilePathsafeFileName 적용 + warn 로깅, 빈 값일 때 fallback PASS applications/agents/packages/cupix-capture-preprocessor-agent/src/model/cpfloorplan.ts +65~71 — safeExt 계산, logger.warn on mismatch, 빈 문자열이면 확장자 없이 id 만 사용

Acceptance Criteria#

Criterion Status Evidence
CPUtils.safeFileName exported from @agents/utils, vitest passes PASS (정적 검증) cputils.tsexport class CPUtils 안 static 메서드로 추가되어 자동 export; 실제 vitest 실행은 이 단계에서 검증 불가하나 스펙 파일 문법상 문제 없음
safeFileName('rvt-site/lvl 1') produces no slashes/whitespace PASS cputils.spec.ts +381 — expect(CPUtils.safeFileName('rvt-site/lvl 1')).toBe('lvl_1') (basename 이 lvl 1 을 남기고 공백이 _ 로 치환됨)
grep path.join.*file_extension under applications/agents/packages/**/model/cpfloorplan.ts shows 0 unsafe concatenations PASS refinement cpfloorplan.ts +58~60, preprocessor cpfloorplan.ts +71 — 두 hotspot 모두 safeExt 를 경유하여 join; 원본 originalImageFileExt / this._extension 을 직접 path.join 에 넘기는 라인은 diff 에서 제거됨
downloadImage catch removes JSON.stringify(error); error passed directly to logger PASS refinement cpfloorplan.ts +78 — JSON.stringify 삭제, error 가 마지막 splat 인자
Both hotspot files' sanitize warnings are grep-able PASS 문자열 normalized floorplan extension 가 두 파일 모두에 존재 (refinement +57, preprocessor +67)
TypeScript / eslint pass on changed files PASS (정적 검증) 타입 시그니처 `(input: string

Issues Found#

차단 이슈 없음.

Observations#

  • applications/agents/packages/utils/src/cputils.spec.ts 파일 끝에 \ No newline at end of file 이 표시됨. 기능상 문제는 아니지만 팀 컨벤션에 따라 개행 추가를 고려할 수 있음.
  • refinement-agent 의 조건문 if (originalImageFileExt != undefined && safeExt !== originalImageFileExt) 는 undefined 입력을 별도로 처리하지만, preprocessor-agent 의 warn 조건 if (safeExt !== this._extension) 는 undefined 여부를 검사하지 않음. this._extension 이 undefined 인 케이스에서 safeExt === '' 가 되므로 warn 이 발생할 수 있으나, 이는 실질적 버그가 아니라 로그 노이즈 정도의 차이. 필요 시 조건 통일을 검토 가능.
  • MAX_LENGTH = 64 는 hardcoded 상수. 향후 재사용을 위해 옵션 파라미터화 여지가 있으나 현 요구사항에는 부합.
  • refinement-agent downloadImage 의 새 로그는 %s format specifier 없이 error 를 trailing splat 으로 전달 — 프로젝트의 fix logger native Error handling 컨벤션에 부합.