Releases: MerciHanrim/FileNexusSuite
Release list
File Nexus Suite v1.1.2
v1.1.2 โ Text Merger MD ์ถ๋ ฅ ํ์ ์ถ๊ฐ / Text Merger MD Output Format
Full Changelog: v1.1.1...v1.1.2
โจ Added
- Text Merger โ MD ์ถ๋ ฅ ํ์ ์ถ๊ฐ / Text Merger โ MD output format added
- ์ ์ฅ ์ค์ ์์ญ์
์ถ๋ ฅ ํ์: TXT / MD๋ผ๋์ค๋ฒํผ์ด ์ถ๊ฐ๋จ. MD ์ ํ ์ ํ์ผ ๊ตฌ๋ถ์ ์ด## ํ์ผ๋ชํค๋ +---๋งํฌ๋ค์ด ์์์ผ๋ก ์๋ ์ ํ๋๊ณ , ๊ธฐ๋ณธ ํ์ผ๋ช ๋merged.md๋ก ๋ณ๊ฒฝ๋จ. ์ ํํ ํ์์ ์ค์ ์ผ๋ก ์ ์ฅ๋จ /Output Format: TXT / MDradio buttons added to the save settings area. When MD is selected, file separators switch to## filenameheader +---Markdown form and the default filename becomesmerged.md. The selected format is saved with other settings.
- ์ ์ฅ ์ค์ ์์ญ์
๐ Notes for Existing Users
- ๊ธฐ์กด v1.1.1 ์ฌ์ฉ์๋ ์์ ํ๊ฒ v1.1.2๋ก ์ด์ ๊ฐ๋ฅ. ์ค์ ๋ฐ์ดํฐ(
FileNexusSuite.json)์ ์ถ๋ ฅ ํ์ผ(Output/)์ ๊ทธ๋๋ก ๋ณด์กด๋ฉ๋๋ค / Existing v1.1.1 users can safely upgrade to v1.1.2. Settings (FileNexusSuite.json) and output files (Output/) are preserved. - ๊ธฐ์กด ์ค์ ํ์ผ์ ์ถ๋ ฅ ํ์ ํญ๋ชฉ์ด ์๋ ๊ฒฝ์ฐ TXT๋ก ๊ธฐ๋ณธ ๋ณต์๋ฉ๋๋ค / If the output format entry is absent from an existing settings file, TXT is used as the default.
๐ Release Signing
- Release commit
[PLACEHOLDER]โ SSH ์๋ช (Ed25519), GitHub Verified ๋ฑ์ง / SSH-signed (Ed25519), GitHub Verified - ํ๊ทธ
v1.1.2SSH ์๋ช , GitHub Verified ๋ฑ์ง / Tagv1.1.2SSH-signed, GitHub Verified - GitHub Actions CI
windows-latest+ Python 3.10 ํ๊ฒฝ์์ ์๋ ํต๊ณผ / GitHub Actions CI passed onwindows-latest+ Python 3.10
Tag: v1.1.2
Released: 2026-05-14
Build: FileNexusSuite_v1.1.2_win64.zip ([PLACEHOLDER] MB)
๊น์ ๊ธฐ์ ๋ณํ ์ด๋ ฅ์
CHANGELOG.md์ฐธ์กฐ / For detailed technical changes, seeCHANGELOG.md
๐ผ
File Nexus Suite v1.1.1
v1.1.1 โ ๋์๋ง ๋ค๊ตญ์ด + ๋ณธ์ฒด i18n ์ ๋ฆฌ / Help Localization + Main Module i18n Cleanup
Full Changelog: v1.1.0...v1.1.1
๐ Bug Fixes
- Text Converter โ Book Info ํจ๋ ๋ ์ด์์ fix / Text Converter โ Book Info panel layout fix
- Debug Log ํจ๋์ ํผ์ณค์ ๋ ์ฐ์ธก Book Info ํจ๋์ Title / Author / Language / Chapter Split ์ ๋ ฅ ํ๋ ๋ผ๋ฒจ์ด ์ ๋ ฅ ๋ฐ์ค์ ๊ฐ๋ ค์ง๋ ๊ฒฐํจ์ด ์์ ๋จ. v1.1.0๋ถํฐ ์กด์ฌํ๋ ๋ฌธ์ / The labels of Title / Author / Language / Chapter Split fields in the Book Info panel were hidden under the input boxes when Debug Log was expanded โ fixed. Issue had been present since v1.1.0
โจ Changed
-
๋์๋ง ์์คํ ์ด OS ์ธ์ด ์ค์ ์ ๋ฐ๋ผ ์๋์ผ๋ก 5๊ฐ ์ธ์ด๋ก ํ์ / Help system now displays in 5 languages following OS language setting
- v1.1.0์์ ๋ณธ์ฒด UI ๋ฌธ์์ด์ ์ ์ฉ๋์๋ Qt Linguist ๋ค๊ตญ์ด ๋ฐํ์ ์ํฌํ๋ก๊ฐ ๋์๋ง ์ฝํ ์ธ ๊น์ง ์ผ๊ด๋๊ฒ ํ์ฅ๋จ. ๋์๋ง ํ ์คํธ๊ฐ OS ์ธ์ด ์๋ ๊ฐ์ง ๋๋ Settings โ Language์์ ์ ํํ ์ธ์ด๋ก ํ์๋จ / The Qt Linguist runtime workflow used for main UI strings in v1.1.0 now extends to help content. Help text displays in the OS-detected language or the user-selected language from Settings โ Language
-
๋ณธ์ฒด์ ๋จ์์๋ ํ๊ตญ์ด ํ๋์ฝ๋ 6๊ณณ ์ ๋ฆฌ / Six remaining Korean-hardcoded sites in the main module cleaned up
- v1.0.x ์์ ๋จ์ผ ํ๊ตญ์ด ์ฝ๋์ ์์ฌ๋ก ๋ณธ์ฒด์ ๋จ์์๋ 6๊ณณ(๋์๋ง ๋ฒํผ ํดํ, ์์ ๋ก๊ทธ ๋ฉ์์ง, EPUB ๋ฉํ๋ฐ์ดํฐ
'์ ์: '๋ผ๋ฒจ, ์ค์ ์ฐฝ ์ฌ์ด๋๋ฐ 4๊ฐ ๋ผ๋ฒจ)์ด 5๊ฐ ์ง์ ์ธ์ด๋ก ์ ์ ํ์๋๋๋ก ์ ๋ฆฌ๋จ / Six leftover Korean-hardcoded sites (help button tooltip, startup log message, EPUB metadata'Author: 'label, four Settings sidebar labels) now display in all 5 supported languages
- v1.0.x ์์ ๋จ์ผ ํ๊ตญ์ด ์ฝ๋์ ์์ฌ๋ก ๋ณธ์ฒด์ ๋จ์์๋ 6๊ณณ(๋์๋ง ๋ฒํผ ํดํ, ์์ ๋ก๊ทธ ๋ฉ์์ง, EPUB ๋ฉํ๋ฐ์ดํฐ
๐ Notes for Existing Users
- ๊ธฐ์กด v1.1.0 ์ฌ์ฉ์๋ ์์ ํ๊ฒ v1.1.1๋ก ์ด์ ๊ฐ๋ฅ. ์ค์ ๋ฐ์ดํฐ(
FileNexusSuite.json)์ ์ถ๋ ฅ ํ์ผ(Output/)์ ๊ทธ๋๋ก ๋ณด์กด๋ฉ๋๋ค / Existing v1.1.0 users can safely upgrade to v1.1.1. Settings (FileNexusSuite.json) and output files (Output/) are preserved - ๋ณธ ๋ฆด๋ฆฌ์ฆ ์ ์ฉ ํ Settings โ Language์์ ์ธ์ด ๋ณ๊ฒฝ ์ ๋์๋ง ํ ์คํธ๋ ํจ๊ป ๋ณ๊ฒฝ๋ฉ๋๋ค / After this release, changing language from Settings โ Language will also update the help text in real time
๐ Release Signing
- Release commit
[PLACEHOLDER]โ SSH ์๋ช (Ed25519), GitHub Verified ๋ฑ์ง / SSH-signed (Ed25519), GitHub Verified - ํ๊ทธ
v1.1.1SSH ์๋ช , GitHub Verified ๋ฑ์ง / Tagv1.1.1SSH-signed, GitHub Verified - GitHub Actions CI
windows-latest+ Python 3.10 ํ๊ฒฝ์์ ์๋ ํต๊ณผ / GitHub Actions CI passed onwindows-latest+ Python 3.10
Tag: v1.1.1
Released: [PLACEHOLDER โ YYYY-MM-DD]
Build: FileNexusSuite_v1.1.1_win64.zip ([PLACEHOLDER] MB)
๊น์ ๊ธฐ์ ๋ณํ ์ด๋ ฅ์
CHANGELOG.md์ฐธ์กฐ / For detailed technical changes, seeCHANGELOG.md
๐ผ
File Nexus Suite v1.1.0
v1.1.0 โ ๋ชจ๋ํ์ ๋์์ธ ํด๋ฆฌ์ฑ: Qt Linguist ๋ฒ์ญ ์์คํ ์ ํ + ํฌํผ/ํ ๋ง ๋ชจ๋ ๋ถ๋ฆฌ + ์ฌ์ด๋๋ฐยท์งํ๋ฅ ํค ํตํฉ / Modularization and Design Polishing: Qt Linguist Translation System Migration + Helper/Theme Module Extraction + Sidebar & Progress Tone Unification
v1.1.0์ v1.0.11์ ์ฝ๋ ๋ณธ์ง ๊ฐํ ๋ค์ ์๋ฆฌ์์, ๋ชจ๋ํ์ ๋์์ธ ํด๋ฆฌ์ฑ์ด ๋ชจ์ด๋ ์๋ฆฌ์
๋๋ค. ๋ณธ ๋ฆด๋ฆฌ์ฆ๋ ์ธ ๋ฌถ์(ํฌํผ ํจ์์ ํ
๋ง ์์คํ
์ ๋ชจ๋ ๋ถ๋ฆฌ, Qt Linguist ๋ฒ์ญ ์์คํ
์ ํ, ์ฌ์ด๋๋ฐ ์นด๋์ Batch Renamer ์งํ๋ฅ ๋ค์ด์ผ๋ก๊ทธ์ ๋์์ธ ํค ํตํฉ)์ผ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ๋ณธ์ฒด ๋ชจ๋์ ํฌํผ์ ํ
๋ง ์์คํ
๋ถ๋ฆฌ๋ฅผ ํตํด ์ฝ 15,662์ค์์ 13,274์ค๋ก ์ถ์๋์์ผ๋ฉฐ, ๋ฒ์ญ ์์คํ
์ ์ธ๋ผ์ธ Python ๋์
๋๋ฆฌ์์ Qt Linguist .ts/.qm ๋ฐํ์ ์์์ผ๋ก ์ ํ๋์ด ๋ฐ์ดํฐ ๊ณ์ธต์ด Python ์์ค ์ธ๋ถ๋ก ์ด์ ๋์์ต๋๋ค. ์ฒซ ์คํ ์ ์ด์์ฒด์ ์ ์ธ์ด ์ค์ ์์ UI ์ธ์ด๊ฐ ์๋ ๊ฐ์ง๋ฉ๋๋ค.
v1.1.0 follows v1.0.11's code essence deepening by gathering modularization and design polishing artifacts. This release bundles three threads (helper utilities and theme system extracted into sibling modules, Qt Linguist translation system migration, design tone unification across sidebar cards and Batch Renamer progress dialog). The main module shrinks from roughly 15,662 to 13,274 lines through helper and theme system extraction; the translation system migrates from an inline Python dictionary to Qt Linguist
.ts/.qmruntime files, moving the data layer outside the Python source. The UI language is auto-detected from the OS settings on first launch.
โจ ์ฃผ์ ๋ณ๊ฒฝ / Major Changes
-
Qt Linguist ๋ฒ์ญ ์์คํ ์ ํ / Qt Linguist translation system migration
- ๊ธฐ์กด
FileNexusSuite.py๋ด๋ถ ์ธ๋ผ์ธTRANSLATIONS๋์ ๋๋ฆฌ๊ฐ Qt Linguist.ts(์์ค) +.qm(๋ฐํ์) ์์์ผ๋ก ์ปดํ์ผ๋จ. ์์ค ํ์ผ์translations_ts/์๋, ๋ฐํ์ ํ์ผ์translations/์๋, 5๊ฐ ์ธ์ด (ko/en/ja/zh_cn/zh_tw) ร 25๊ฐ ์ปจํ ์คํธ ร 503๊ฐ ๋ฒ์ญ / InlineTRANSLATIONSdict migrated to Qt Linguist.ts(source) +.qm(runtime) files. Source files undertranslations_ts/, runtime files undertranslations/, 5 languages ร 25 contexts ร 503 translations - ๋ชจ๋ UI ๋ฌธ์์ด์ด ๊ธฐ์กด
_t(key)์์์์self.tr(key)๋ก ์ ํ๋์ด ๋ฐํ์์QTranslator๋ฅผ ํตํด ํด์๋จ / All UI strings migrated from_t(key)toself.tr(key), resolved at runtime throughQTranslator - OS ์ธ์ด ์๋ ๊ฐ์ง โ ์ฒซ ์คํ ์ ์ด์์ฒด์ ์ธ์ด ์ค์ ์ ๊ธฐ๋ฐํด UI ์ธ์ด๊ฐ ์๋ ์ ํ๋๋ฉฐ, ์ค์ ์์ ๋ณ๊ฒฝ ๊ฐ๋ฅ / OS language auto-detection on first launch; changeable in Settings
scripts/update_translations.bat์scripts/add_ts_contexts.pyํฌํผ ์คํฌ๋ฆฝํธ๊ฐlupdate/lrelease์ฌ์ดํด์ ์๋ํ. ๋ฒ์ญ ํ์ ์.tsํ์ผ์ Qt Linguist๋ก ์ง์ ํธ์งํ๋ฉฐ, UI ๋ณ๊ฒฝ ํ.qm๋ฐํ์ ํ์ผ์ ์ฌ์์ฑ / Helper scripts automate thelupdate/lreleasecycle; translators edit.tsfiles directly in Qt Linguist, with.qmfiles regenerated after UI changes
- ๊ธฐ์กด
-
ํฌํผ ํจ์ ๋ฐ ํ ๋ง ์์คํ ๋ชจ๋ ๋ถ๋ฆฌ / Helper utilities and theme system extracted into sibling modules
fns_utils.py์ ๊ท โ 17๊ฐ์ ์์ Python ํฌํผ ํจ์๊ฐ ๋ณธ์ฒด ๋ชจ๋์์ ๋ถ๋ฆฌ๋จ. ์ซ์/์์ฐ ์ ๋ ฌ ์ ํธ๋ฆฌํฐ (_pad,extract_number,_get_leading_num,extract_number_auto,auto_width_for_group,detect_common_prefix,natural_sort_key,_SKIP_FILES), Tag Editor ํต์ฌ ๋ก์ง (remove_tag_from_name,_build_tag_str,add_tag_to_name,depad_name,apply_renames), HTML escape/unescape ์ ํธ๋ฆฌํฐ (_de,_h2t,_strip_xml_illegal,_ex) / Newfns_utils.pyโ 17 pure-Python helpers extracted from the main modulefns_theme.py์ ๊ท โ 9๊ฐ ํ ๋ง ํ๋ ํธ ๋์ ๋๋ฆฌ (THEMES, ํ ๋ง๋ณ 18๊ฐ ํค), 5๊ฐ ํ ๋ง ํฌํผ (_hex_rgba,_combo_arrow_url,_detect_system_theme,_resolve_theme,make_style), ๊ทธ๋ฆฌ๊ณ_apply_card_shadow์์ ฏ ํฌํผ๊ฐ ๋ถ๋ฆฌ๋จ._apply_card_shadow์ ์๊ทธ๋์ฒ๋_apply_card_shadow(widget)์์_apply_card_shadow(widget, border_color)๋ก ๋ณ๊ฒฝ๋์ดBORDERglobal ์์กด์ ๋ช ์์ ์ธ์๋ก ํ๊ณ ๋ชจ๋์ ์๊ธฐ-์๊ฒฐ๋ก ์ ์ง / Newfns_theme.pyโ 9-theme palette dict, 5 theme helpers, and_apply_card_shadowwidget helper extracted; signature change breaks theBORDERglobal dependency- ๋ ๋ชจ๋ ๋ชจ๋ PySide6 ์ธ ์ธ๋ถ ์์กด์ด ์์ผ๋ฉฐ ๋ณธ์ฒด ๋ฐํ์ ์ํ์ ๋ ๋ฆฝ์ ์ผ๋ก ์ฌ์ฌ์ฉ ๊ฐ๋ฅ. ๋ณธ์ฒด ๋ชจ๋์ ๋ ๋ถ๋ฆฌ๋ฅผ ํตํด ์ฝ 532์ค ๊ฐ์ (15,662 โ 15,130) / Both modules are independent of FNS runtime state; main module shrinks by roughly 532 lines through these two extractions
-
ํ์ผ ๋ชฉ๋ก ์์ ฏ์ ๊ฐ์ํ base ํด๋์ค ํตํฉ / File-list widget virtualization unification
- ๊ฑฐ์ ๋์ผํ
QTreeWidgetํจํด์ ๊ณต์ ํ๋ 5๊ฐ ์์ ฏ (MergeFileTree,BulkFixerFileList,TextConverterFileList, Tag Editor์_file_list์_tree)์ด 3๊ฐ์ ์ ๊ท base ํด๋์ค๋ก ํตํฉ / Five widgets sharing a near-identicalQTreeWidgetpattern unified under three new base classes FileListModel(QAbstractTableModel)โ ๋ฒ์ฉ ํ๋ฉด ๋ชฉ๋ก ๋ชจ๋ธ (์๋ธํด๋์ค ์ ๊ณตCOLUMNS๊ธฐ๋ฐ ๋ ๋๋ง,PATH_ROLE = UserRole+4,sort()/sort_key());FileListBase(QTableView)โ ๊ณตํต ๊ณ์ฝ (COLUMNS,COLUMN_WIDTHS,SELECTION_MODE๋ฑ 6๊ฐ ํด๋์ค ์์ฑ + ๊ณตํต ๋ฉ์๋);DragDropMixinโ drag-drop ๋์์ด ํ์ํ 3๊ฐ ์๋ธํด๋์ค๋ฅผ ์ํ mixin /FileListModel,FileListBase,DragDropMixinโ base classes consolidating shared model/view/drag-drop logic- ๊ฒฐ๊ณผ: v1.0.11์์ Batch Renamer ๋ฏธ๋ฆฌ๋ณด๊ธฐ์๋ง ์ ์ฉ๋์๋
QAbstractTableModel๊ธฐ๋ฐ ๊ฐ์ํ ๋ ๋๋ง์ด ๋ค์ฏ ์์ ฏ ๋ชจ๋์ ์ ์ฉ๋์ด, ํฐ ํ์ผ ๋ชฉ๋ก๋ ์ด๋ ํญ์์๋ ํ๋ฉด์ ๋ณด์ด๋ ํ๋ง ๋ ๋๋ง๋จ. ์ฝ 350์ค์ ์ค๋ณต ์ฝ๋๊ฐ 270์ค์ ๊ณต์ base๋ก ๋์ฒด /QAbstractTableModelvirtualization (previously only on Batch Renamer preview) now applies uniformly to all five widgets; roughly 350 lines of duplicated subclass code replaced by 270 lines of shared base
- ๊ฑฐ์ ๋์ผํ
-
์ฌ์ด๋๋ฐ ์นด๋์ ์๊ฐ์ ๋ถ๋ฆฌ๊ฐ ๊ฐํ / Sidebar card visual separation strengthened
- ์ฐ์ธก ์ฌ์ด๋๋ฐ ์นด๋๋ค (Batch Renamer์ Number Reset / Start Number / Digits / Prefix-Suffix ๋ฑ)์ด ์ ๋ณด ๋ฐ๋๋ ์ ์งํ๋ฉด์ ์ด์ง ๋ ์๋ ํํ๋ก ์๊ฐ์ ์ผ๋ก ๊ทธ๋ฃนํ๋จ / Cards in the right-hand sidebar feel slightly elevated and visually grouped while preserving information density
- ์ธ ๊ฐ์ง ํ์กฐ ๋ณ๊ฒฝ: (1) ์ ๊ท
_apply_card_shadow(widget)ํฌํผ๊ฐ ๋ชจ๋QGroupBox์ ๋ถ๋๋ฌ์ดQGraphicsDropShadowEffect์ ์ฉ (blur radius 18, Y offset 3,BORDER์์ alpha 0.5๋ก derive); (2) ๊ธ๋ก๋ฒQGroupBox๋ฃฐ์margin-bottom:6px์ ๊ฐํ๋ padding ์ถ๊ฐ; (3)QGroupBox::title์์ดMUTED์์ACCENT๋ก ๋ณ๊ฒฝ๋์ด ์นด๋ ํค๋๊ฐ ์น์ ๋ง์ปค์ฒ๋ผ ์ฝํ / Three coordinated changes: subtleQGraphicsDropShadowEffecton everyQGroupBox, stronger margin/padding on the globalQGroupBoxrule, andQGroupBox::titlecolor shifted fromMUTEDtoACCENT AppSuite._apply_card_shadows()๊ฐ__init__๊ณผapply_theme()์์ ํธ์ถ๋์ด ๋ผ์ดํธ/๋คํฌ ํ ๋ง ๋ณ๊ฒฝ ์ ๊ทธ๋ฆผ์ ์์ดBORDER๋ฅผ ๋ฐ๋ผ ๊ฐฑ์ / Shadow color tracksBORDERacross light/dark theme switches
-
Batch Renamer ์งํ๋ฅ ๋ค์ด์ผ๋ก๊ทธ FNS ํค ๋งค์น / Batch Renamer progress dialog tone-matched with FNS theme
- Batch Renamer์ ingest worker์ rename worker๊ฐ ์ฌ์ฉํ๋ Qt ๊ธฐ๋ณธ
QProgressDialog๋ฅผ ์ ๊ท_build_progress_dlgํฌํผ๋ก ๋น๋ํ FNS ํค ๋ชจ๋ฌ ์งํ๋ฅ ๋ค์ด์ผ๋ก๊ทธ๋ก ๊ต์ฒด. ๊ธฐ์กด_confirm/_build_dlg์์ ํ๋ ํธ ๊ณ์น (SURFACE๋ฐฐ๊ฒฝ,ACCENT์งํ ๋ฐ chunk,BORDER์ธ๊ณฝ์ ,_btn_style(False)์ทจ์ ๋ฒํผ) / Qt's defaultQProgressDialogreplaced with an FNS-toned modal dialog inheriting the_confirm/_build_dlgpalette - ๊ธฐ์กด ๋์ ๋ชจ๋ ๋ณด์กด: ๋ชจ๋ฌ (
Qt.WindowModal), 400 ms ์ต์ ํ์ ์ง์ฐ (QTimer.singleShot(400, ...)+ ์๋ฃ ํ๋๊ทธ๋ก ์งง์ ์์ ์ ๊น๋นก์ ๋ฐฉ์ง), ์๋ฃ ์ ์๋ ๋ซํ, ์ทจ์ ์ ํ (worker.request_cancel()).QProgressDialog์ฌ๋ณผ์QtWidgets์ํฌํธ์์ ์ ๊ฑฐ / All prior behaviors preserved: modal, 400 ms minimum-duration delay, auto-close on completion, cancel propagation
- Batch Renamer์ ingest worker์ rename worker๊ฐ ์ฌ์ฉํ๋ Qt ๊ธฐ๋ณธ
๐ฆ ์ถ๊ฐ / Added
_ElideLabel(QLabel)ํฌํผ ์์ ฏ /_ElideLabel(QLabel)helper widget- ๋๋น๊ฐ ๋ด์ฉ๋ณด๋ค ์ข์ผ๋ฉด ํ
์คํธ๋ฅผ
'...'๋ก ์ฐ์ธก ์ ์ญํ๋ ์ฌ์ฌ์ฉ ๊ฐ๋ฅ ๋ผ๋ฒจ. ์ ์ฒด ํ ์คํธ๋_full_text์ ๋ณด๊ด๋๊ณresizeEvent์์ ์ ์ญ์ด ์ฌ์ ์ฉ๋์ด ๋ถ๋ชจ ๋๋น ๋ณํ์ ๋ฐ๋ผ ์ ์ญ ์์น๊ฐ ๋์ ์ผ๋ก ๊ฐฑ์ ๋จ / Right-elides text with'...'when narrower than content; full text stored in_full_textand re-applied onresizeEvent - ๊ฐ๋ก
QSizePolicy๊ฐIgnored๋ก ์ค์ ๋์ด ๊ธด ๋ฌธ์์ด์ด ๋ถ๋ชจ์ ์ต์ ๋๋น๋ฅผ ํค์ฐ๋ ์ผ์ด ์์. ์ ์ฒด ํ ์คํธ๋ ๋ชจ๋setText()ํธ์ถ์์ ํดํ์ผ๋ก ๋ ธ์ถ๋จ / HorizontalQSizePolicy.Ignoredso long strings never inflate the parent's minimum width; full text exposed via tooltip - ํ์ฌ๋ Text Merger์ ์ ํ ์์ฝ ๋ผ๋ฒจ์์ ์ฌ์ฉ๋๋ฉฐ, ๊ฐ์ฉ ๋๋น๋ณด๋ค ๊ธธ์ด์ง ์ ์๋ ๋ชจ๋ ์ํ ๋ผ๋ฒจ์ ์ ์ฉ ๊ฐ๋ฅ / Currently used by Text Merger's selection summary label; available for any future status label
- ๋๋น๊ฐ ๋ด์ฉ๋ณด๋ค ์ข์ผ๋ฉด ํ
์คํธ๋ฅผ
๐ ์์ / Fixed
-
Text Merger ์ ํ ๋ผ๋ฒจ ๋ ์ด์์ ๊นจ์ง (๋ค์ค ํ์ผ ์ ํ ์) / Text Merger selection-label layout breakage with multiple files selected
- ํ๋จ ์ ํ ์์ฝ ๋ผ๋ฒจ (
_lbl_selection)์ด ์ด๋/์ญ์ ๋ฒํผ๊ณผ ๊ฐ์ ๊ฐ๋ก ํ์ ๊ณต์ ํ๊ณ ์์ด, ๋ค์์ ํ์ผ์ด ์ ํ๋๋ฉด ๋ผ๋ฒจ์ ๊ธธ์ด๊ฐ ์ข์ธก ํจ๋์ ์ต์ ๋๋น๋ฅผ ํค์ ์ฐ์ธก(์ ์ฅ ์ค์ ) ํจ๋์ ํ๋ฉด ๋ฐ์ผ๋ก ๋ฐ์ด๋ด๊ณ ์ด๋/์ญ์ ๋ฒํผ ํ ์คํธ๋ ์๋ฆฌ๋ ํ์ / The bottom selection summary label shared a horizontal row with the move/delete buttons; with many files selected, the label's intrinsic width inflated the left panel's minimum size and pushed the right panel off-screen - ์์ : (1) ๋ผ๋ฒจ์
bot_btn_row์๋์ ๋ณ๋ ์ธ๋ก ํ์ผ๋ก ์ด๋, (2)_ElideLabelํฌํผ(์ Added ์ฐธ๊ณ )๋ก ๊ฐ์ธ ๊ฐ๋กminimumSize๋ฅผ ๋ฌด์ํ๊ณ ๋๋น๊ฐ ์ข์ ๋ ์ฐ์ธก ์ ์ญ. ์ ์ฒด ์ ํ ํ ์คํธ๋ ํดํ์ผ๋ก ๊ทธ๋๋ก ํ์ธ ๊ฐ๋ฅ / Fixed by moving the label to its own row and wrapping it in_ElideLabel; full selection text remains accessible via the tooltip - v1.0.11๋ถํฐ ์กด์ฌํ๋ ๋ฌธ์ ์ด๋ฉฐ, v1.1.0 base ํด๋์ค ํตํฉ์ ํ๊ท๊ฐ ์๋์ด ํ์ธ๋จ / Issue had been present since v1.0.11; not a regression of the v1.1.0 base-class refactor
- ํ๋จ ์ ํ ์์ฝ ๋ผ๋ฒจ (
-
PyInstaller ๋น๋์ ๋ฒ์ญ ํ์ผ ๋๋ฝ / Translation files missing in PyInstaller frozen build
- ๋น๋๋ ์คํํ์ผ์ด ํ๊ตญ์ด Windows ํ๊ฒฝ์์๋ ์์ด๋ง ํ์๋๊ณ ์ค์ > Language ๋ฉ๋ด์ ๋ค๋ฅธ 4๊ฐ ์ธ์ด๊ฐ ๋ํ๋์ง ์๋ ํ์. ๋ ์์ธ: (1)
build_pyinstaller.py์--add-dataํ๋๊ทธ๊ฐ ์์ดtranslations/*.qmํ์ผ์ด frozen ๋น๋์ ๋ฒ๋ค๋ง๋์ง ์์, (2)_resource_dir()์ดos.path.dirname(sys.executable)์ ๋ฐํํ์ฌ PyInstaller 6.x onedir ๋ชจ๋์ contents directory (_internal/)๋ฅผ ์ฐพ์ง ๋ชปํจ / Built executable silently fell back to English on all platforms because--add-datawas missing from the build script and_resource_dir()did not resolve to PyInstaller 6.x's_internal/contents directory - ์์ : (1)
build_pyinstaller.py์--add-data "translations;translations"์ถ๊ฐ, (2)_resource_dir()์ดgetattr(sys, '_MEIPASS', os.path.dirname(sys.executable))์ ๋ฐํํ๋๋ก ๋ณ๊ฒฝ. 5๊ฐ ์ธ์ด ๋ชจ๋ frozen ๋น๋์์ ์ ์ ๋ ธ์ถ / Fixed by adding--add-datato the PyInstaller command and updating_resource_dir()to usesys._MEIPASS; all five languages restored in the frozen build
- ๋น๋๋ ์คํํ์ผ์ด ํ๊ตญ์ด Windows ํ๊ฒฝ์์๋ ์์ด๋ง ํ์๋๊ณ ์ค์ > Language ๋ฉ๋ด์ ๋ค๋ฅธ 4๊ฐ ์ธ์ด๊ฐ ๋ํ๋์ง ์๋ ํ์. ๋ ์์ธ: (1)
๐งช ํ ์คํธ ์๋ํ / Test Automation
- 594 โ 513 passing (-81), 0 failures / 0 errors / 5 intentional skips (ํ๋ฆผ ๋ก์ปฌ + Git ํด๋ ์ด์ค ๊ฒ์ฆ). Qt Linguist ๋ง์ด๊ทธ๋ ์ด์
์์
TRANSLATIONS๋์ ๋๋ฆฌ literal์ ๋ํ source-grep ํ ์คํธ๊ฐ ๋ชจ๋ ์ ๊ฑฐ๋์๊ธฐ ๋๋ฌธ (๋์ ๋๋ฆฌ๊ฐ Python ์์ค์ ๋ ์ด์ ์กด์ฌํ์ง ์์) / 594 โ 513 passing (-81), Hanrim local + Git folder dual verification. Net reduction reflects removal of source-grep tests against theTRANSLATIONSdict literal (no longer in Python source after Qt Linguist migration) - Qt Linguist ๋ฐํ์์ฉ ํ
์คํธ ์ค์ํธ ๋ง๋ฌด๋ฆฌ โ ๋๋ฑํ ์ปค๋ฒ๋ฆฌ์ง๊ฐ
TestV105RegressionModule(self.tr()ํธ์ถ ๊ธฐ๋ฐ ๋ฐํ์ ๋ฒ์ญ...
File Nexus Suite v1.0.11
v1.0.11 โ ์ฝ๋ ๋ณธ์ง ๊ฐํ: Batch Renamer ๋์ฉ๋ ์๋ต์ฑ ์ฌ์์ฑ + ์๋ฌธ ๊ธฐ๋ณธ ์ ํ + 12๊ฐ ์ธ๋ผ์ธ UI i18n migration / Code Essence Deepening: Batch Renamer Scalability Rewrite + English-First Transition + 12 Inline UI i18n Migration
v1.0.11์ v1.0.10์ MIT ์ ํ๊ณผ OSS ๊ฒฐ์ ์์์ ๋ค์ ์๋ฆฌ์์, ์ฝ๋ ๋ณธ์ง์ OSS-facing ์์์ผ๋ก ๋ ๊น๊ฒ ๋ค์ง๋ ํธ๋์ ๋๋ค. ๋ณธ ๋ฆด๋ฆฌ์ฆ๋ ์ธ ํธ๋(Batch Renamer ๋์ฉ๋ ์๋ต์ฑ ์ฌ์์ฑ, ๋ฉ์ธ ์ฝ๋ + ๋ถ์ ๋ฌธ์ ์๋ฌธ ๊ธฐ๋ณธ ์ ํ, 12๊ฐ ์ธ๋ผ์ธ UI ๋ฌธ์์ด TRANSLATIONS ์ด์ )์ ๋ฌถ์์ ๋๋ค. 154,895 ํ์ผ / 2,714 ํด๋ / 86.8 GB ๊ท๋ชจ ๋ฐ์ดํฐ์ ์์ ๋ฐ์ํ๋ ์์ญ ์ด~์๋ถ ๋ฉ์ถค ํ์์ด ํ๋ ธ์ผ๋ฉฐ โ 103,716 ํ์ผ / 1,767 ํด๋ / 32.7 GB์์ โ ๊ฒ์ฆ๋์์ต๋๋ค.
v1.0.11 follows v1.0.10's decisive turning point: OSS opening by deepening the code itself for OSS-facing posture. This release bundles three tracks (Batch Renamer scalability rewrite, English-first transition for main code + supporting documents, 12 inline UI strings migrated to TRANSLATIONS). The tens-of-seconds to minutes freeze observed at 154,895 files / 2,714 folders / 86.8 GB has been resolved โ verified at 103,716 files / 1,767 folders / 32.7 GB.
โจ ์ฃผ์ ๋ณ๊ฒฝ / Major Changes
-
Batch Renamer ๋์ฉ๋ ์๋ต์ฑ ์ฌ์์ฑ / Batch Renamer scalability rewrite
- ๋ฏธ๋ฆฌ๋ณด๊ธฐ ํ
์ด๋ธ์ ๊ฐ์ํ๋
QTableView+QAbstractTableModel(์ ๊ทBatchPreviewModel+BatchRowHeightDelegate)๋ก ์ ํ โ ๊ธฐ์กดQTableWidget์ด ํ๋ฉด ๊ฐฑ์ ๋ง๋ค ์์ฑํ๋ ์ฝ 47๋ง ๊ฐ์QTableWidgetItem๋ถ๋ด ์ ๊ฑฐ._f_refresh/_p_refresh๋ ์ ๋ณ ์์ ฏ ๊ตฌ์ฑ ๋ก์ง์ดdata(index, role)๋ก ์ด๋ํ๋ฉด์ 23 / 21์ค์์ 4์ค๋ก ์ถ์ / Preview table converted to virtualizedQTableView+QAbstractTableModel(newBatchPreviewModel+BatchRowHeightDelegate) โ eliminates ~470,000QTableWidgetItemallocations per render._f_refresh/_p_refreshshrink from 23/21 lines to 4 lines as per-cell widget construction moves intodata(index, role) _f_ingest/_p_ingest์_f_do_rename/_p_do_rename์BatchIngestWorker(QThread)์BatchRenameWorker(QThread)๋ก ๋ฐฑ๊ทธ๋ผ์ด๋ ์คํ, ์ทจ์ ๊ฐ๋ฅํ ๋ชจ๋ฌQProgressDialog(ํด๋๋ณ ์งํ๋ฅ ) ๋ฐฉ์. rename worker ์์์๋ ๊น์ด ์ฐ์ ํด๋ ์ํ์WinError 5์ผ๊ด ์ฌ์๋ ๋ก์ง์ ๊ทธ๋๋ก ๋ณด์กด / Ingest and rename now run onBatchIngestWorker(QThread)/BatchRenameWorker(QThread)with a modalQProgressDialog(cancel + per-folder progress); the rename worker preserves the depth-first folder traversal and theWinError 5bulk-retry loop- ํด๋ / ํ์ผ ํญ์ด
'f'/'p'kindํ๋ผ๋ฏธํฐ๋ก ๋์ผ model / worker ํด๋์ค๋ฅผ ๊ณต์ / Both folder + file tabs share the same model / worker classes via a'f'/'p'kindparameter - 5๊ฐ ์ธ์ด์ i18n ํค 3๊ฐ ์ถ๊ฐ (
dlg_cancel,batch_ingest_progress,batch_rename_progress). ๋ worker ๋ค์ด์ผ๋ก๊ทธ์QProgressDialog์ฐฝ ์ ๋ชฉ๋ Qt ๊ธฐ๋ณธ๊ฐ (python,sys.argv[0]์ ๋)์์FileNexusSuite๋ก ์ฌ์ ์ / 3 new i18n keys ร 5 languages. Window title also overridden from Qt's default (python, fromsys.argv[0]) toFileNexusSuite
- ๋ฏธ๋ฆฌ๋ณด๊ธฐ ํ
์ด๋ธ์ ๊ฐ์ํ๋
-
๋ฉ์ธ ์ฝ๋ + ๋ถ์ ๋ฌธ์ ์๋ฌธ ๊ธฐ๋ณธ ์ ํ / English-first transition for main codebase + supporting documents
FileNexusSuite.pyํ๊ตญ์ด ์ฃผ์/docstring/๋๋ฒ๊ทธ ๋ก๊ทธ 1,133์ค์ ์๋ฌธ ์ ํ (์ฌ์ฉ์ ๋ ธ์ถ UI ๋ฌธ์์ด, ์ธ์ด ๋ถ๊ธฐ ๊ฐ์ด๋ ์ฝํ ์ธ , ์ฌ์ ํค/๊ฐ์ ํ๊ตญ์ด ๋ณด์กด). ์์ ์ฑ์ ์ํด ๋ commit ๋ถ๋ฆฌ: Step 1+2 (506์ค,f54bc81)์ Step 3 final (627์ค,177598b) / 1,133 lines of Korean comments/docstrings/debug logs translated to English (user-facing UI strings, language-branched guides, dictionary keys/values preserved). Split into two commits for safetytest_file_nexus.py๋ ๋์ผ ์์์ผ๋ก 277๊ฐ ๋งคํ (F1 L1โL3500: 90, F2 L3501โL4100: 120, F3 L4101โL4590: 67). 459 ๋ณดํธ ๋ผ์ธ(SAMPLE_KO_* ์ ๋ ฅ ๋ณ์, assertEqual ๊ธฐ๋๊ฐ, ํ๊ตญ์ด ์ธ์ฉ 9๊ฑด ๋ฑ)์ ์ธ์ด ์ค๋ฆฝ ๋์ ๊ฒ์ฆ ์ฝ๋๋ผ ๋ณด์กด /test_file_nexus.py: 277 mappings across 3 chunks. 459 protected lines preserved (SAMPLE_KO_* test inputs, assertEqual expected outputs, 9 Korean evidentiary citations)STORY.mdํ/์ ์ด์ค์ธ์ด ์์ (c469f6b),README.txt์๋ฌธ ๊ธฐ๋ณธ + ๋ค๊ตญ์ด ๋ผ๋ฒจ (3922250), ๋น๋ ๋ฉํ๋ฐ์ดํฐ ์๋ฌธ ์ ํ (7ca4f734) /STORY.mdbilingual,README.txtEnglish-first multilingual, build metadata translated
-
12๊ฐ ์ธ๋ผ์ธ UI ๋ฌธ์์ด TRANSLATIONS ์ด์ / 12 inline UI strings migrated to TRANSLATIONS
- 14๊ฐ ์ ๊ท ๋ฒ์ญ ํค ร 5๊ฐ ์ธ์ด = 70๊ฐ ํญ๋ชฉ ์ถ๊ฐ (
crash_*์์ธ ์ฒ๋ฆฌ ๋ค์ด์ผ๋ก๊ทธ /already_running_*์ค๋ณต ์คํ /rename_skip_*Batch Renamer ์คํต /lib_required_msgBulk Fixer ImportError ร 4 /dlg_info๋ค์ด์ผ๋ก๊ทธ ํค๋ fallback /help_*๋์๋ง ์ฐฝ) / 14 new translation keys ร 5 languages = 70 entries - dead code ์ ๊ฑฐ:
SHORTCUT_DEFS์'label'ํ๋ (๋ณ๋_sc_label_keys๋งต์ด i18n ํค ๋ณด์ , ํ ๋ฒ๋ ์ฝํ์ง ์๋ ์ฝ๋),_CARD_CFG์'label'ํ๋ (ํ ์๋ฆฌ๋ง ์ฌ์ฉ โ_theme_label()ํธ์ถ๋ก ๋์ฒด) / Dead code cleaned:SHORTCUT_DEFS['label']and_CARD_CFG['label'] - TRANSLATIONS ๋ฐ๊นฅ ํ๊ตญ์ด ๋ฌธ์์ด 191 โ 142 (-49). ๋จ์ 142๊ฑด์ ์๋๋ ๋ถ๋ถ (122๊ฑด
if lang == 'ko'๋ถ๊ธฐ ์ ๊ฐ์ด๋ ์ฝํ ์ธ , 7๊ฑด ํฐํธ/์ ์๊ถ/์ธ์ด๋ช , 4๊ฑด_section_iconsํธํ์ฑ lookup, 9๊ฑด ๊ธฐํ) / Korean string literals outside TRANSLATIONS reduced 191 โ 142
- 14๊ฐ ์ ๊ท ๋ฒ์ญ ํค ร 5๊ฐ ์ธ์ด = 70๊ฐ ํญ๋ชฉ ์ถ๊ฐ (
๐ฆ ์ถ๊ฐ / Added
- Batch Renamer ๊ทธ๋ฃน ํค๋ + ์ ์ด๋ฆ ์ปฌ๋ผ ํดํ / Batch Renamer tooltips on group header and new-name column
- ๊ธฐ์กด์ ์๋ณธ ํ์ผ๋ช
์ปฌ๋ผ์๋ง
setToolTip(full_path)๋ฐํ ์์์ด โ ๊ทธ๋ฃน ํค๋(๐ parent_folder)์ ์ ์ด๋ฆ ์ปฌ๋ผ์ ํดํ โ๋ผ ๊ธด ํ๊ตญ์ด ์ฑ ์ ๋ชฉ์ด๋ ์ฑํฐ ์ด๋ฆ์ด ์ปฌ๋ผ ๋๋น๋ก ์๋ ธ์ ๋ ํ๋์ ์ ์ฐฐ โ / Previously only original-name column hadsetToolTip(full_path)โ group header and new-name column had no tooltips _f_refresh/_p_refresh์์ชฝ์์ ์ธ ์๋ฆฌ(๊ทธ๋ฃน ํค๋ / ์๋ณธ ์ปฌ๋ผ / ์ ์ด๋ฆ ์ปฌ๋ผ)์ ์ผ๊ด ์ ์ฉ / Now applied symmetrically across both panels at three sites- ์๋ณธ๊ณผ ์ ์ด๋ฆ ํ์ ์ฌ์ด์ ๋์นญ์ฑ ๋ณต์ / Restores symmetry between original and new-name display
- ๊ธฐ์กด์ ์๋ณธ ํ์ผ๋ช
์ปฌ๋ผ์๋ง
๐ ์์ / Fixed
-
Batch Renamer (file mode) ๊ทธ๋ฃน๋ณ ์๋ฆฟ์ / per-group digit width
_p_calc_preview๊ฐ ๊ฐ์ฅ ํฐ ๊ทธ๋ฃน์ ํ์ผ ์์์ ๊ณ์ฐํ ๋จ์ผauto_d๊ฐ์ ๋ชจ๋ ๊ทธ๋ฃน์ ์ ์ญ ์ ์ฉ โ 9-ํ์ผ ๊ทธ๋ฃน์ด 100+ ํ์ผ ๊ทธ๋ฃน๊ณผ ๊ฐ์ 3์๋ฆฌ๋ก ๋ ๋๋ง๋๋ ๋ฌธ์ . ์ด์ ๊ฐ ๊ทธ๋ฃน์ด ์์ ์ ํ์ผ ์์ ๋ง์ถฐ ์๋ฆฟ์ ๊ณ์ฐ (grp_max_num = start + len(files) - 1) / Each group now computes its own digit width based on its own file count
-
Batch Renamer ingest ํตํฉ empty-folder ๋ค์ด์ผ๋ก๊ทธ / consolidated empty-folder dialog
- ๋น์ด์๋ ํด๋ ์ฌ๋ฌ ๊ฐ ๋๋๊ทธ ์ ํด๋๋ง๋ค ๋ชจ๋ฌ
_dlg_info๊ฐ ๋ ํ์ ํญ์ฃผ๋ก ~21+ ํด๋์์ ์ฑ ๊ฐ์ ์ข ๋ฃ ์ํ. ์ด์ ๋น ํด๋ ๋ชฉ๋ก์ ๋ชจ์ ๋จ์ผ ํตํฉ ๋ค์ด์ผ๋ก๊ทธ (โค10๊ฐ: ์ ์ฒด ํ์, >10๊ฐ: ์ฒ์ 10๊ฐ +... (+N)) / Skipped folders consolidated into a single dialog (โค10 paths shown, >10 truncated with... (+N))
- ๋น์ด์๋ ํด๋ ์ฌ๋ฌ ๊ฐ ๋๋๊ทธ ์ ํด๋๋ง๋ค ๋ชจ๋ฌ
-
์ค๊ตญ์ด ์ฌ์ ์ i18n ์ผ๊ด์ฑ / i18n consistency in Chinese dictionaries
zh_tw์ simplified ๋์ถ 2๊ฑด (tag_drop2,merge_sel_one),zh_cn์merge_sel_oneํค ๋๋ฝ. simplified ์ฌ์ฉ์๊ฐ_t์ zh_cn โ zh_tw fallback path๋ฅผ silentํ๊ฒ ํ๊ณ traditional ๊ฐ์ ๋ฐ๋ ์ฐ์ฐํ ์๊ฐ ์ผ์น ํ์. ์์ชฝ ์ฌ์ ์ด ๊ฐ์์ ์คํฌ๋ฆฝํธ๋ก ํค๋ฅผ ๊ฐ๋๋ก ์ ์ / Both dictionaries now carry the keys in their respective scripts
-
legacy
%APPDATA%config fallback ์ ๊ฑฐ / Dropped legacy%APPDATA%config fallback in_show_already_running_popup- pre-v1.0.x try-block ์์ฌ โ
~/AppData/Roaming/FileNexusSuite/FileNexusSuite.json์ ๋จผ์ ์๋ ํ__file__์๋ ๊ฒฝ๋ก fallback. ๋ ๋ถ๊ธฐ ๋ชจ๋ dead since v1.0.x onward (_CONFIG_PATH = _app_dir() / "FileNexusSuite.json"๋ง ์ฌ์ฉ). 14์ค โ 10์ค / 14-line probe-and-fallback reduced to 10 lines (-4 lines, single source of truth)
- pre-v1.0.x try-block ์์ฌ โ
๐ ๋ณ๊ฒฝ / Changed
- Batch Renamer ingest: O(1) ์ค๋ณต ๊ฒ์ฌ / O(1) duplicate-path check
- ๊ธฐ์กด ๊ทธ๋ฃน๋ค์ ๋ํ O(Nยฒ)
any()์ ํ ๊ฒ์ฌ๋ฅผset์กฐํ๋ก ๊ต์ฒด. ํด๋ ingest (_f_ingest)์ ํ์ผ ingest (_p_ingest,os.walk์ฌ๊ท path ํฌํจ) ์์ชฝ์ ๋์นญ ์ ์ฉ. ~2,700 ํด๋ ์ผ๊ด ๋๋๊ทธ ์ ๋ฉ์ธ ์ค๋ ๋ CPU ์๊ฐ ~170ms ์ ์ฝ /setlookup replacing O(Nยฒ)any()linear scan, saves ~170 ms on 2,700 folders dragged
- ๊ธฐ์กด ๊ทธ๋ฃน๋ค์ ๋ํ O(Nยฒ)
๐งช ํ ์คํธ ์๋ํ / Test Automation
- 535 โ 594 passing (+59), 61 classes (+3), 0 failures / 0 errors / 5 skipped (ํ๋ฆผ ๋ก์ปฌ + Git ํด๋ ์ด์ค ๊ฒ์ฆ) / 535 โ 594 passing (+59), 61 classes (+3), zero failures/errors, 5 intentional skips (Hanrim local + Git folder dual verification)
TestBatchRenamerDigitWidth(+20) โ_p_calc_preview์ ๊ทธ๋ฃน๋ณ digit width ๋ก์ง ์ํจ์ ์ถ์ถ (auto/nopad/pad2/pad3 ๋ชจ๋ ร ๊ฒฝ๊ณ ํ์ผ ์ ร ์์๊ฐ + per-group independence) / Pure-function extraction of per-group digit-width logicTestBatchRenamerEmptyFolderDialog(+5 โ -5 skipped) โ ํตํฉ empty-folder dialog์ ํตํฉ ๊ฒ์ฆ. asyncBatchIngestWorker๊ฐ_BarePanel์์์์๋QObject๊ฐ โ๋ผ skip ์์. ํตํฉ ๋์ ์์ฒด๋_run_ingest_worker.on_done()์์์ ๋ณด์กด๋จ / Integration test of consolidated empty-folder dialog (5 skipped due to async worker requirement)TestBatchRenamerScenarioB(+5) โ ์๋๋ฆฌ์ค B์ source-grep ๊ฒ์ฆ. 4 ์ ๊ท ํด๋์ค (BatchPreviewModel/BatchRowHeightDelegate/BatchIngestWorker/BatchRenameWorker) + PySide6 imports +QTableView()๊ต์ฒด + workerkind๊ฒ์ฆ + model ๊ณต๊ฐ API / Source-grep checks for scenario B classes (PySide6 not required)_run_fix์๋ฌธ sibling ํ ์คํธ (+29) โ 6 ํด๋์ค ร ์๋ฌธ ์๋งค ํ ์คํธ,_SENT_END = '.!?โฆใ๏ผ๏ผโฅใใ๏ผ)}>]"\''์ ์ธ์ด ์ค๋ฆฝ ๋์์ ์๋ฌธ ์ ๋ ฅ์ผ๋ก ๊ฒ์ฆ. 12 SAMPLE_EN_* fixtures (CC0 1.0) ์ถ๊ฐ / 29 English sibling tests across 6 classes- 8 unclosed file handle ์ ๊ฑฐ โ
open(path, encoding='utf-8').read()์ํฐํจํด์with open(...) as _f์์์ผ๋ก ์ ์ . ResourceWarning 8 โ 0 / 8 unclosed file handles closed (ResourceWarnings 8 โ 0)
๐ ํ์ผ ๋ณ๊ฒฝ / File Changes
| ํ์ผ / File | ๋ณ๊ฒฝ / Change |
|---|---|
FileNexusSuite.py |
14,915 โ 15,347 ์ค (+432) โ ์๋๋ฆฌ์ค B refactor + i18n migration + python ์ ๋ชฉ ์ ์ / Scenario B refactor + i18n migration + python title fix |
test_file_nexus.py |
4,798 โ 5,008 ์ค (+210) โ ์๋ํ ํ ์คํธ +59๊ฑด / +59 automated tests |
LICENSE |
๋ณ๊ฒฝ โ (v1.0.10 ๊ทธ๋๋ก ๋ณด์กด) / Unchanged |
version_info.txt |
4๊ณณ ๊ฐฑ์ (filevers / prodvers / FileVersion / ProductVersion) / Version (4 locations) updated |
README.md / README_KO.md |
version ๋ฑ์ง (1.0.10 โ 1.0.11) + tests ๋ฑ์ง (589 โ 594 passing) / version + tests badges updated |
README.txt |
v1.0.11 ๊ฐฑ์ / v1.0.11 updated |
SECURITY.md |
Supported Versions ๊ฐฑ์ (1.0.10 โ 1.0.11) / Supported Versions updated |
CHANGELOG.md / CHANGELOG_KO.md |
v1.0.11 ์น์ ์ถ๊ฐ (์๋๋ฆฌ์ค B + python ์ ๋ชฉ ์ ์ ํก์) / v1.0.11 section added |
๐ ๋ฆด๋ฆฌ์ฆ ์๋ช / Release Signing
- ๋จ์ผ Release ์ปค๋ฐ + SSH ์๋ช
(Ed25519, fingerprint
SHA256:4H2f7lrFfI4u0YP0dpp6N9BQH2f74iKjjMRHu7lyjKI) / Single Release commit + SSH signature - ์ปค๋ฐ ๋ฉ์์ง / Commit message:
Release v1.0.11: Batch Renamer scalability + English-first transition + 12 inline UI i18n - Commit hash:
3ca7987 - ํ๊ทธ
v1.0.11SSH ์๋ช , GitHub Verified ๋ฑ์ง / Tagv1.0.11SSH-signed, GitHub Verified badge - GitHub Actions CI
windows-latest+ Python 3.10 ํ๊ฒฝ์์ ์๋ ํต๊ณผ / GitHub Actions CI passed onwindows-latest+ Python 3.10
โ ์๋ ค์ง ์ด์ / Known Issues
- ๋ณธ ๋ฆด๋ฆฌ์ฆ์์ ์ ๊ท ์๋ ค์ง ์ด์ โ โ v1.0.10์ *`test_file_nexus.py...
File Nexus Suite v1.0.10
v1.0.10 โ MIT ์ ํ๊ณผ OSS ๊ฒฐ์ ์์์ : ๋ผ์ด์ ์ค ์ ํ + LGPL ํธํ์ฑ ๋ช ์ํ + SignPath OSS Sponsorship ์ ์ฒญ / The Start of the OSS Turn: License Transition + LGPL Compatibility Documentation + SignPath OSS Sponsorship Application
v1.0.10์ v1.0.5 ~ v1.0.9์ 5๊ฐ ๋ฆด๋ฆฌ์ฆ๋ก ๋์ ๋ v1.0.x ์๋ฆฌ์ฆ ์ธํ๋ผ๋ฅผ OSS ์ปค๋ฎค๋ํฐ๋ก ๊ฐ๋ฐฉํ๋ ๊ฒฐ์ ์ ์ ํ์ ์
๋๋ค. ๋ณธ ๋ฆด๋ฆฌ์ฆ๋ ์ธ ํธ๋(๋ผ์ด์ ์ค ์ ํ Freeware โ MIT, LGPL ํธํ์ฑ ๋ช
์์ ๋ฌธ์ํ, SignPath OSS Sponsorship ์ ์ฒญ ํธ๋)์ ๋ฌถ์์ด๋ฉฐ, ์ฝ๋ ๋ณ๊ฒฝ๋์ v1.0.5~v1.0.9 ์ด๋ค ๋ฆด๋ฆฌ์ฆ๋ณด๋ค๋ ์ ์ต๋๋ค(FileNexusSuite.py ๋ผ์ธ ์ ๋ณํ 0, ํ
์คํธ ๋ด์ฉ๋ง ๋ณ๊ฒฝ). ๊ทธ๋ฌ๋ ์๋ฏธ ๋ณํ๋ ๊ฐ์ฅ ํฝ๋๋ค โ ์ฌ์ฉ์๊ฐ ๋ณธ ์ํํธ์จ์ด๋ฅผ ๋ฐ์ ์ธ ๋์ ๊ถ๋ฆฌ๊ฐ ๊ธ์ง์์ ํ์ฉ์ผ๋ก ์ ํํ ์ ๋ฐ๋ ๋ฐฉํฅ์ผ๋ก ํ์ฅ๋์์ต๋๋ค.
v1.0.10 marks the decisive turning point where the v1.0.x series infrastructure โ accumulated across five releases (v1.0.5 ~ v1.0.9) โ is opened to the OSS community. This release bundles three tracks (license transition Freeware โ MIT, explicit LGPL compatibility documentation, SignPath OSS Sponsorship application track). Code changes are smaller than any v1.0.5~v1.0.9 release (
FileNexusSuite.pyline count delta 0, text-only changes). Yet the semantic change is the largest: the rights users gain when they receive this software have been flipped from prohibited to permitted in the exact opposite direction.
โจ ์ฃผ์ ๋ณ๊ฒฝ / Major Changes
-
๋ผ์ด์ ์ค ์ ํ: Freeware (์์ค ๊ณต๊ฐ) โ MIT License / License transition: Freeware (source available) โ MIT License
- ์ฌ์ฉยท์์ ยท์ฌ๋ฐฐํฌยทํ๋งค๊ฐ ๋ชจ๋ ์์ ๋กญ๊ฒ ํ์ฉ (์ ์๊ถ ๊ณ ์ง ์ ์ง ์กฐ๊ฑด). ์ด์ ๋ฒ์ ์ "๋ฌด๋จ ์ฌ๋ฐฐํฌยท์ฌ๊ฐ๊ณตยทํ๋งค ๊ธ์ง" ๋ฌธ๊ตฌ๊ฐ ์ ํํ ์ ๋ฐ๋ ๋ฐฉํฅ์ผ๋ก ์ ํ / All of use, modify, redistribute, and sell are now freely permitted (provided that the copyright notice is retained). The previous "unauthorized redistribution, repackaging, or resale prohibited" clause is reversed in the exact opposite direction
- ์ฌ์ฉ์๋ ๋ณธ ์ํํธ์จ์ด๋ฅผ forkํ์ฌ ์์ ์ ํ๋ก์ ํธ๋ก ๋ฐ์ ์ํค๊ฑฐ๋, ์์ ๋ณธ์ ๋ฐฐํฌํ๊ฑฐ๋, ์์ ์ ์ ํ์ ํตํฉ ๊ฐ๋ฅ / Users may fork this software to develop into their own projects, distribute modified versions, or integrate into commercial products
- ํ๋ฆผ์ด *"๊ฐ์ธ ์์ ๋๊ตฌ๋ก ์์ํ์ง๋ง, ๊ฐ์ ์์ ์ ํ๋ ๋ค๋ฅธ ๋ถ๋ค์๊ฒ๋ ๋์์ด ๋๊ธฐ๋ฅผ"*์ด๋ผ๋ ๊ฒฐ๋ก v1.0.x ์๋ฆฌ์ฆ ๋์ ์ ๊ฒฐ๊ณผ๋ฅผ OSS ์ปค๋ฎค๋ํฐ๋ก ๊ฐ๋ฐฉ / Released by Hanrim with the spirit "originally built as a personal tool, in the hope it may help others with similar workflows"
-
MIT ์ ํ์ ๊ฒฐ / Why MIT specifically
- ๊ฐ๊ฒฐ์ฑ: 21์ค ํ์ค ํ ์คํธ๋ก ์ฌ์ฉ์๊ฐ ์ฝ๊ณ ์ดํดํ๊ธฐ ์ฌ์ / Conciseness: 21-line standard text easy for users to read and understand
- ํธํ์ฑ: GPL์ ๋น๋กฏํ ๊ฑฐ์ ๋ชจ๋ OSS ๋ผ์ด์ ์ค์ ํธํ โ fork ์ ๋ผ์ด์ ์ค ์ถฉ๋ 0 / Compatibility: Compatible with virtually all OSS licenses including GPL โ zero license conflicts when forked
- ์์ ํ์ฉ ๋ช ์์ ํ์ฉ: "GPL ์ ์ผ์ฑ" ๊ฐ์ ์๋ฌด ๋ฐ์ 0 / Commercial use explicitly permitted: zero obligations like "GPL contagion"
- OSS ์ ๊ณ ํ์ค: GitHub Top ํ๋ก์ ํธ์ 50% ์ด์์ด MIT ์ฌ์ฉ / OSS industry standard: 50%+ of GitHub Top projects use MIT
-
Copyright ยฉ 2026 Hanrim. All rights reserved.โCopyright ยฉ 2026 Hanrimโ "All rights reserved" ํ๊ธฐ 6๊ณณ ์ผ๊ด ์ ๋ฆฌ. 1910๋ ๋ถ์๋ ธ์ค์์ด๋ ์ค ํ์ฝ ์์ฌ๋ก ํ๋ ์ ์๊ถ๋ฒ์ ๋ฒ์ ์๋ฏธ ์์ + MIT ๋ผ์ด์ ์ค ์๋ฏธ์ ๊ฒฐ ์ผ๊ด์ฑ / "All rights reserved" notation cleaned across 6 locations. Vestige from the 1910 Buenos Aires Convention with no legal meaning in modern copyright law + consistency with MIT license semantics
๐ฆ ์ถ๊ฐ / Added
-
LGPL ํธํ์ฑ ๋ช ์์ ๋ฌธ์ํ / Explicit LGPL compatibility documentation
_build_license_html()์ PySide6 (LGPL-3.0) / chardet (LGPL-2.1) note ํ๋์ LGPL replacement ์๋ด 1๋ฌธ์ฅ์ฉ ์ถ๊ฐ / One-sentence LGPL replacement note added to PySide6 (LGPL-3.0) / chardet (LGPL-2.1) note fields in_build_license_html()- ์๋ด ๋ฌธ์ฅ: "File Nexus Suite is built with PyInstaller. Users may replace this LGPL library by rebuilding from source โ see the GitHub repository for build instructions."
- PyInstaller
--onedir๋น๋ ๋ชจ๋์_internal/ํด๋ ๋ถ๋ฆฌ ๊ตฌ์กฐ์์ ์ฌ์ฉ์๊ฐ LGPL ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ง์ ๊ต์ฒด ๊ฐ๋ฅํจ์ ๋ช ์. LGPL ยง3 ์๋ฌด๋ฅผ ์๋ฌต์ ์ถฉ์กฑ(GitHub source ๊ณต๊ฐ)์์ ๋ช ์์ ์ถฉ์กฑ์ผ๋ก ๊ฐํํ์ฌ ํ์์ง๋ ์๊ตฌ ์ฐจ๋จ / Explicitly states that users can directly replace LGPL libraries thanks to PyInstaller--onedirmode's_internal/folder separation. Strengthens LGPL ยง3 obligation from implicit fulfillment (GitHub source publication) to explicit documentation, permanently closing the gray zone
-
README.txt_internalํด๋ ๋ณดํธ ์๋ด /README.txt_internalfolder protection note- PyInstaller
--onedir๋น๋ ๋ชจ๋์์ ์ฌ์ฉ์๊ฐ_internal/ํด๋๋ฅผ *"ํ์ ์์ด ๋ณด์ด๋ ๋ฐ์ดํฐ"*๋ก ์คํดํ์ฌ ์ญ์ ํ ์ํ์ ํ/์ ์์ชฝ ์๋ด๋ก ์ฐจ๋จ / Mitigates the risk of users mistaking_internal/for "seemingly unnecessary data" and deleting it, with both Korean and English notices README.txt๊ฐ *"ํฌ์ฅ์ง ์๋ด ๋ผ๋ฒจ"*์์ ์ง์ง ์ ์ฒด์ฑ์ธ *"_internal๋ณดํธ ์ฅ์น"*๋ก ์๋-์ฐ์ถ๋ฌผ ์ ํฉ์ ๊ฐ์ถค /README.txtachieves intent-artifact alignment, transitioning from "package label" to its true identity as "_internalprotection device"
- PyInstaller
-
README "์ดํ์ฌ" ํ ์ค / README "altruism" line
README.md/README_EN.md๋ผ์ด์ ์ค ์น์ +_build_license_html()๋ณธ ํ๋ก์ ํธ ํญ๋ชฉ note์ ์ผ๊ด ์ถ๊ฐ. "๊ฐ์ธ ์์ ๋๊ตฌ๋ก ์์ํ์ง๋ง, ๊ฐ์ ์์ ์ ํ๋ ๋ค๋ฅธ ๋ถ๋ค์๊ฒ๋ ๋์์ด ๋๊ธฐ๋ฅผ ๋ฐ๋ผ๋ฉฐ MIT ๋ผ์ด์ ์ค๋ก ๊ณต๊ฐํฉ๋๋ค." / Added consistently toREADME.md/README_EN.mdlicense section +_build_license_html()project entry note. "Originally built as a personal tool, now released under MIT in the hope it may help others with similar workflows."- GitHub README์ ์ฑ ๋ด ๋ผ์ด์ ์ค ํ์ด์ง๊ฐ ๊ฐ์ ๊ฒฐ์ ๋ฉ์์ง๋ฅผ ์ฌ์ฉ์์๊ฒ ์ ๋ฌ / GitHub README and in-app license page deliver the same message to users
๐ ๋ณ๊ฒฝ / Changed
-
5์ธ์ด
license_summaryํค ์๋ฏธ ์ ๋ฐ๋ ์ฌ์์ฑ / 5-languagelicense_summarykey reworded with opposite semantics- en/ko/ja/zh_cn/zh_tw ๋ชจ๋ "๋ฌด๋จ ์ฌ๋ฐฐํฌยท์ฌ๊ฐ๊ณตยทํ๋งค ๊ธ์ง" โ *"์ฌ์ฉยท์์ ยท์ฌ๋ฐฐํฌยทํ๋งค ๋ชจ๋ ํ์ฉ"*์ผ๋ก ์ ํํ ์ ๋ฐ๋ ๋ฐฉํฅ. zh_cn์ v1.0.9 ยง5.1.G fallback chain์ ์ํฅ์ ๋ฐ์ง ์๋๋ก 5์ธ์ด ์ง์ ์ ์ ์ ์ง (๋ผ์ด์ ์ค ํต์ฌ ํค์ด๋ฏ๋ก zh_tw ์ดํ ์ฐจ์ด ๋ณด์กด) / All five languages reworded from "unauthorized redistribution, repackaging, or resale prohibited" โ "use, modify, redistribute, and sell all permitted". zh_cn maintains direct 5-language definition unaffected by v1.0.9 ยง5.1.G fallback chain (license-critical key, preserves zh_tw vocabulary distinction)
-
_build_license_html()๋ณธ ํ๋ก์ ํธ ํญ๋ชฉ ์ ๋ฉด ์ฌ์์ฑ /_build_license_html()project entry fully rewordedFreeware โ Free for Personal & Commercial UseโMIT License/ Title field updatednoteํ๋: "๋ฌด๋จ ์ฌ๋ฐฐํฌยท์ฌ๊ฐ๊ณตยทํ๋งค ๊ธ์ง" ๋จ๋ฝ โ "MIT ๋ผ์ด์ ์ค / ์ ์๊ถ ๊ณ ์ง ์ ์ง ์ ๋ชจ๋ ๊ถ๋ฆฌ ํ์ฉ" ๋จ๋ฝ. "์ดํ์ฌ" ํ ์ค ์ ๊ท ์ถ๊ฐ, AI ํ์ด ํ๋ก๊ทธ๋๋ฐ ๊ฒฐ ๋ณด์กด /notefield reworded; "altruism" line newly added, AI pair programming context preserved
-
README ๋ฑ์ง ์๊ฐ ์ฒด๊ณ ์ฌ์ ๋ฆฝ / README badge visual system refined
- *"v1.0.10์ด v1.0.x ์๋ฆฌ์ฆ์์ OSS ๋์ฐฉ์ "*์ด๋ผ๋ ๊ฒฐ์ ์์ ํ๋ฆ์ผ๋ก ํํ / Expresses the narrative "v1.0.10 as the OSS arrival point of v1.0.x series" through color flow
- ์์์ (
#7B6FA3๋ณด๋ผ): version 1.0.10 / Starting point (#7B6FA3purple): version 1.0.10 - OSS ํ๊ธฐ (
#97CA00์ง์ OSS ์ด๋ก): tests 535 passing / license MIT โ v1.0.10 ์ ๊ท ์๋ฆฌ / OSS vitality (#97CA00deep OSS green): tests 535 passing / license MIT โ new placement in v1.0.10 - ์ ์ฒด์ฑ (
#CC785CAnthropic ๊ตฌ๋ฆฟ๋น): AI pair Claude / Download CTA / Identity (#CC785CAnthropic copper): AI pair Claude / Download CTA - ๋ธ๋๋ ์ธ์ฉ (์ธ๋ถ ํ์ค ๊ทธ๋๋ก): python / PySide6 / platform / CI badge / Brand citations (external standards as-is): python / PySide6 / platform / CI badge
-
LICENSEํ์ผ ํ์ ์ ํ /LICENSEfile format transition- ์์ฒด ์์ฑ Freeware ํ์ โ MIT ํ์ค 21์ค ํ ์คํธ๋ก ์ ํ. GitHub Licensee gem์ด ์ ํํ "MIT License" ์๋ ํ์ง / Custom Freeware format โ 21-line MIT standard text. GitHub Licensee gem now correctly auto-detects "MIT License"
- ํ๊ตญ์ด ์๋ด + Test Data Exception (CC0) ๋ถ๋ก ๋ณด์กด. third-party libraries ๋ชฉ๋ก์ LICENSE์์ ์ ๊ฑฐ (
_build_license_html()+ README๊ฐ ๋จ์ผ ์ง์ค ์์ฒ ์ฑ ์) / Korean notice + Test Data Exception (CC0) appendix preserved. Third-party libraries list removed from LICENSE (_build_license_html()+ README take single source of truth responsibility)
โ ๊ฒ์ฆ / Verified
-
๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ผ์ด์ ์ค ํธํ์ฑ ๋ฌด๊ฒฐ ์ ๊ฒ / Library license compatibility integrity audit
- 7์ข ์์กด ๋ผ์ด๋ธ๋ฌ๋ฆฌ (Python/PySide6/chardet/python-docx/pdfplumber/openpyxl/python-hwpx) ๋ชจ๋ MIT ํธํ ํ์ธ / All 7 dependencies (Python/PySide6/chardet/python-docx/pdfplumber/openpyxl/python-hwpx) confirmed MIT-compatible
- LGPL 2์ข (PySide6/chardet)์ ยง3 ์๋ฌด๊ฐ (๊ฐ) GitHub source ๊ณต๊ฐ + (๋ค) ๋ช ์์ ์๋ด ์ถ๊ฐ์ ์ด์ค ๋ณด์ฅ์ผ๋ก ํ์์ง๋ ์๊ตฌ ์ฐจ๋จ / LGPL libraries' ยง3 obligation permanently closed via dual guarantee: (๊ฐ) GitHub source publication + (๋ค) explicit replacement note
-
๊ฐ์ธ ์์ฐ ๋ถ๋ฆฌ ์ ๊ฒ / Personal asset separation audit
- LICENSE /
_build_license_html()/ README / RELEASE_NOTE ๋ชจ๋ OSS-facing ์ฐ์ถ๋ฌผ์์ ํ๋ฆผ ๊ฐ์ธ ์์ฐ(๋ธ๋ก๊ทธ, ๋ณธ๋ช ๋ฑ) ์ผ์ ๋ฏธํฌํจ ํ์ธ. ์ด ๊ฒฐ์ v1.0.10 ์ดํ ๋ชจ๋ ๋ฆด๋ฆฌ์ฆ์ ์๊ตฌ ์ ์ฉ / All OSS-facing artifacts confirmed free of Hanrim's personal assets (blog, full name, etc.). This principle applies permanently from v1.0.10 onward
- LICENSE /
๐งช ํ ์คํธ ์๋ํ / Test Automation
- 535 passing (v1.0.9์ ๋์ผ), 58๊ฐ ํด๋์ค, ์คํจยท์ค๋ฅยท์คํต 0 (ํ๋ฆผ ๋ก์ปฌ + Git ํด๋ ์ด์ค ๊ฒ์ฆ + GitHub Actions CI ํต๊ณผ) / 535 passing (same as v1.0.9), 58 classes, zero failures/errors/skips (Hanrim local + Git folder dual verification + GitHub Actions CI passed)
- v1.0.10 ๋ณ๊ฒฝ ์์ญ(๋ผ์ด์ ์ค ํ ์คํธ 5์ธ์ด + ๋ผ์ด๋ธ๋ฌ๋ฆฌ note 2๊ณณ + ํธํฐ "All rights reserved" ์ ๊ฑฐ + ๋ฒ์ ๊ฐฑ์ )์ด ์๋ ํ ์คํธ invariant์ ์ถฉ๋ 0 / Zero conflicts between v1.0.10 change areas (license text 5 languages + library notes 2 locations + footer "All rights reserved" removal + version update) and test invariants
- v1.0.4 ์์
์์ ์ ๋์
๋ ์ ์ ํํ ๋น๊ต ํจํด (
parts = tuple(int(p) for p in ver.split('.')))์ด1.0.10๊ฐ์ ๋ ์๋ฆฟ์ ํจ์น ๋ฒ์ ์ ์๋ ๋์ โ ๋ชจ๋ ๋ฒ์ ๋น๊ต invariant ์์ฐ ํต๊ณผ / Integer tuple comparison pattern introduced in v1.0.4 automatically handles two-digit patch versions like1.0.10โ all version comparison invariants pass naturally
๐ ํฅํ ํธ๋ / Deferred Tracks
- SignPath OSS Sponsorship ์ ์ฒญ / SignPath OSS Sponsorship application
- v1.0.10 Release publish ์งํ
signpath.org์ OSS Sponsorship ์ ์ฒญ์ ์ ์ถ. v1.0.10์ด *"Latest release: first MIT release"*๋ก ์ ์ฒญ์์ ๊ธฐ๋ก๋จ์ผ๋ก์จ ๊ฒํ ์ ๋ขฐ๋ ๊ฐํ / OSS Sponsorship application submitted tosignpath.orgimmediately after v1.0.10 publish. v1.0.10 recorded in application as "Latest release: first MIT release" strengthens review credibility - ์๊ฒฉ ์กฐ๊ฑด 6๊ฐ ๋ชจ๋ ์ถฉ์กฑ: OSI-approved license (MIT) / No malware / Actively maintained / Released / Documented / Verifiable build from source
- ์น์ธ ํ v1.0.11์...
- v1.0.10 Release publish ์งํ
File Nexus Suite v1.0.9
v1.0.9 โ v1.0.x ์๋ฆฌ์ฆ ๋ง๋ฌด๋ฆฌ: ACDG ์ฌํ ์ ๋ฆฌ ๋ฌถ์ (ํ๊ธฐ ์ ์ฑ ๋๊ธฐํ + ๋น๋ ๋๊ตฌ strict ๋ชจ๋ + zh_cn ์ฌ์ ์ ๋ฆฌ + fallback chain) / End of v1.0.x series: ACDG cleanup bundle (notation policy sync + build strict mode + zh_cn dictionary cleanup + fallback chain)
v1.0.9๋ v1.0.5 ~ v1.0.8 ์ฌ์ด 4๊ฐ ๋ฆด๋ฆฌ์ฆ๋ก ๋ฌด๊ฑฐ์์ง v1.0.x ์๋ฆฌ์ฆ๋ฅผ ๋ซ๋ ์ฌํ ์ ๋ฆฌ / ๋ฐ์ดํฐ ์ฒญ์ ์นดํ ๊ณ ๋ฆฌ ๋ฆด๋ฆฌ์ฆ์ ๋๋ค. v1.0.8 ์ธ์์ธ๊ณ ยง5.1์์ ์ ์๋ ACDG 4๊ฐ ์์ (A: ํ๊ธฐ ์ ์ฑ ๋๊ธฐํ, C: ๋น๋ ๋๊ตฌ strict ๋ชจ๋, D: HelpDialog ์ ๊ฒ, G: zh_cn ์ฌ์ ์ ๋ฆฌ)์ ๋ฌถ์ด ์งํํ์ผ๋ฉฐ, ๋ค์ ์๋ฆฌ์ฆ(v1.1.0 โ ๊ตฌ์กฐ ๋ฆฌํฉํ ๋ง / ์ ๊ธฐ๋ฅ)์ ๊ฒฐ์ ๋ช ํํ ๋ถ๋ฆฌํฉ๋๋ค. ยง5.1.D๋ ์ ๊ฒ ๊ฒฐ๊ณผ ์ต์ C ์ ์ฉ ๋ถ์๋ก 0์ค ์์ ์ผ๋ก ๋ง๊ฐ๋์ด ์ ์ฌ ๊ฒฐํจ ์์์ด ๋ฐ์ดํฐ๋ก ํ์ธ๋๊ณ , ยง5.1.G๋ ์ธ์์ธ๊ณ ๋ช ์ธ "188๊ฐ ํค"๊ฐ ๋ฐ์ดํฐ๋ก ๊ฒ์ฆ๋์ง ์์ ํ์ค ๋ฐ์ดํฐ 47๊ฐ โ invariant ๋ณดํธ 7๊ฐ ์ ์ธ โ 40๊ฐ๋ก ์ ์งํ๊ฒ ์ฌ์ ์ํ ํ fallback chain(zh_cn โ zh_tw โ ko)์ ํจ๊ป ๋์ ํ์ฌ ์ฌ์ฉ์ ๋์ ์ํฅ 0์ด ์ ์์ ๋ณด์ฅ๋๋๋ก ๊ตฌ์กฐ์ ์ผ๋ก ํ์์ต๋๋ค. 1์ฐจ ์ ์ฉ ํ v1.0.5 ํ๊ท ํ ์คํธ 6๊ฐ FAIL์ด ๋ฐ๊ฒฌ๋์ผ๋ ํ๊ท ์์ ์ฌ์ดํด์ ๊ฑฐ์ณ 535/0/0/0์ผ๋ก ๊นจ๋์ด ๋ซํ์ต๋๋ค.
v1.0.9 closes the v1.0.x series, which had grown heavy across four releases (v1.0.5 ~ v1.0.8), under the post-cleanup / data hygiene category. It bundles the four ACDG tasks defined in v1.0.8 handover ยง5.1 (A: notation policy sync, C: build strict mode, D: HelpDialog audit, G: zh_cn dictionary cleanup), drawing a clear line from the next series (v1.1.0 โ structural refactor / new features). ยง5.1.D was closed as a 0-line task after the audit confirmed Option C didn't apply, with the absence of latent defects established as evidence; ยง5.1.G honestly re-defined the handover spec "188 keys" โ which was not verifiable in data โ to 47 actual matches โ 40 after excluding 7 invariant-protected keys, while introducing a fallback chain (zh_cn โ zh_tw โ ko) so that user-observable behavior remains unchanged by definition. After initial application, six v1.0.5 regression tests failed, but a regression-fix cycle closed cleanly at 535/0/0/0.
โจ ์ฃผ์ ๊ธฐ๋ฅ / Major Features
-
build_pyinstaller.py--strict๋ชจ๋ ๋์ /build_pyinstaller.py--strictmode introduced- ๋ฒ์ ์ผ๊ด์ฑ ๊ฒ์ฆ ๋จ๊ณ๋ฅผ ๋น๋ ์ (step 5)์ผ๋ก ๋ถ๋ฆฌ. mismatch ์ strict ๋ชจ๋์์ PyInstaller๊ฐ ์์๋ ํ๊ธฐ ์ ์ ์ฆ์ abort๋์ด ์์ญ ์ด ๋น๋ + UPX ์์ถ ์๊ฐ ์ ์ฝ + ๊ธฐ์กด ๋น๋ ์ฐ์ถ๋ฌผ ๋ณด์กด / Version consistency check separated to pre-build (step 5). In strict mode on mismatch, build aborts before PyInstaller even starts, saving tens-of-seconds build + UPX compression time and preserving prior dist artifacts
- ์ ๊ท ํจ์
check_version_consistency(strict)์ถ๊ฐ, step ์ํ์ค 7โ8๋จ๊ณ๋ก ์ฌ์ ๋ ฌ / New functioncheck_version_consistency(strict)added, step sequence reorganized 7โ8 build.batwrapper์%*์ธ์ ํจ์ค์ค๋ฃจ ์ถ๊ฐํ์ฌbuild.bat --strict์ง์ ํธ์ถ ๊ฐ๋ฅ /build.batwrapper now supports%*argument pass-through for directbuild.bat --strictinvocation
-
zh_cn์ฌ์ fallback chain ๋์ /zh_cndictionary fallback chain introduced_t()/_rt()ํจ์์ zh_cn โ zh_tw โ ko fallback chain ์ถ๊ฐ. v1.0.5๋ถํฐ ko ๋จ์ผ fallback์ด์๋ ํ๊ณ ๋ณด์ /_t()/_rt()now use zh_cn โ zh_tw โ ko chain. Improvement over single ko fallback since v1.0.5- zh_cn ์ฌ์ ์ ๋ฏธ์ ์ ํค๋ zh_tw๋ก 1์ฐจ fallback๋์ด ์ฌ์ฉ์ ๋์ ์ํฅ 0์ด ์ ์์ ๋ณด์ฅ / Keys missing in zh_cn fall back to zh_tw first, guaranteeing zero user-observable impact by definition
-
zh_cn์ฌ์ 40๊ฐ ํค ์ ๋ฆฌ /zh_cndictionary 40-key cleanup- zh_cn โ zh_tw ๊ฐ์ด 100% ๋์ผํ ํค 47๊ฐ ์ค invariant ๋ณดํธ 7๊ฐ ์ ์ธํ๊ณ 40๊ฐ ์ ๋ฆฌ / 40 keys cleaned among 47 with values identical to zh_tw, excluding 7 invariant-protected keys
- ์ ๋ฆฌ ๋์: ์ด๋ชจ์ง/์ฌ๋ณผ (โถ ๋ฑ), ์งง์ ๋จ์ด (ๅๆถ/ๅฎๆ/ๅญ/่ก ๋ฑ), ์๋ฆฟ์ ํ๊ธฐ (ๆๅฐ2ไฝ/ๅบๅฎ3ไฝ ๋ฑ), ์๋ฆฌํ์์ (ไพ: jpg, png, gif ๋ฑ), ํ ๋ง๋ช (ๆทฑ่ฒ/่่/่ฐ่กฃ่ ๋ฑ), ์ธ์ฝ๋ฉ ๋ผ๋ฒจ ์ผ๋ถ / Cleaned: emojis/symbols, short words, digit notations, placeholders, theme names, partial encoding labels
- ๋ณดํธ๋ 7๊ฐ:
dlg_yes/dlg_no/dlg_warning(๋ค์ด์ผ๋ก๊ทธ ๊ณตํต),conv_status_done/conv_sub_epub2txt/conv_sub_txt2epub(๋ณํ ์ํ),rename_cancel(์ทจ์) / 7 protected: dialog commons, conversion status, cancel โ core UI keys retain direct 5-language definition
-
test_zh_cn_fallback_to_zh_tw์ ๊ท invariant /test_zh_cn_fallback_to_zh_twnew invariant_t()/_rt()๋ ํจ์ ๋ชจ๋์ fallback ํจํด์ด ์ด์์๊ณ ๊ฒ์ฆ ๋์ ํค๊ฐ ์กด์ฌํ๋์ง ๊ฒ์ฆ / Verifies fallback pattern is alive in both_t()/_rt()and that verification target keys existTEST_MANAGEMENT_POLICY.mdยง3 4๋ฒ ์์น ์ ์ฉ. fallback ๋ฉ์ปค๋์ฆ์ด ํฅํ ๋๊ตฐ๊ฐ์ ์ค์๋ก ๊นจ์ง๋ฉด CI์์ ์ฆ์ ์๋ ๊ฐ์ง / AppliesTEST_MANAGEMENT_POLICY.mdยง3 principle #4 โ accidental future breakage caught by CI immediately
๐ ๋ฒ๊ทธ ์์ / Bug Fixes
- (์์ โ v1.0.9๋ ์ฌํ ์ ๋ฆฌ ์นดํ
๊ณ ๋ฆฌ) / (None โ v1.0.9 is a post-cleanup category release)
- ๋ณธ ๋ฆด๋ฆฌ์ฆ๋ ๊ธฐ๋ฅ ์์ ์ด ์๋ ์ฝ๋ ์ฒญ๊ฒฐ์ฑ ๋ฐ ๋๊ตฌ ๊ฐ์ ์ด ํต์ฌ / This release focuses on code hygiene and tooling improvement rather than functional fixes
๐ ๋ณ๊ฒฝ / Changed
-
README.md/README_EN.mdCopyright ๋ฐ ์ ์์ ํ๊ธฐ ๋๊ธฐํ /README.md/README_EN.mdcopyright and author notation syncYongwoo Shin (Hanrim)โHanrim๋จ๋ (4๊ณณ). v1.0.8 ยง4.36 ๋งค์ฒด๋ณ ํ๊ธฐ ์ ์ฑ ์ ๋ฐ๋ฅธ GitHub-facing ์๋ฃ ๋๊ธฐํ / 4 locations changed toHanrimalone. GitHub-facing material sync per v1.0.8 ยง4.36 medium-specific notation policy- ์ธ๋ถ ๊ฒฉ์ ๋งค์ฒด(ํฌํธํด๋ฆฌ์ค, ๊ธฐํ์)๋ ํ๋ค์
Yongwoo Shin (Hanrim)์ ์ง / Formal external materials (portfolio, planning docs) retain full form
-
test_all_langs_same_key_count์ฌ์ค๊ณ /test_all_langs_same_key_countredesigned- ๋์นญ ๊ฐ์ (5์ธ์ด ๋์ผ ํค ์)์์ ๋น๋์นญ ํ์ฉ์ผ๋ก ์ ํ โ zh_cn์ zh_tw ๋ถ๋ถ์งํฉ ํ์ฉ, ko/en/ja/zh_tw๋ ๋์ผ ํค ์ ๊ฐ์ / Switched from symmetric enforcement (all 5 languages same count) to asymmetric โ zh_cn allowed as zh_tw subset, ko/en/ja/zh_tw must match
- zh_cn fallback ๋ฉ์ปค๋์ฆ๊ณผ ์ ํฉ์ฑ ํ๋ณด / Aligned with zh_cn fallback mechanism
-
test_all_languages_have_similar_key_count๊ฐฑ์ /test_all_languages_have_similar_key_countupdated- zh_cn์ fallback chain ์ฌ์ฉ ๋ช ์ํ์ฌ ํค ์ ๊ฒ์ฆ์์ ์ ์ธ, ๋ค๋ฅธ 4์ธ์ด๋ง โค5 ์ฐจ์ด ๊ฐ์ / zh_cn excluded from count check (fallback intent), other 4 languages still constrained โค5 diff
- v1.0.5 ์์ ์๋(์๊ฒฐ์ฑ ๋ณด์ฅ) ์ ์งํ๋ฉด์ ยง5.1.G ์ ํฉ / Retains v1.0.5-era intent (completeness guarantee) while aligning with ยง5.1.G
โ ๊ฒ์ฆ / Verified
HelpDialog์ ๊ฒ โ ์ต์ C ์ ์ฉ ๋ถ์ ํ์ธ /HelpDialogaudit โ Option C not applicable confirmed- v1.0.8 SettingsDialog์ ๋ผ๋ฒจ color ์์ฌ ๋ฒ๊ทธ์ ๊ฐ์ ๊ตฌ์กฐ์ ๊ฒฐํจ์ด ๋ค๋ฅธ ๋ค์ด์ผ๋ก๊ทธ์ ์ ์ฌํ ๊ฐ๋ฅ์ฑ์ ์ง๋จ / Audited whether the SettingsDialog label-color residue defect from v1.0.8 was latent in other dialogs
- ํธ์ถ ๋ฐฉ์ ๋น๊ต ๊ฒฐ๊ณผ: HelpDialog๋ ๋จ์
exec()๋ชจ๋ฌ + ์๊ทธ๋ ์ฐ๊ฒฐ 0๊ฐ / SettingsDialog๋ "์ฐฝ ์ ์ง" + ์๊ทธ๋ 3๊ฐ (theme/shortcuts/language) โ ๋ณธ์ง์ ์ผ๋ก ๋ค๋ฅธ ํจํด / Comparison result: HelpDialog uses plainexec()modal + 0 signals; SettingsDialog uses "stays open" + 3 signals โ fundamentally different patterns - HelpDialog์
refresh()๋ฉ์๋๋ ์๋์ ์ผ๋กpass+ ์ฃผ์ "exec() ๋ชจ๋ฌ์ด๋ผ ์ด๋ฆด ๋๋ง๋ค ์๋ก ์์ฑ๋จ"์ผ๋ก ์๋ ๋ช ๋ฌธํ. ๋ค์ด์ผ๋ก๊ทธ๊ฐ ์ด์์๋ ๋์ ์ธ๋ถ ์ํ๊ฐ ๋ฐ๋์ด ๋ค์ด์ฌ ์๋๋ฆฌ์ค ์์ฒด๊ฐ ๊ตฌ์กฐ์ ์ผ๋ก ์กด์ฌํ์ง ์์ /HelpDialog.refresh()is intentionallypasswith comment "modal exec(), recreated on each open"; the scenario of external state changing while dialog is alive structurally cannot occur - ๊ฒฐ๋ก : ์ ๊ฒ ์์ฒด๊ฐ v1.0.9 ยง5.1.D์ ์ฐ์ถ๋ฌผ โ ์ ์ฌ ๊ฒฐํจ ์์์ ๋ฐ์ดํฐ๋ก ๋ช ์. ์ฝ๋ ๋ณ๊ฒฝ 0์ค๋ก ๋ง๊ฐ / Conclusion: the audit itself is the ยง5.1.D artifact โ absence of latent defects established. Closed as 0-line task
๐งช ํ ์คํธ ์๋ํ / Test Automation
- ์ด 535๊ฐ ํ ์คํธ ํต๊ณผ / 535 tests passing, 58๊ฐ ํด๋์ค / 58 classes, ์คํจ 0 / ์ค๋ฅ 0 / ์คํต 0 / 0 failed / 0 errors / 0 skipped โญ
- +1 vs v1.0.8 (534 โ 535) โ
test_zh_cn_fallback_to_zh_tw์ ๊ท invariant /test_zh_cn_fallback_to_zh_twnew invariant - ํ๊ท ๋ฐ๊ฒฌ โ ์์ ์ฌ์ดํด / Regression-discovery โ fix cycle:
- ยง5.1.G 1์ฐจ ์ ์ฉ ํ v1.0.5 ํ๊ท ํ
์คํธ 6๊ฐ FAIL ๋ฐ๊ฒฌ โ
merge_enc_utf8/merge_enc_utf16/merge_enc_shiftjis3๊ฐ๊ฐ invariant ๋ณดํธ ํค์์์ 1์ฐจ ์ง๋จ์์ ๋๋ฝ / After initial ยง5.1.G application, 6 v1.0.5 regression tests failed โ first diagnosis missed that 3 keys (merge_enc_utf8/merge_enc_utf16/merge_enc_shiftjis) were invariant-protected - ์ ๋ฆฌ ๋์ 47โ40๊ฐ๋ก ์ถ์ +
test_all_languages_have_similar_key_countzh_cn ์์ธ ๊ฐฑ์ ์ผ๋ก ํ๊ท ๋ซ์ / Resolved by reducing cleanup target 47โ40 and updatingtest_all_languages_have_similar_key_countto except zh_cn
- ยง5.1.G 1์ฐจ ์ ์ฉ ํ v1.0.5 ํ๊ท ํ
์คํธ 6๊ฐ FAIL ๋ฐ๊ฒฌ โ
- ์ด์ค ๊ฒ์ฆ / Dual verification:
- ์์ ํด๋: 535/0/0/0 / Work folder: 535/0/0/0
- Git ํด๋: 535/0/0/0 / Git folder: 535/0/0/0
๐ ๊ฒ์ฆ ๋ฒ์ / Verification Scope
- ๋จ์ ํ ์คํธ / Unit tests: 535 passing (ํ๋ฆผ ๋ก์ปฌ Windows + Git ํด๋ ์ด์ค ๊ฒ์ฆ, GitHub Actions CI๋ push ํ ์๋ ์ฌํ ์์ ) / 535 passing (dual verification on Hanrim's local Windows + Git folder; GitHub Actions CI will reproduce automatically after push)
- ์๋ QA โ ยง5.1.G ์ง์ ๊ฒ์ฆ ๊ถ์ฅ ์๋๋ฆฌ์ค / Manual QA โ ยง5.1.G recommended scenarios:
- ์ฑ ์ธ์ด๋ฅผ ็ฎไฝไธญๆ(zh_cn)๋ก ์ ํ ํ ์ ๋ฆฌํ 40๊ฐ ํค๊ฐ ์ฌ์ฉ๋๋ ํ๋ฉด ํ์ธ (์: ํ ๋ง ์ค์ ์ "็ฝ่ฒ/ๆทฑ่ฒ", Batch Renamer์ "โถ") / Switch app language to ็ฎไฝไธญๆ and visit screens using cleaned keys (e.g., theme settings "็ฝ่ฒ/ๆทฑ่ฒ", Batch Renamer "โถ")
- fallback chain์ผ๋ก zh_tw ๊ฐ๊ณผ ๋์ผํ๊ฒ ํ์๋์ด์ผ ํจ (๊ฐ 100% ๋์ผ์ด๋ผ ์๊ฐ ์ฐจ์ด 0) / Should display identical to zh_tw values via fallback (100% value match means zero visual difference)
- zh_tw / ๊ธฐํ ์ธ์ด ํ๊ท ํ์ธ โ ์ฌ์ ๋ฏธ๋ณ๊ฒฝ์ด๋ผ ์ํฅ ์์ด์ผ ํจ / zh_tw and other languages regression check โ should be unaffected (dictionaries unchanged)
- ๋น๋ ๋๊ตฌ ๊ฒ์ฆ / Build tooling verification:
python build_pyinstaller.py์ ์ ๋น๋ (๊ธฐ์กด ๋์ ๋ณด์กด) /python build_pyinstaller.pynormal build (existing behavior preserved)python build_pyinstaller.py --strictํค๋ ํ์ + ์ ์ ๋น๋ /python build_pyinstaller.py --strictheader display + normal build- ์๋์ mismatch ์๋๋ฆฌ์ค: README.txt ์์ ๋ณ๊ฒฝ ํ
--strict์คํ ์ step 5์์ ์ฆ์ abort ํ์ธ / Intentional mismatch scenario: temporary README.txt change +--strictaborts immediately at step 5 build.bat/build.bat --strictwrapper ํต๊ณผ /build.bat/build.bat --strictwrapper verification passed
- ๋ฒ์ ์ ํฉ์ฑ ๊ฒ์ฆ / Version consistency verification:
APP_VERSION์์ /version_info.txt4๊ณณ /README.md/README_EN.md๋ฑ์ง /README.txt๋ชจ๋ v1.0.9๋ก ์ ํฉ / All aligned to v1.0.9:APP_VERSIONconstant,version_info.txt(4 locations),README.md/README_EN.mdbadges,README.txt
๐ฆ ๊ตฌ์กฐ์ ๋ณ๊ฒฝ / Structural Changes
- ๋ผ์ธ ์ ๋ณ๋ / Line count changes:
FileNexusSuite.py: 14,883 โ 14,850์ค (-33: zh_cn 40๊ฐ ํค ์ ๊ฑฐ -40 +_t()/_rt()fallback ๋ณด๊ฐ +6 + APP_VERSION ๊ฐฑ์ ๋ฑ) / -33 lines (zh_cn 40-key removal -40 +_t()/_rt()fallback +6 + APP_VERSION etc.)- `test_file_nexus.py...
File Nexus Suite v1.0.8
v1.0.8 โ ์ค์ ๋ค์ด์ผ๋ก๊ทธ ๋ผ๋ฒจ color ์์ฌ ๋ฒ๊ทธ ๊ตฌ์กฐ์ ํด๊ฒฐ (ํ์ด์ง lazy ์ฌ์์ฑ) / Settings dialog label color residue bug โ structural fix via page lazy recreation
v1.0.8์ v1.0.5๋ถํฐ ๋ค์ฏ ๋ฆด๋ฆฌ์ฆ๋ฅผ ์ด์๋จ์ ๋ณธ๊ณผ์ ๋ฅผ ๋ง์นจ๋ด ํด๊ฒฐํ ๋ฆด๋ฆฌ์ฆ์
๋๋ค. v1.0.6์์ ์๋ํ 4๊ฐ์ง ์ ๊ทผ(QTimer ์ง์ฐ / unpolish-polish / QApplication ์ ์ญ ์ฌ์ ์ฉ / findChildren update)์ด ๋ชจ๋ ์คํจํ ํ v1.0.7์์ ์ด์๋๋ ๋ณธ๊ณผ์ ๋ก, ์ด๋ฒ์๋ ์ฌ์ ์กฐ์ฌ โ ์ฝ๋ ์ง๋จ โ ์ต์
์ฌํ๊ฐ์ ์ ์งํ ํ๋ฆ์ผ๋ก ํ์ด๋์ต๋๋ค. ์ฝ๋ ์ง๋จ ๊ฒฐ๊ณผ ยง11.1์ "์ํฅ ์์ ฏ 3๊ฐ์ง"๊ฐ ์ค์ ๋ก๋ 22๊ฐ ์์ ฏ ๊ฐฑ์ ๋๋ฝ์ ๋น์ฐ ์ผ๊ฐ์ด์์์ด ๋๋ฌ๋ฌ๊ณ , ์ฒ์ ๊ถ์ฅํ๋ ์ต์
A(Targeted ๊ฐฑ์ , 6080์ค)๋ฅผ ์ต์
C(ํ์ด์ง lazy ์ฌ์์ฑ, +17์ค)๋ก ๋ณ๊ฒฝํ๋ ์ ์งํ ์ฌํ๊ฐ๋ฅผ ๊ฑฐ์ณ ์ฝ๋ ๋ณ๊ฒฝ๋์ 1/4๋ก ์ค์ด๋ฉด์ ๋๋ฝ ์ฌ๋ฐ ์ํ์ ์๊ตฌ ๋ฐฉ์งํ๋ ๊ตฌ์กฐ์ ํด๊ฒฐ์ ๋๋ฌํ์ต๋๋ค. ์ํฌ์ด๋ผ์ด๋(์ค์ ์ฐฝ ์ฌ์คํ)์ ๋์ผํ ๋ฉ์ปค๋์ฆ์ ๋ค์ด์ผ๋ก๊ทธ ๋ด๋ถ์์ ์๋ํํ ๋ฐฉ์์ผ๋ก, v1.0.6 Phase 2 Completion Record ยง11.3์์ ํ๋ฆผ์ด ์ฌ์ ํ๋ณด๋ก ์ ์ด๋ "ํ์ด์ง lazy ์์ฑ + ์ฌ๋ฐฉ๋ฌธ ์ ์กฐ๊ฑด๋ถ ์ฌ์์ฑ" ๋ฐฉํฅ๊ณผ ์ ํํ ์ผ์นํฉ๋๋ค. ์ฌ์ด๋ ๊ฒฐํจ 2๊ฑด(_ver_lbl ๊ฐฑ์ ๋๋ฝ, ์ถ๋ ฅ ํด๋ ๋ฒํผ ํ
์คํธ ๊ฐฑ์ ๋๋ฝ)๋ ๊ฐ์ ๊ตฌ์กฐ์ ํด๊ฒฐ๋ก ๋์ ํ๋ ธ์ผ๋ฉฐ, TEST_MANAGEMENT_POLICY.md ยง3 4๋ฒ ์์น(์ ๊ท ๊ธฐ๋ฅ์ ๋ํ ์๋ ์ปค๋ฒ๋ฆฌ์ง ๋ช
์)์ ๋ฐ๋ผ TestSettingsDialogStructureInvariant ํด๋์ค 3๊ฐ invariant๊ฐ ์ถ๊ฐ๋์ด ์ต์
C ๋ฉ์ปค๋์ฆ์ด ํฅํ ๋๊ตฐ๊ฐ์ ์ค์๋ก ๊นจ์ง ์ CI์์ ์ฆ์ ์๋ ๊ฐ์ง๋ฉ๋๋ค.
v1.0.8 finally resolves the original target that survived five releases since v1.0.5. After v1.0.6's four attempted approaches (QTimer deferral, unpolish-polish, QApplication global re-apply, findChildren update) all failed and the issue was deferred through v1.0.7, this release tackles it through an honest sequence of preliminary research โ code diagnosis โ option re-evaluation. Code diagnosis revealed that the "3 affected widgets" mentioned in ยง11.1 were merely the visible tip of a 22-widget update omission iceberg, leading to a transparent re-evaluation that swapped the initially recommended Option A (targeted updates,
6080 lines) for Option C (page lazy recreation, +17 lines) โ reducing code change to a quarter while permanently preventing recurrence. The mechanism automates the existing workaround (close and reopen the settings dialog) within the dialog itself, aligning precisely with the "page lazy recreation on revisit" approach that Hanrim had pre-listed in v1.0.6 Phase 2 Completion Record ยง11.3. Two side defects (_ver_lblupdate omission, output folder button text update omission) were resolved as a byproduct of the structural fix, and followingTEST_MANAGEMENT_POLICY.mdยง3 principle #4 (codify automated coverage for new features),TestSettingsDialogStructureInvariantwith 3 invariant tests was added โ ensuring CI automatically catches any future accidental breakage of the Option C mechanism.
โจ ์ฃผ์ ๊ธฐ๋ฅ / Major Features
-
์ค์ ๋ค์ด์ผ๋ก๊ทธ ํ์ด์ง lazy ์ฌ์์ฑ ๋ฉ์ปค๋์ฆ ๋์ / Settings dialog page lazy recreation mechanism
- ์ ๊ท ๋ฉ์๋
SettingsDialog._recreate_pages()โ ํ์ด์ง 4๊ฐ destroy + recreate / New methodSettingsDialog._recreate_pages()โ destroy + recreate 4 pages - 7๋จ๊ณ ์์ ํ๋ฆ: ๋จ์ถํค ์บก์ฒ ์์ ์ข
๋ฃ โ ์ถ๋ ฅ ํด๋ ์์ ์
๋ ฅ๊ฐ ๋ณด์กด โ ๊ธฐ์กด ํ์ด์ง ์์ ฏ ์ ๊ฑฐ(
removeWidget+deleteLater) โ ์ปจํ ์ด๋ dict ์ด๊ธฐํ โ ์ ํ์ด์ง ์์ฑ โ ์์ ์ ๋ ฅ๊ฐ ๋ณต์ โ ํ์ฌ ํ์ด์ง ์ ํ / 7-step safe flow: stop keyboard capture โ preserve unsaved output folder input โ remove old page widgets (removeWidget+deleteLater) โ clear container dicts โ create new pages โ restore unsaved input โ switch to current page - ์ํฌ์ด๋ผ์ด๋(์ค์ ์ฐฝ ์ฌ์คํ) ๋ฉ์ปค๋์ฆ์ ๋ช ์์ ์๋ํ โ v1.0.6 Phase 2 Completion Record ยง11.3 ๊ถ์ฅ ๋ฐฉํฅ๊ณผ ์ผ์น / Explicit automation of the existing workaround โ aligns with v1.0.6 Phase 2 Completion Record ยง11.3 recommendation
- ์ ๊ท ๋ฉ์๋
-
_refresh_theme/_retranslate_dialog์ฑ ์ ๋ช ํํ /_refresh_theme/_retranslate_dialogresponsibility clarification- ๋ค์ด์ผ๋ก๊ทธ ์ธ๊ณฝ ์์ ฏ๋ง ์ฑ
์์ง๋๋ก ๋จ์ํ. ํ์ด์ง ๋ด๋ถ ์์ ฏ์ stylesheetยทํ
์คํธ ๊ฐฑ์ ์
_recreate_pages์ ์ผ๊ด ์์ / Simplified to handle only outer dialog widgets; page-internal widget styling/text updates fully delegated to_recreate_pages _refresh_theme: 32์ค โ 30์ค / 32 lines โ 30 lines_retranslate_dialog: 48์ค โ 16์ค / 48 lines โ 16 lines
- ๋ค์ด์ผ๋ก๊ทธ ์ธ๊ณฝ ์์ ฏ๋ง ์ฑ
์์ง๋๋ก ๋จ์ํ. ํ์ด์ง ๋ด๋ถ ์์ ฏ์ stylesheetยทํ
์คํธ ๊ฐฑ์ ์
-
TestSettingsDialogStructureInvariant์ ์ค โ ์ต์ C ๋ฉ์ปค๋์ฆ ๊ตฌ์กฐ invariant /TestSettingsDialogStructureInvariantestablished โ Option C mechanism structural invarianttest_settings_dialog_has_recreate_pagesโ_recreate_pages๋ฉ์๋ ์กด์ฌ ๊ฒ์ฆ (hasattr+callable) /_recreate_pagesmethod existence verificationtest_refresh_theme_calls_recreate_pagesโ_refresh_theme๋ณธ๋ฌธ์self._recreate_pages()ํธ์ถ ํฌํจ ๊ฒ์ฆ (inspect.getsource๊ธฐ๋ฐ) /_refresh_themesource-level call verification (inspect.getsource)test_retranslate_dialog_simplifiedโ_retranslate_dialog์ด ํ์ด์ง ๋ด๋ถ attribute 9๊ฐ(_theme_page_title,_lang_page_title๋ฑ)๋ฅผ ์ง์ ๊ฐฑ์ ํ์ง ์์ ๊ฒ์ฆ /_retranslate_dialogdoes not directly touch 9 page-internal attributes (_theme_page_title,_lang_page_title, etc.)TEST_MANAGEMENT_POLICY.mdยง3 4๋ฒ ์์น(์ ๊ท ๊ธฐ๋ฅ์ ๋ํ ์๋ ์ปค๋ฒ๋ฆฌ์ง ๋ช ์) ์ ์ฉ. ์ต์ C ๋ฉ์ปค๋์ฆ์ด ํฅํ ๋๊ตฐ๊ฐ์ ์ค์๋ก ๊นจ์ง๋ฉด CI์์ ์ฆ์ ์๋ ๊ฐ์ง / AppliesTEST_MANAGEMENT_POLICY.mdยง3 principle #4 (codify auto-coverage for new features) โ accidental future breakage caught by CI immediately
-
์ฌ์ ์กฐ์ฌ โ ์ฝ๋ ์ง๋จ โ ์ต์ ์ฌํ๊ฐ ํ๋ฆ ๋ช ๋ฌธํ / Preliminary research โ code diagnosis โ option re-evaluation, codified
- v1.0.6 ยง11.3์ "์ฌ์ ์กฐ์ฌ ํ์" ์์น์ ์ค์ ์์ ํ๋ฆ์ผ๋ก ์ ์ฉํ ์ฒซ ์ฌ๋ก / First execution of the "preliminary research mandatory" principle from v1.0.6 ยง11.3 as actual workflow
- 4๊ฐ ์์ ๋ฌธ์ ์ฐ์ถ: ์ฌ์ ์กฐ์ฌ ๋ ธํธ / ์ฝ๋ ์ง๋จ ๋ณด๊ณ ์ / ์ต์ ์ฌํ๊ฐ ๋ณด๊ณ ์ / ์ต์ C ์์ ์ง์์ / 4 process documents produced: preliminary research note / code diagnosis report / option re-evaluation report / Option C work instruction
- ์ด ํ๋ฆ์ด ์ต์ A โ C ๋ณ๊ฒฝ์ ์ ์งํ ๊ทผ๊ฑฐ๊ฐ ๋จ (22๊ฐ ๋๋ฝ ๋ฐ๊ฒฌ ํ ๊ถ์ฅ ๋ณ๊ฒฝ) / This flow provided the honest rationale for switching Option A โ C (after discovering 22 omissions)
๐ ๋ฒ๊ทธ ์์ / Bug Fixes
-
์ค์ ๋ค์ด์ผ๋ก๊ทธ ๋ผ๋ฒจ/ํ๋ ์ color ์์ฌ ๋ฒ๊ทธ (v1.0.5๋ถํฐ ์กด์ฌ, ๋ณธ๊ณผ์ ) / Settings dialog label/frame color residue (pre-existing since v1.0.5, original target)
- ํ์: ๋ผ์ดํธ โ ๋คํฌ ๋ฐฉํฅ ํ ๋ง ์ ํ ํ ๋ค๋ฅธ ํญ ์ด๋ ์ ์ผ๋ถ ์์ ฏ(์ธ์ด ํ๋ ์ ๋ฐฐ๊ฒฝ, ํ์ดํ ๋ผ๋ฒจ color, ์ถ๋ ฅ ํด๋ ์์ ฏ)์ด ์ด์ ํ ๋ง ๊ฐ์ผ๋ก ์์ฌ. ์ค์ ์ฐฝ ์ฌ์คํ ์ ์ ์ ๋ณต๊ท (์ํฌ์ด๋ผ์ด๋) / Symptom: after light โ dark theme switch and tab navigation, some widgets (language frame background, title label color, output folder widgets) retained previous-theme values. Closing and reopening the settings dialog restored normal display (workaround)
- ๊ทผ๋ณธ ์์ธ: ํ์ด์ง 4๊ฐ์ inline stylesheet์ ์์๊ฐ์ด f-string์ผ๋ก ๋ฐํ ์์ฑ ์์ ํ
๋ง๋ก ์๊ตฌ ๊ณ ์ (v1.0.5๋ถํฐ์ ๊ตฌ์กฐ์ ํ๊ณ).
__init__์์ ๋จ ํ ๋ฒ ์์ฑ๋์ดQStackedWidget์ ์ ์ธต๋๋ฉฐ ์ ๋ ์ฌ์์ฑ๋์ง ์์ / Root cause: f-string-embedded colors in pages' inline stylesheets froze them at creation-time theme (structural limitation since v1.0.5). Pages were created exactly once in__init__and stacked intoQStackedWidget, never recreated - ์ฝ๋ ์ง๋จ์ผ๋ก ยง11.1์ "์ํฅ ์์ ฏ 3๊ฐ์ง"๊ฐ ์ค์ ๋ก๋ 22๊ฐ ์์ ฏ ๊ฐฑ์ ๋๋ฝ์ ๋น์ฐ ์ผ๊ฐ์์ด ๋๋ฌ๋จ โ ํ์ด์ง ๋ด๋ถ ๊ฑฐ์ ๋ชจ๋ inline stylesheet ์์ ฏ์ด ๋์ผํ ๊ตฌ์กฐ์ ๋ฌธ์ / Code diagnosis revealed ยง11.1's "3 affected widgets" were the visible tip of 22-widget update omission iceberg โ nearly all page-internal inline-stylesheet widgets shared the same structural defect
- ์์ : ์ต์ C(ํ์ด์ง lazy ์ฌ์์ฑ) โ ํ ๋ง/์ธ์ด ๋ณ๊ฒฝ ์ ํ์ด์ง 4๊ฐ๋ฅผ destroy + recreate. ์ํฌ์ด๋ผ์ด๋ ๋ฉ์ปค๋์ฆ์ ์๋ํ / Fix: Option C (page lazy recreation) โ destroy + recreate all 4 pages on theme/language change. Automation of the existing workaround
- ์ต์
A โ C ์ ์งํ ์ฌํ๊ฐ: ์ฒ์ ๊ถ์ฅํ๋ ์ต์
A(Targeted ๊ฐฑ์ ,
6080์ค)๋ 22๊ฐ ์์ ฏ ๋ฐ๊ฒฌ ํ ๋๋ฝ ์ฌ๋ฐ ์ํ ์๊ตฌ ๋ณด์ ๋ผ๋ ํ๊ณ๊ฐ ๋๋ฌ๋จ. ์ต์ C(+17์ค)๋ก ๋ณ๊ฒฝํ์ฌ ์ฝ๋ ๋ณ๊ฒฝ๋ 1/4๋ก ์ถ์ + ๊ตฌ์กฐ์ ํด๊ฒฐ / Honest re-evaluation Option A โ C: initially recommended Option A (targeted updates,6080 lines) revealed permanent recurrence risk after the 22-widget discovery. Switched to Option C (+17 lines) โ quarter the code change + structural resolution
-
_ver_lblํ ๋ง ์ ํ ๊ฐฑ์ ๋๋ฝ (์ฌ์ด๋ ๊ฒฐํจ, v1.0.6 ์์ฌ) /_ver_lbltheme switch update omission (side defect, v1.0.6 residue)- ํ์: ์ฌ์ด๋๋ฐ ํ๋จ ๋ฒ์ ๋ผ๋ฒจ์ด ํ ๋ง ์ ํ ์ ๊ฐฑ์ ๋์ง ์์ ์ด์ ํ ๋ง ์์์ผ๋ก ์์ฌ / Symptom: sidebar bottom version label retained previous theme colors after theme switch
- ๋ฐ๊ฒฌ ๊ฒฝ๋ก: v1.0.6 ์ฝ๋์
# v1.0.6: ํ ๋ง ์ ํ ์ ๊ฐฑ์ ์ฉ self ์ ์ฅ์ด๋ผ ์ฃผ์ ๋ฌ์๋๊ณ ๋_refresh_themeํธ์ถ์ด ๋๋ฝ๋ ๊ฒฐํจ์ด ์ต์ C ์์ ์ค ์ฝ๋ ์ง๋จ ๋จ๊ณ์์ ๋ฐ๊ฒฌ / Discovery: v1.0.6 source contained the comment# v1.0.6: stored on self for theme switch updatesbut the actual_refresh_themecall was missing โ surfaced during Option C code diagnosis - ์์ :
_refresh_theme์ 1์ค ์ถ๊ฐ (์ธ๊ณฝ ์์ ฏ์ด๋ผ_recreate_pages์ฒ๋ฆฌ ๋์ ์๋) / Fix: 1 line added to_refresh_theme(outer widget, not handled by_recreate_pages)
-
์ถ๋ ฅ ํด๋ ๋ฒํผ ํ ์คํธ ๊ฐฑ์ ๋๋ฝ (์ฌ์ด๋ ๊ฒฐํจ, v1.0.6 D-2 ์์ฌ) / Output folder button text update omission (side defect, v1.0.6 D-2 residue)
- ํ์: ์ธ์ด ๋ณ๊ฒฝ ์ ์ถ๋ ฅ ํด๋ [์ ํ] / [๊ธฐ๋ณธ๊ฐ] ๋ฒํผ ํ ์คํธ๊ฐ ์ด์ ์ธ์ด๋ก ์์ฌ / Symptom: output folder [Pick] / [Reset] button text retained previous language after language change
- ๊ทผ๋ณธ ์์ธ:
_retranslate_dialog์ดself._odir_btn/self._odir_reset_btn์ ์ฐธ์กฐํ์ง๋ง,_page_language์์๋ ๋ก์ปฌ ๋ณ์odir_btn/odir_reset๋ก๋ง ๋ง๋ค์ดhasattr๊ฒ์ฌ๋ก silently fail / Root cause:_retranslate_dialogreferencedself._odir_btn/self._odir_reset_btn, but_page_languageonly created them as local variablesodir_btn/odir_resetโ thehasattrguard caused silent failure - ์์ : ํ์ด์ง ์ฌ์์ฑ์ผ๋ก ์๋ ํด๊ฒฐ (์ต์ C ๋ถ์ ํจ๊ณผ) / Fix: automatically resolved by page recreation (Option C byproduct)
๐ ๋ฌธ์ / Documentation
CHANGELOG.mdv1.0.8 ์น์ ์ ์ค /CHANGELOG.mdv1.0.8 section added- Fixed / Changed / Added / Tests / Documentation / File Changes 6๊ฐ ํ์ ์น์ / 6 subsections: Fixed / Changed / Added / Tests / Documentation / File Changes
FileNexusSuite.pyAPP_VERSION์์ ๊ฐฑ์ /FileNexusSuite.pyAPP_VERSIONconstant update- L76
APP_VERSION = "1.0.7"โ"1.0.8"โ f-string์ผ๋ก ์ฐธ์กฐ๋๋ ๋์๋ง ์ฐฝ ํ์ดํ 5๊ฐ ์ธ์ด + ์ฌ์ด๋๋ฐ ๋ฒ์ ๋ผ๋ฒจ์ด ์๋ ์ผ๊ด ๊ฐฑ์ / All f-string references (5-language help titles + sidebar version label) automatically updated
- L76
version_info.txt4๊ณณ ๊ฐฑ์ /version_info.txt4-point updatefilevers/prodversํํ +FileVersion/ProductVersion๋ฌธ์์ด ๋ชจ๋ v1.0.8 / 1.0.8.0์ผ๋ก ์ ํฉ ํ๋ณด. PyInstaller ๋น๋ ์ Windows.exe์์ฑ ์ฐฝ ๋ฉํ๋ฐ์ดํฐ ์ ํฉ / All aligned to v1.0.8 / 1.0.8.0:filevers/prodverstuples +FileVersion/ProductVersionstrings. PyInstaller.exeproperties metadata consistency secured
README.md/README_EN.md๋ฑ์ง ๋๊ธฐํ /README.md/README_EN.mdbadge sync- version ๋ฑ์ง 1.0.7 โ 1.0.8, tests ๋ฑ์ง 531 โ 534 ์์ชฝ ์ผ์น / version badge 1.0.7 โ 1.0.8, tests badge 531 โ 534 โ both READMEs synchronized
- **`RE...
File Nexus Suite v1.0.7
v1.0.7 โ ๊ธฐ์ ๋ถ์ฑ ์ ๋ฆฌ + GitHub Actions CI ๋์ + ํ ์คํธ ๊ด๋ฆฌ ์ ์ฑ ์๋ฆฝ / Technical debt cleanup + GitHub Actions CI adoption + test management policy establishment
v1.0.7์ ๊ธฐ๋ฅ ์ถ๊ฐ๊ฐ ์๋ ๊ธฐ์ ๋ถ์ฑ ์ ๋ฆฌ์ ์ธํ๋ผ ๊ฐํ์ ์ง์คํ ๋ฆด๋ฆฌ์ฆ์
๋๋ค. 3๊ฐ ์ฌ์ ์์
์ธ์
์ ํตํด ๋ฒ์ญํค ๊ณ ์ 15๊ฑด์ ์ ๊ฑฐํ๊ณ invariant ํ
์คํธ๋ฅผ ํญ ๊ธฐ๋ฐ 10๊ฐ ๋๋ถ๋ฅ๋ก ์ฌ๊ตฌ์ฑํ์ผ๋ฉฐ, ๋งค ๋ฆด๋ฆฌ์ฆ๋ง๋ค ์๋์ผ๋ก ์ด์ํด์ค๋ ๋ฒ์ ์ค๋
์ท ๋ฐฉ์์ ํ๊ณ๋ฅผ ๋ช
๋ฌธํํ **TEST_MANAGEMENT_POLICY.md**๋ฅผ ์ ์คํ์ต๋๋ค. ๊ฐ์ฅ ์ค์ํ ๋ณํ๋ GitHub Actions CI ๋์
์ผ๋ก, ์ฒซ ์คํ๋ถํฐ ๋ก์ปฌ์์ ๋ฐ๊ฒฌ๋์ง ์๋ ์จ์ ์ด์ 2๊ฑด(์ ๋ น PyPI ํจํค์ง, Windows ์์ด ๋ก์ผ์ผ UnicodeEncodeError)์ ์ฆ์ ๋๋ฌ๋ด๋ฉฐ ๊ฐ์น๋ฅผ ์
์ฆํ์ต๋๋ค. APP_VERSION ์์์ ๋ฒ์ -๋
๋ฆฝ ๊ตฌ์กฐ ๊ฒ์ฆ ์ฌ์ค๊ณ, version_info.txt ์ ํฉ ํ๋ณด, README ๋ฑ์ง ํ์ฅ์ผ๋ก v1.0.7๋ถํฐ ๋ชจ๋ ๋ฆด๋ฆฌ์ฆ๊ฐ CI ์๋ ๊ฒ์ฆ์ ๊ฑฐ์น๋ค๋ ์๋ก์ด ๊ธฐ์ค์ ์ด ํ๋ฆฝ๋์ต๋๋ค.
v1.0.7 is a technical-debt-cleanup release focused on infrastructure reinforcement rather than new features. Through three preparatory sessions, 15 orphan translation keys were removed and invariant tests were restructured into tab-based 10 functional categories, and
TEST_MANAGEMENT_POLICY.mdโ a new permanent reference document โ was established to codify the limits of the version-snapshot approach previously migrated by hand each release. The most significant change is the adoption of GitHub Actions CI, which immediately proved its value by surfacing two hidden issues on its very first runs (a phantom PyPI package, and Windows English-locale UnicodeEncodeError) that had gone undetected locally. With theAPP_VERSIONconstant redesigned for version-independent structural verification,version_info.txtalignment secured, and README badges expanded, a new baseline is established: every release from v1.0.7 onward passes CI's automatic verification.
โจ ์ฃผ์ ๊ธฐ๋ฅ / Major Features
-
GitHub Actions CI ๋์ / GitHub Actions CI adoption
- ๋ฌ๋:
windows-latest๋จ์ผ โ ํ๋ฆผ ๋ก์ปฌ Windows ํ๊ฒฝ๊ณผ ์ผ์น, 531/0/0/0 ์ฌํ ์ต์ฐ์ / Runner:windows-latestsingle โ matches Hanrim's local Windows, prioritizing 531/0/0/0 reproduction - Python 3.10 ๋จ์ผ โ ํ๋ฆผ ๋ก์ปฌ Python 3.10.11๊ณผ ์ผ์น / Python 3.10 single โ matches local Python 3.10.11
- pip ์บ์ ์ ์ฉ โ 2๋ฒ์งธ ์คํ๋ถํฐ 1
2๋ถ ๋ด ์๋ฃ / pip cache enabled โ subsequent runs complete in 12 minutes - ํธ๋ฆฌ๊ฑฐ:
mainpush/PR +workflow_dispatch/ Triggers:mainpush/PR +workflow_dispatch - ์ปค์คํ
๋ฌ๋ exit code ๊ณ์ฝ โ ์คํจ/์ค๋ฅ ์
sys.exit(1)๋ฐํ์ผ๋ก CI ๋ฑ์ง ์ ํ์ฑ ๋ณด์ฅ / Custom runner exit-code contract โ returnssys.exit(1)on failure/error for CI badge accuracy - CI ์ฒซ ์คํ์์ ์ด๋ฏธ 2๊ฑด์ ์จ์ ์ด์ ๋ฐ๊ฒฌ โ ํ๋ก์ ํธ ์์ฑ๋์ ์ค์ง์ ํฅ์ / Two hidden issues already surfaced on CI's first runs โ real-world improvement in project completeness
- ๋ฌ๋:
-
์ธ์ 3 โ ๋ฒ์ญํค ๊ณ ์ 15๊ฑด ์ ๋ฆฌ / Session 3 โ 15 orphan translation key cleanup
- ฮฒ ํ๋กํ ์ฝ ์ ์ฉ ๊ฐ์ฌ: 17๊ฑด ๋ณด๊ณ โ 2๊ฑด ํ์ฑ ์ฌ์ฉ ํ์ธ(
conv_sub_txt2epub/conv_sub_epub2txt๋์ ๋์คํจ์น) โ 15๊ฑด ์ ๊ฑฐ + 2๊ฑด ๋ํ ํค ํธ์ / ฮฒ-protocol audit: 17 reported โ 2 confirmed actively used (conv_sub_txt2epub/conv_sub_epub2txtdynamic dispatch) โ 15 removed + 2 absorbed as representative keys - ์ ๊ฑฐ๋ ํค 15๊ฐ:
bulk_out_folder,bulk_save_dir,bulk_save_fixed,bulk_save_over,merge_file_list,merge_file_mgmt,p_prefix_ph,sort_header,tag_file_list,tag_preview_title,tf_dlg_overwrite,tf_grp_opt,tf_ph_input,tf_subtitle,tf_title/ 15 removed keys - ์ด 76์ค ์ ๊ฑฐ (15ํค ร 5์ธ์ด + ์ฃผ์ 1์ค) / Total 76 lines removed (15 keys ร 5 languages + 1 comment line)
- ฮฒ ํ๋กํ ์ฝ ์ ์ฉ ๊ฐ์ฌ: 17๊ฑด ๋ณด๊ณ โ 2๊ฑด ํ์ฑ ์ฌ์ฉ ํ์ธ(
-
์ธ์ 3 โ invariant ํ ์คํธ ํญ ๊ธฐ๋ฐ 10๊ฐ ๋๋ถ๋ฅ ์ฌ๊ตฌ์ฑ / Session 3 โ invariant tests restructured into 10 tab-based major categories
- ์ ๊ฑฐ๋ ๊ตฌ ๋ฒ์ ์ค๋
์ท ํ
์คํธ 7๊ฐ:
test_all_langs_have_dlg_keys,test_all_langs_have_sort_header,test_all_langs_have_sc_tab_bulk,test_all_langs_have_new_v010_keys,test_rename_keys_exist,test_all_langs_have_v010_1_keys,test_all_langs_have_v100_keys/ 7 removed version-snapshot tests - ์ ์ค 9๊ฐ ํญ ๊ธฐ๋ฐ ํ
์คํธ:
common_dialog/text_merger/text_converter/tag_editor/batch_renamer/text_fixer/settings/shortcut/misc(๊ธฐ์กดbulk_fixer_keysํ์ฅ ์ ์ง) / 9 new tab-based tests test_ko_has_minimum_keys๊ธฐ์ค ์์น ๊ฐฑ์ (280 โ 400, ํ 404๊ฐ ๊ธฐ์ค ์์ ๋ง์ง) / Minimum key count threshold updated (280 โ 400, safety margin based on current 404)- ๊ดํต ์ถ: "์ญ์ฌ๋ Git ์ด๋ ฅ๊ณผ CHANGELOG๊ฐ ๋ด๋นํ๊ณ , ํ ์คํธ๋ ํ์ฌ ์ด์์๋ ๋ช ์ธ๋ก ์ ์ง๋๋ค" / Guiding principle: "History belongs to Git log and CHANGELOG; tests remain living specifications"
- ์ ๊ฑฐ๋ ๊ตฌ ๋ฒ์ ์ค๋
์ท ํ
์คํธ 7๊ฐ:
-
์ธ์ 3 โ
TEST_MANAGEMENT_POLICY.md์ ์ค / Session 3 โTEST_MANAGEMENT_POLICY.mdestablished- ํ๋ก์ ํธ ์๊ตฌ ์ฐธ์กฐ ๋ฌธ์ (155์ค, ๋ฃจํธ ๋ฐฐ์น) / Permanent project reference document (155 lines, placed at repo root)
- 5๋ ์์น ๋ช ๋ฌธํ + ๋ฐ๋ ํ์ ๊ธฐ์ค 5๊ฐ (ํ ์คํธ ํ์ผ invariant ๋ฑ๋ก ์ฌ๋ถ ์ ์ค ํฌํจ) / Codified 5 core principles + 5 dead-code judgment criteria (including new "test-file invariant registration" criterion)
- ๋๋ถ๋ฅ 10๊ฐ ๋ช ์ธ + ๊ธ์ง ์ฌํญ (๋ฒ์ ์ค๋ ์ท ๋ฐฉ์ invariant ์ ๊ท ๋์ ๊ธ์ง) / 10 category specifications + prohibitions (ban on new version-snapshot-style invariants)
-
TestAppVersion๋ฒ์ -๋ ๋ฆฝ ๊ตฌ์กฐ ๊ฒ์ฆ ์ฌ์ค๊ณ /TestAppVersionredesigned for version-independent structural verification- ๊ธฐ์กด ๊ด๋ก:
TestV104RegressionโTestV105RegressionโTestV106AppVersion๋งค ๋ฆด๋ฆฌ์ฆ ์ด์ / Previous pattern: migration at each release - ์ฌ์ค๊ณ: ์ธ๋ฏธ๋ฒ์ (MAJOR.MINOR.PATCH) ํฌ๋งท ๊ฒ์ฆ์ผ๋ก ์ ํ โ ํฅํ ๋ฒ์ ๊ฐฑ์ ์ ํ ์คํธ ์์ ๋ถํ์ / Redesign: switched to semver (MAJOR.MINOR.PATCH) format validation โ no test updates needed on future version bumps
TEST_MANAGEMENT_POLICY.mdยง4.4 "๋ฒ์ ์ค๋ ์ท ๋ฐฉ์ invariant ์ ๊ท ๋์ ๊ธ์ง" ์์น์ ๋ฒ์ญํค ์ธ ์ฝ๋ ๋ฒ์ ์ค๋ ์ท์๋ ์ ์ฉ / AppliedTEST_MANAGEMENT_POLICY.mdยง4.4 "ban on new version-snapshot-style invariants" to code version snapshots as well
- ๊ธฐ์กด ๊ด๋ก:
๐ ๋ฒ๊ทธ ์์ / Bug Fixes
-
APP_VERSION์์ ๊ฐฑ์ ๋๋ฝ /APP_VERSIONconstant update omission (์ธ์ 3 ๋๋ฝ / session 3 omission)- ํ์:
FileNexusSuite.pyL76APP_VERSION = "1.0.6"๊ทธ๋๋ก ๋จ์ ์ฑ ํ์ดํยท๋์๋ง ์ฐฝ ๋ฒ์ ํ์๊ฐ v1.0.6์ผ๋ก ๋ณด์ / Symptom: L76APP_VERSION = "1.0.6"left unchanged โ app title and help window version display showed v1.0.6 - ๋ฐ๊ฒฌ: ๋ฆด๋ฆฌ์ฆ ์ง์ ํ๋ฆผ์
findstr /S /I "1\.0\.6"์ ์ ๊ฒ์ฆ์ผ๋ก ๋๋ฌ๋จ / Discovered: during Hanrim's pre-releasefindstr /S /I "1\.0\.6"verification sweep - ์์ :
APP_VERSION = "1.0.7"๊ฐฑ์ โ f-string์ผ๋ก ์ฐธ์กฐ๋๋ ์ฑ ์ ์ญ ๋ฒ์ ํ์๊ฐ ์๋ ์ผ๊ด ๊ฐฑ์ / Fix: updated to "1.0.7" โ all f-string references across the app automatically reflect the new version
- ํ์:
-
version_info.txt๋ฒ์ 4๊ณณ ์์กด /version_info.txt4-point version residue- ํ์:
filevers,prodversํํ +FileVersion,ProductVersion๋ฌธ์์ด์ด ๋ชจ๋1.0.6/ Symptom:filevers/prodverstuples andFileVersion/ProductVersionstrings all at1.0.6 - ์ํฅ: PyInstaller ๋น๋ ์ Windows
.exe์์ฑ ์ฐฝ์ ๋ฒ์ ๋ฉํ๋ฐ์ดํฐ๊ฐ v1.0.6์ผ๋ก ํ์๋จ / Impact: PyInstaller builds would show v1.0.6 in Windows.exefile properties - ์์ : 4๊ณณ ๋ชจ๋ v1.0.7 / 1.0.7.0์ผ๋ก ๊ฐฑ์ โ
Copyright ยฉ 2026 Hanrimํ๊ธฐ๋ ์ ์ง (๋งค์ฒด๋ณ ๊ฐ๊ฒฐ/ํ๋ค์ ๊ตฌ๋ถ ์ ์ฑ ) / Fix: all 4 locations updated โCopyright ยฉ 2026 Hanrimpreserved (per-medium brevity/full-name policy)
- ํ์:
-
CI ์ฒซ ์คํ hotfix โ PyPI ์ ๋ น ํจํค์ง / CI first-run hotfix โ phantom PyPI package
- ํ์:
pip install -r requirements.txt์คํ ์PySide6-Qt6-Qt6Svg>=6.4.0์์ERROR: Could not find a version that satisfies the requirement์คํจ (CI #1, 39์ด) / Symptom: pip install failed with "No matching distribution found" forPySide6-Qt6-Qt6Svg>=6.4.0(CI #1, 39s) - ์์ธ: PyPI์ ์กด์ฌํ์ง ์๋ ํจํค์ง. ํ๋ฆผ ๋ก์ปฌ์์๋ ์ด๋ฏธ ์ค์น๋ ์ํ๋ผ
pip install์ ์กฐ์ฉํ ๋์ด๊ฐ ๋ฐ๊ฒฌ๋์ง ์์ / Cause: package does not exist on PyPI. Locally, it was already installed, so pip silently skipped โ the issue went undetected - ์์ :
requirements.txt์์ ํด๋น ์ค ์ ๊ฑฐ. PySide6 ๋ณธ์ฒด๊ฐ QtSvg ๋ชจ๋์ ๋ด์ฅ / Fix: removed the line fromrequirements.txt. PySide6 bundles QtSvg natively - ์์: CI ๋์ ์ ๊ฐ์น๊ฐ ์ฒซ ์คํ์์ ๋ฐ๋ก ์ ์ฆ๋จ / Significance: CI's value proven on its very first run
- ํ์:
-
CI 2๋ฒ์งธ ์คํ hotfix โ Windows ๋ก์ผ์ผ UnicodeEncodeError / CI second-run hotfix โ Windows locale UnicodeEncodeError
- ํ์: ํ
์คํธ ๋ฌ๋ ์คํ ์ค
UnicodeEncodeError: 'charmap' codec can't encode character '\ud83d'(CI #2, 1๋ถ 10์ด) / Symptom:UnicodeEncodeError: 'charmap' codec can't encode character '\ud83d'during test runner (CI #2, 1m 10s) - ์์ธ: GitHub Actions
windows-latest๊ธฐ๋ณธ ์ฝ์ ์ธ์ฝ๋ฉ์ดcp1252(์์ด ๋ก์ผ์ผ)๋ผ ํ๊ธยท์ด๋ชจ์ง ์ถ๋ ฅ ์คํจ. ํ๋ฆผ ๋ก์ปฌ์cp949๋๋ UTF-8 ๋ชจ๋๋ผ ๋ฌธ์ ์์ / Cause: GitHub Actionswindows-latestdefault console encoding iscp1252(English locale), failing on Korean/emoji output. Local Windows usescp949or UTF-8 mode - ์์ : ์ปค์คํ
๋ฌ๋ ์ง์
๋ถ์
sys.stdout.reconfigure(encoding='utf-8')์ถ๊ฐ (Python 3.7+ ํ์ค,hasattr๊ฐ๋๋ก ๋ฌดํด) / Fix: addedsys.stdout.reconfigure(encoding='utf-8')at runner entry (Python 3.7+ standard, guarded byhasattr)
- ํ์: ํ
์คํธ ๋ฌ๋ ์คํ ์ค
-
์์กด์ฑ ์ ์ธ ๋ถ์ผ์น / Dependency declaration inconsistency
requirements.txt์python-hwpx>=2.9.0๋๋ฝ โ v1.0.6 HWPX ์ ๋ ฅ ์ง์ ์์กด์ฑ์ด READMEยท๊ธฐ์ ์คํ์๋ง ๋ช ์๋๊ณ requirements์์ ๋น ์ ธ ์๋ ๋ถ์ผ์น ํด์ /python-hwpx>=2.9.0was missing fromrequirements.txtโ v1.0.6 HWPX input support dependency was only stated in README/tech-stack but missing from requirements; inconsistency now resolved
-
README_EN.md๋ฑ์ง ๋๊ธฐํ ๋๋ฝ /README_EN.mdbadge sync omission- ์ธ์ 3์์ ํ๊ตญ์ด README๋ง ๊ฐฑ์ ํ๊ณ ์์ด ๋ฒ์ ์ ๋๋ฝ / Korean README was updated in session 3, but English version was overlooked
- ์์ : version ๋ฑ์ง 1.0.6 โ 1.0.7, CI ๋ฑ์ง ์ถ๊ฐ, tests ๋ฑ์ง ์ถ๊ฐ, ์ค์น ๋ช
๋ น์ด
pip install -r requirements.txt๋ก ๋จ์ํ / Fix: version badge 1.0.6 โ 1.0.7, CI badge added, tests badge added, install command simplified
๐ ๋ฌธ์ / Documentation
TEST_MANAGEMENT_POLICY.md์ ์ค (155์ค, ๋ฃจํธ ๋ฐฐ์น) / NewTEST_MANAGEMENT_POLICY.md(155 lines, repo root)- ํ ์คํธ ๊ด๋ฆฌ 5๋ ์์น, ๋๋ถ๋ฅ 10๊ฐ ๋ช ์ธ, ๋ฐ๋ ํ์ ๊ธฐ์ค, ๊ธ์ง ์ฌํญ์ ๋ช ๋ฌธํํ ํ๋ก์ ํธ ์๊ตฌ ์ฐธ์กฐ ๋ฌธ์ / Codifies 5 core principles of test management, 10 category specifications, dead-code criteria, and prohibitions โ permanent project reference
CHANGELOG.mdv1.0.7 ์น์ ํ์ฅ /CHANGELOG.mdv1.0.7 section expanded- Fixed / Removed / Changed / Added / Tests / File Changes / Deferred 7๊ฐ ํ์ ์น์ / 7 subsections: Fixed / Removed / Changed / Added / Tests / File Changes / Deferred
README.md/README_EN.md๋ฑ์ง ํ์ฅ /README.md/README_EN.mdbadge expansion- CI ์ํ ๋ฑ์ง +
531 tests passing๋ฑ์ง ์ถ๊ฐ, ์ค์น ๋ช ๋ น์ด ๋จ์ผ ์ง์ค ์์ฒํ (pip install -r requirements.txt) / CI status badge +531 tests passingbadge added; install command centralized
- CI ์ํ ๋ฑ์ง +
๐งช ํ ...
File Nexus Suite v1.0.6
v1.0.6 โ Text Converter ๊ตฌ์กฐ ๋ฆฌํฉํ ๋ง + ๋ถ๋ถ ์์ ํ์ผ ๋์ + ์ค์ ๋ค์ด์ผ๋ก๊ทธ ๋ฒ์ฒด ์์ฌ ์์ / Text Converter refactoring + partial corruption handling + Settings dialog Traditional Chinese residue fix
Text Converter ๋ ์ด์์์ Bulk Fixer(v1.0.6) ํจํด์ผ๋ก ์ฌ๊ตฌ์ฑํ์ฌ ๋๋กญ์กด ๋ถ๋ฆฌยท5:4 ๋ ์ด์์ยทํ๋จ ์๋ด ๋ฐ์ค ์ ๊ฑฐ๋ฅผ ์ ์ฉํ๊ณ , ๋ฉ๋ชจ์ฅ์์ ์ด๋ฆฌ๋๋ฐ Python strict ํด๋ฐฑ์ด ๋ชจ๋ ์คํจํ๋ ๋ถ๋ถ ์์ ์ธ์ฝ๋ฉ ํ์ผ ๋์์ ์ถ๊ฐํ์ต๋๋ค(Phase 1 + Phase 2-a ํฐ์ด๋ ์๋ ์ฒ๋ฆฌ). Text Merger๋ HWPX ์
๋ ฅ ์ง์๊ณผ A1'' ์ธ์ฝ๋ฉ ์๋ ์ถ์ฒ ๊ธฐ๋ฅ์ ์ป์๊ณ , v1.0.5๋ถํฐ ์กด์ฌํ๋ ์ค์ ๋ค์ด์ผ๋ก๊ทธ ๋ฒ์ฒด ์ค๊ตญ์ด ์์ฌ ๋ฒ๊ทธ๋ฅผ ๊ทผ๋ณธ ์์ ํ์ต๋๋ค. ๋ฐ์ดํฐ ์์ค ์ํ์ด ์๋ toolTip ์ค์ผ ๋ฒ๊ทธ์ ํค๋ ์ ๋ ฌ ๋ฒ๊ทธ๋ ํจ๊ป ํด๊ฒฐํ๊ณ , ๋ถ ๋จ์ ๊ฑธ๋ฆฌ๋ O(NรK) ์์น ์ถ์ ์๊ณ ๋ฆฌ์ฆ์ O(N)์ผ๋ก ์ฌ์ค๊ณํด ์๋ฐฑ~์์ฒ ๋ฐฐ ์ฑ๋ฅ์ ๊ฐ์ ํ์ต๋๋ค.
Rebuilt the Text Converter layout along the Bulk Fixer (v1.0.6) pattern โ drop-zone separation, 5:4 left-right ratio, bottom help-box removal โ and added proper handling for partially corrupted encoding files that Notepad opens fine but Python's strict fallback all fail on (Phase 1 + Phase 2-a tiered automatic processing). Text Merger gained HWPX input support and A1'' automatic encoding recommendation, and a pre-existing Settings dialog Traditional Chinese residue bug (from v1.0.5) was rooted out. Also resolved the
toolTipcontamination bug (with data-loss risk) and header-sort bug, and redesigned theO(NรK)position-tracking algorithm toO(N)for hundreds-to-thousands times speedup on previously minute-long operations.
โจ ์ฃผ์ ๊ธฐ๋ฅ / Major Features
-
Phase 2-a โ ์ธ์ฝ๋ฉ ๋ฆฌํฌํธ ๊ธฐ๋ฅ + ํฐ์ด๋ ์๋ ์ฒ๋ฆฌ / Phase 2-a โ encoding report generation + tiered automatic processing
- Bulk Fixer๊ฐ ๋ถ๋ถ ์์ ํ์ผ์ ์ธ ํฐ์ด๋ก ์๋ ๋ถ๋ฅ / Bulk Fixer now automatically classifies partially corrupted files into three tiers
- Tier 1 (์์ โค500์): ์ฒ๋ฆฌ + ๋ฆฌํฌํธ ์์ฑ / Tier 1 (โค500 corrupt chars): process + generate report
- Tier 2 (์์ 501
5000์): ์ฒ๋ฆฌ + ๊ฒฝ๊ณ ์์ ๋ฆฌํฌํธ / Tier 2 (5015000 corrupt chars): process + elevated-warning report - Tier 3 (์์ 5001์+): ์๋ณธ ๋ณดํธ ์คํต + ๋ฆฌํฌํธ๋ง / Tier 3 (5001+ corrupt chars): skip to preserve original + report only
- ๋ฆฌํฌํธ ํ์ผ๋ช
:
{์๋ณธํ์ผ๋ช }.encoding_report.txt(UTF-8 BOM ์์) / Report filename:{original}.encoding_report.txt(UTF-8 without BOM) - ์ค์ธก ๊ธฐ๋ฐ ์๊ณ๊ฐ ๊ฒฐ์ โ
make_tier_test_data.py๋ก ๊ฒฝ๊ณ๊ฐ(499/5000/5001) ํฉ์ฑ ๋ฐ์ดํฐ ํ๊ท ๊ฒ์ฆ / Empirically-chosen thresholds โ boundary values (499/5000/5001) validated via synthesized test data inmake_tier_test_data.py - ์ค๊ณ ์ฒ ํ ๋ถ๋ฆฌ: Text Fixer(์ฌ์ฉ์ ๋์ ๊ธฐ๋ฐ) / Bulk Fixer(์ฌํ ํฌ๋ช ์ฑ ๊ธฐ๋ฐ) / Philosophy separation: Text Fixer (user-consent based) vs. Bulk Fixer (post-hoc transparency based)
-
#7 Text Converter ๊ตฌ์กฐ ๋ฆฌํฉํ ๋ง / #7 Text Converter structural refactoring
- ์ ๊ท ํด๋์ค
TextConverterDropZone(109์ค) โBulkFixerDropZone๋ณต์ +modeํ๋ผ๋ฏธํฐ๋ก TXTโEPUB ์ ํ ์ ํ ์คํธยท์์ด์ฝ ์๋ ๊ฐฑ์ / New classTextConverterDropZone(109 lines) โ cloned fromBulkFixerDropZone+modeparameter auto-refreshing text/icon on TXTโEPUB toggle TextConverterFileList๋จ์ํ โInternalMoveโDragDrop๋ชจ๋ ์ ํ,setSectionsClickable(True)๋ช ์,startDragCopyAction ๊ฐ์ / SimplifiedTextConverterFileListโInternalMoveโDragDrop, explicitsetSectionsClickable(True), forcedstartDragCopyAction- ๋ ์ด์์ 5:4 ์ฌ๊ตฌ์ฑ โ ์ผ์ชฝ(๋๋กญ์กด+ํ์ผ๋ชฉ๋ก) ํ๋, ์ค๋ฅธ์ชฝ(์ต์ +์ถ๋ ฅํด๋+๋ณํ๋ฒํผ+์งํ๋ฐ+์ํ) ์ฌ๋ฐฐ์น / Layout restructured 5:4 โ left panel (dropzone + file list) expanded, right panel (options + output folder + convert button + progress + status) rearranged
- ํ๋จ ์๋ด ๋ฐ์ค ์ ๊ฑฐ (
conv_help5๊ฐ ์ธ์ด ๋ฒ์ญ ํค ์ญ์ ) / Bottom help-box removed (conv_helptranslation keys dropped across 5 languages) - ํด๋ ๋๋กญ ๋ฏธ์ง์ โ EPUB ์์ฑ ์ ์๋ณธ ํด๋ ๊ตฌ์กฐ ๋ณด์กด ์ด์ ๋ฐฉ์ง (์๋๋ ์ค๊ณ) / Folder drop unsupported โ intentional design to avoid EPUB source-folder structure preservation issues
- ์ค๊ธฐ QA 9/9 ์ ์ ํต๊ณผ โ ๋๋กญ์กด ์๋ฐฉํฅ / ๋ชจ๋ ์ ํ / ๋ด๋ถ ๋๋๊ทธ / ํค๋ ์ ๋ ฌ / 5:4 / 5๊ฐ ์ธ์ด / ๋ณํ E2E / toolTip ํ๊ท / ํ ๋ง ์ ํ / IceCream Ebook Reader ์ธ๋ถ ๊ฒ์ฆ ํฌํจ / Manual QA 9/9 passed โ dropzone bidirectional / mode toggle / internal drag / header sort / 5:4 / 5 languages / round-trip conversion / toolTip regression / theme switch / with external IceCream Ebook Reader verification
- ์ ๊ท ํด๋์ค
-
Text Merger โ HWPX ์ ๋ ฅ ์ง์ / Text Merger โ HWPX input support
python-hwpx 2.9.0(MIT) ๋์ ,.hwpxโ ํ ์คํธ ์ถ์ถ / Addedpython-hwpx 2.9.0(MIT),.hwpxโ text extractionMergeEncodingDelegate์ HWPX ๋ฐฐ์ง(#9B59B6 ๋ณด๋ผ์) ํ์ / Purple HWPX badge (#9B59B6) onMergeEncodingDelegate- HWP(๊ตฌํ) ๊ฐ์ง ์ ํตํฉ ์๋ด ๋ค์ด์ผ๋ก๊ทธ โ 5๊ฐ ์ธ์ด / HWP (legacy) detection shows a unified informational dialog across 5 languages
lxml5.4.0์ผ๋ก ์๋ ๋ค์ด๊ทธ๋ ์ด๋ ๋ฐ์ (๊ฒฝ๊ณ ๋ง, ๋์ ์ํฅ ์์) /lxmlauto-downgraded to 5.4.0 (warning only, no functional impact)
-
Text Merger โ A1'' ์ธ์ฝ๋ฉ ์๋ ์ถ์ฒ / Text Merger โ A1'' automatic encoding recommendation
- ์ ํจ์
merger_recommend_save_encoding()โ ๋ชจ๋ ํ ์คํธ ํ์ผ์ด ๊ฐ์ ๋น์ ๋์ฝ๋ ์ธ์ฝ๋ฉ + ์ ๋ขฐ๋ โฅ0.7์ผ ๋ ๊ทธ ์ธ์ฝ๋ฉ ์ถ์ฒ, ๊ทธ ์ธ UTF-8 / New functionmerger_recommend_save_encoding()โ recommends the non-Unicode encoding if all files share it with confidence โฅ0.7, otherwise UTF-8 - UI: ๋๋กญ๋ค์ด ์๋ "๐ก ์ถ์ฒ: XXX" ๋ผ๋ฒจ + [์ ์ฉ] ๋ฒํผ / UI: "๐ก Recommended: XXX" label + [Apply] button beneath the dropdown
- ํ์ผ ์ถ๊ฐ/์ ํ์ญ์ /์ ์ฒด์ญ์ /์ธ์ด์ ํ 4์ง์ ์์ ์๋ ๊ฐฑ์ / Auto-refresh at 4 trigger points: add files / delete selected / clear all / language switch
- ์ ํจ์
-
Phase 1 โ ๋ถ๋ถ ์์ ํ์ผ ์์ ์ฒ๋ฆฌ / Phase 1 โ safe handling of partially corrupted files
- ๊ณตํต ํฌํผ
safe_read_text_with_report()โ strict ํด๋ฐฑ 8๊ฐ ๋ชจ๋ ์คํจ ์errors='replace'๋ก ์ต์ข ์ฌ์๋ / Shared helpersafe_read_text_with_report()โ final retry witherrors='replace'when all 8 strict fallbacks fail - ๊นจ์ง ๋ฐ์ดํธ๋ U+FFFD (
๏ฟฝ)๋ก ๋์ฒด (Python ๊ธฐ๋ณธ๊ฐ, ์ ๋์ฝ๋ ํ์ค) / Corrupt bytes replaced with U+FFFD (๏ฟฝ), Python's default and the Unicode standard - Text Fixer replace ๋ชจ๋ ์ ๊ฒฝ๊ณ ๋ค์ด์ผ๋ก๊ทธ
tf_warn_partial_enc(5๊ฐ ์ธ์ด) / Text Fixer replace mode shows warning dialogtf_warn_partial_encin 5 languages - Bulk Fixer ๋ฏธ๋ฆฌ๋ณด๊ธฐยท์ผ๊ด ๊ต์ ยทText Fixer ํ์ผ ๋ก๋ 3๊ณณ ์ ์ฉ / Applied in 3 locations: Bulk Fixer preview, Bulk Fixer worker, Text Fixer file load
- ๊ณตํต ํฌํผ
-
Phase 2-b โ Text Fixer / Bulk Fixer ๋์๋ง ํ์ฅ / Phase 2-b โ Text Fixer / Bulk Fixer help section expansion
- Text Fixer ๋์๋ง: "Partially corrupted files note" + ๋จ์ผ ํ์ผ ๊ฒํ ๋๊ตฌ ๋ช ์ + Tier 3 ์๋ ์คํต ์๋ด / Text Fixer help: "Partially corrupted files note" + single-file review tool explanation + Tier 3 auto-skip notice
- Bulk Fixer ๋์๋ง: "Automatic corruption tiering note" (Tier 1/2/3 ์์ธ) + ๋ฆฌํฌํธ ํ์ผ๋ช ํ์ + Text Fixer ๊ฐ๋ณ ๊ฒํ ์ ๋ / Bulk Fixer help: "Automatic corruption tiering note" (Tier 1/2/3 details) + report filename format + Text Fixer individual review guidance
- 5๊ฐ ์ธ์ด ๋ชจ๋ ์๊ฐ ๊ฒ์ ํต๊ณผ / Visual review passed in all 5 languages
๐ ๋ฒ๊ทธ ์์ / Bug Fixes
-
์ค์ ๋ค์ด์ผ๋ก๊ทธ ๋ฒ์ฒด ์ค๊ตญ์ด ์์ฌ / Settings dialog Traditional Chinese residue (v1.0.5๋ถํฐ ์กด์ฌ / pre-existing since v1.0.5)
- ํ์: ็น้ซ โ ํ๊ตญ์ด ์ ํ ์ ๋จ์ถํค ๋ฆฌ์
๋ฒํผ์
้ ่จญ,้่จญๆๆๅฟซๆท้ต/ ์ถ๋ ฅ ํด๋ ๋ผ๋ฒจ์่ผธๅบ่ณๆๅคพ/ ๋ฒํผ์้ธๆ่ณๆๅคพ/้่จญ๋ฑ ๋ฒ์ฒด ์์ฌ / Symptom: after switching ็น้ซ โ Korean, residue like้ ่จญ,้่จญๆๆๅฟซๆท้ต,่ผธๅบ่ณๆๅคพ,้ธๆ่ณๆๅคพ,้่จญremained - ์์ธ:
SettingsDialog._retranslate_dialog๊ฐ ์ผ๋ถ ์์ ฏ ํ ์คํธ ๊ฐฑ์ ์ ๋๋ฝ (๋จ์ถํค ๋ฆฌ์ ๋ฒํผ 6๊ฐ + ์ ์ฒด ๋ฆฌ์ + ์ผ๋ฐ ์ค์ ์ถ๋ ฅ ํด๋ ๋ผ๋ฒจยท๋ฒํผ + ๋ผ์ด์ ์ค ํ์ดํ) / Root cause:SettingsDialog._retranslate_dialogmissed text updates for 6 individual reset buttons + reset-all button + output folder label/buttons + license title - ์์ โ ์ง์์ v2 ๊ธฐ๋ฐ:
_apply_theme_now์_retranslate_dialog()ํธ์ถ ์ถ๊ฐ(ยง2.1), ์์ ฏ self ์ ์ฅ 9๊ฐ ๋ณด์(ยง2.2),_retranslate_dialog์ D-1/D-2/D-3 ๋ธ๋ก ํ์ฅ(ยง2.4) / Fix โ per Work Instruction v2: added_retranslate_dialog()call to_apply_theme_now(ยง2.1), preserved 9 widget self-references (ยง2.2), expanded_retranslate_dialogwith D-1/D-2/D-3 blocks (ยง2.4) - AppSuite ๋ด ๋ฐ๋ ์ฝ๋ 3๊ฐ ๋ฉ์๋ 74์ค ์์ ์ ๊ฑฐ(ยง2.5) โ
_page_language/_on_lang_selected/_retranslate_dialog(SettingsDialog๊ฐ ๋ณ๋ QDialog๋ก ๋ถ๋ฆฌ๋๊ธฐ ์ ์์ฌ๋ ๋ณต์ ๋ณธ) / Removed 3 dead methods (74 lines) in AppSuite (ยง2.5) โ remnants from beforeSettingsDialogwas split into a separateQDialog
- ํ์: ็น้ซ โ ํ๊ตญ์ด ์ ํ ์ ๋จ์ถํค ๋ฆฌ์
๋ฒํผ์
-
toolTip์ค์ผ ๋ฐ์ดํฐ ์์ค ๋ฒ๊ทธ /toolTipcontamination data-loss bug (v1.0.4๋ถํฐ ์กด์ฌ / pre-existing since v1.0.4)- ํ์: ์ ๋ขฐ๋ <0.90 ํ์ผ์ ํดํ์ ์๋ด๋ฌธ์ด ๋ง๋ถ์ด
item.toolTip(0)๊ธฐ๋ฐ ๊ฒฝ๋ก ์กฐํ ์คํจ โ ์ญ์ ํ ํ์ผ์ด ๋ณํฉ ๊ฒฐ๊ณผ์ ํฌํจ๋๋ ๋ฐ์ดํฐ ์์ค / Symptom: low-confidence (<0.90) files had info appended to their toolTip, breakingitem.toolTip(0)path lookups โ deleted files included in merge output, causing data loss - ์์ :
_PATH_ROLE = Qt.ItemDataRole.UserRole + 4์ ์ค, ์์ ๊ฒฝ๋ก ์ ์ฅ / Fix: new_PATH_ROLE = Qt.ItemDataRole.UserRole + 4storing pure paths - 3๊ฐ ํด๋์ค ์ ์ฉ:
MergeEncodingDelegate,TextConverterFileList,BulkFixerFileList/ Applied to 3 classes:MergeEncodingDelegate,TextConverterFileList,BulkFixerFileList - ํ์ ํธํ ํด๋ฐฑ ์ ์ง:
item.data(0, _PATH_ROLE) or item.toolTip(0)/ Backward-compat fallback retained:item.data(0, _PATH_ROLE) or item.toolTip(0)
- ํ์: ์ ๋ขฐ๋ <0.90 ํ์ผ์ ํดํ์ ์๋ด๋ฌธ์ด ๋ง๋ถ์ด
-
ํค๋ ์ ๋ ฌ ๋ฒ๊ทธ / Header sort bug (v1.0.4๋ถํฐ ์กด์ฌ / pre-existing since v1.0.4)
- ํ์:
setSortingEnabled(False)+DragDrop๋ชจ๋ ์กฐํฉ์์ ํค๋ ํด๋ฆญ์ผ๋ก ์ ๋ ฌ์ด ๋์ํ์ง ์์ / Symptom: withsetSortingEnabled(False)+DragDropmode, header-click sorting stopped working - ์์ธ: Qt์ ๊ธฐ๋ณธ ๋์์ผ๋ก
setSortingEnabled(False)์ ํค๋ ์น์ ํด๋ฆญ์ด ๋นํ์ฑํ๋จ / Cause: Qt disables header section clicks whensetSortingEnabled(False) - ์์ :
hdr.setSectionsClickable(True)๋ช ์ ์ถ๊ฐ (MergeFileTree v1.0.3/1.0.4 ํจํด ๋ณต์ ) / Fix: explicithdr.setSectionsClickable(True)(pattern cloned from MergeFileTree v1.0.3/1.0.4)
- ํ์:
-
alchemy_detect_encoding ํด๋ฐฑ ์ ๋ขฐ๋ 0.0 โ 0.7 / alchemy_detect_encoding fallback confidence 0.0 โ 0.7
- ํด๋ฐฑ ๋ฃจํ ํต๊ณผ ์(cp949/shift_jis/gbk/big5) ์ ๋ขฐ๋๋ฅผ 0.7๋ก ์ํฅ / Confidence raised to 0.7 on fallback-loop success (cp949/shift_jis/gbk/big5)
- utf-8 strict ํด๋ฐฑ๋ 0.0 โ 0.7 (์ผ๊ด์ฑ) / utf-8 strict fallback also raised to 0.7 (consistency)
- ์งง์ ํ๊ธ CP949 ํ์ผ์ด "70% CP949" ๋ฐฐ์ง + "๐ก ์ถ์ฒ: CP949"๋ก ์ ์ ํ์ / Short Korean CP949 files now correctly show "70% CP949" badge + "๐ก Recommended: CP949"
โก ์ฑ๋ฅ ๊ฐ์ / Performance Improvements
- O(NรK) โ O(N) ์์น ์ถ์ ์ฌ์ค๊ณ / O(NรK) โ O(N) position tracking redesign
- ๊ธฐ์กด: ํ์ผ๋น ์์ ๋ฐ์ดํธ K๊ฐ ์ฐพ๊ธฐ ์ํด N๋ฐ์ดํธ ์ ์ ์ํ โ Kํ ๋ฐ๋ณต = O(NรK) / Before: for each of K corrupt bytes, scanned all N bytes โ O(NรK)
- ์ ๊ท:
codecs.register_error('_fns_track', ...)๊ธฐ๋ฐ ๋จ์ผ ํจ์ค๋ก ๋์ฝ๋ฉ ์ค ์์น ์์ง โ O(N) / After: single-pass position collecti...
File Nexus Suite v1.0.5
v1.0.5 โ Text Merger ์ ์ฅ ์ธ์ฝ๋ฉ ๋๋กญ๋ค์ด UI ์ฌ์ฉ์ฑ ๊ฐ์ / Text Merger save-encoding dropdown UI usability improvements
๋นํ๋ก๊ทธ๋๋จธ๊ฐ 8์ข
์ ์ฅ ์ธ์ฝ๋ฉ ์ค ๋ฌด์์ ๊ณจ๋ผ์ผ ํ ์ง ์ง๊ด์ ์ผ๋ก ํ๋จํ ์ ์๋๋ก Text Merger ๋๋กญ๋ค์ด ๋ผ๋ฒจ์ ์ฐ๊ด ์ธ์ด๋ฅผ ๋ณ๊ธฐํ๊ณ ์ฝค๋ณด๋ฐ์ค ์๋์ ํ ์ค ๋์๋ง์ ์ถ๊ฐํ์ต๋๋ค. ๋ด๋ถ ํค์ ํ์ ๋ผ๋ฒจ์ ๋ถ๋ฆฌํ๋ addItem(display, userData) ๋ฆฌํฉํ ๋ง์ ํตํด v1.0.4 ์ดํ ์ค์ ํ์ผ๊ณผ๋ ์์ ํธํ๋ฉ๋๋ค. ๋น๋ ํ QA ์ค ๋ฐ๊ฒฌ๋ "์ธ์ด ์ ํ ์ ์ํ ๋ฉ์์ง๊ฐ ํ๊ตญ์ด๋ก ๋จ๋ ๊ธฐ์กด ๋ฒ๊ทธ"๋ ํจ๊ป ํด์ํ๊ณ , v1.0.2๋ถํฐ ์๋ณ๋๋ ๋ฒ์ญ ์ฌ์ ์ค๋ณต ํค 74๊ฐ๋ฅผ ์ผ๊ด ์ ๋ฆฌํ์ฌ ๊ธฐ์ ๋ถ์ฑ๋ฅผ ํด์ํ์ต๋๋ค.
Redesigned the Text Merger save-encoding dropdown: each item now carries a language hint (e.g.
Shift-JIS (์ผ๋ณธ์ด)), and a one-line helper ("If unsure, select UTF-8") sits beneath the combobox. Internally, display labels were separated from stable keys using theaddItem(display, userData)pattern, preserving full config compatibility with v1.0.4 and earlier. A pre-existing bug where status messages stayed in Korean after language switch โ discovered during post-build QA โ was also fixed, and 74 duplicate translation keys identified since v1.0.2 were cleaned up as long-standing tech debt.
๐ ๋ฒ๊ทธ ์์ (๋น๋ ํ QA์์ ๋ฐ๊ฒฌ) / Bug Fixes (from post-build QA)
- ์ธ์ด ์ ํ ์ Text Merger ํ๋จ ์ํ ๋ฉ์์ง๊ฐ ํ๊ตญ์ด๋ก ๋จ๋ ๋ฌธ์ / Text Merger status messages stayed in Korean after language switch
- ํ์: ํ์ผ ์ถ๊ฐ ํ ์ธ์ด๋ฅผ ์์ด/์ผ๋ณธ์ด/์ค๊ตญ์ด๋ก ์ ํํด๋
26๊ฐ ํ์ผ ์ถ๊ฐ๋จ (์ธ์ฝ๋ฉ ์๋ ๊ฐ์ง ์๋ฃ)๊ฐ ํ๊ตญ์ด๋ก ์์กด (v1.0.4 ์ด์ ๋ถํฐ ์กด์ฌํ ๊ธฐ์กด ๋ฒ๊ทธ) - Symptom: After adding files, switching language to English/Japanese/Chinese left
26๊ฐ ํ์ผ ์ถ๊ฐ๋จ...in Korean (pre-existing bug since before v1.0.4) - ์์ธ:
retranslate()๊ฐmerge_status_ready์ํ์ผ ๋๋ง_lbl_status๋ฅผ ๊ฐฑ์ โ ํ์ผ ์ถ๊ฐ/์ญ์ /์ ์ฅ ํ ๋ฉ์์ง์์ ๋ฌด๋ฐ์ - Root cause:
retranslate()only refreshed_lbl_statuswhen it held themerge_status_readytext โ messages after add/del/save never updated - ๋ฒ์: 9์ข
์ํ ๋ฉ์์ง ์ ๋ถ (
ready,add,del,clr,reading,save_done,save_err,path_set,path_reset_done) ๋์ผ ๊ตฌ์กฐ ๋ฒ๊ทธ - Scope: All 9 status messages (
ready,add,del,clr,reading,save_done,save_err,path_set,path_reset_done) shared the same defect - ์์ :
_retranslate_status()ํฌํผ +_match_status_template()์ ๊ท์ ๋งค์นญ ์ ํธ ์ ์ค - Fix: Added
_retranslate_status()helper and_match_status_template()regex-based matching utility - ์ ์ ๋ฉ์์ง 5์ข
(
ready/clr/reading/save_err/path_reset_done): ๋จ์ ๋งคํ ํ ํ์ฌ ์ธ์ด๋ก ์ฌ๋ ๋ - Static messages (5): simple lookup and re-render in current language
- ๋ณต์ ๊ฐ๋ฅ ๋์ ๋ฉ์์ง 2์ข
: ์๋ณธ ์ ๋ณด๋ก ์ฌ๊ตฌ์ฑ โ
merge_status_addโlen(self.file_list)/merge_path_setโself.save_dir - Recoverable dynamic messages (2): reconstructed from live state โ
merge_status_addโ file count /merge_path_setโ current save dir - ๋ณต์ ๋ถ๊ฐ ๋ฉ์์ง 3์ข
(
del/save_done/bulk_scanning):ready๋ก ๋ฆฌ์ +_glog๋๋ฒ๊ทธ ๋ก๊ทธ๋ก ์ถ์ ์ฑ ํ๋ณด - Non-recoverable messages (3): reset to
readywith_glogdebug trace for traceability - ์ ์ฉ์ฐ๋์ ์ค๊ธฐ QA ์ค 3๊ฐ ์ธ์ด(์ยท์ผยท์ค๊ฐ) ์คํฌ๋ฆฐ์ท์ผ๋ก ํฌ์ฐฉ๋จ โญ
- Discovered by developer's multilingual QA screenshots (EN / JA / zh_CN) โญ
- ํ์: ํ์ผ ์ถ๊ฐ ํ ์ธ์ด๋ฅผ ์์ด/์ผ๋ณธ์ด/์ค๊ตญ์ด๋ก ์ ํํด๋
โจ ๊ธฐ๋ฅ ์ถ๊ฐ / New Features
-
๋๋กญ๋ค์ด 8๊ฐ ์์ดํ ์ ์ฐ๊ด ์ธ์ด ๋ณ๊ธฐ / Language hints added to all 8 dropdown items
- ํ๊ตญ์ด UI ์:
Shift-JIS (์ผ๋ณธ์ด),EUC-KR (ํ๊ตญ์ด),CP949 (ํ๊ตญ์ด Windows),GBK (์ค๊ตญ์ด ๊ฐ์ฒด),Big5 (์ค๊ตญ์ด ๋ฒ์ฒด) - Korean UI example:
Shift-JIS (์ผ๋ณธ์ด),EUC-KR (ํ๊ตญ์ด),CP949 (ํ๊ตญ์ด Windows),GBK (์ค๊ตญ์ด ๊ฐ์ฒด),Big5 (์ค๊ตญ์ด ๋ฒ์ฒด) - 5๊ฐ ์ธ์ด ๋ชจ๋ ์ ์ฉ โ ์ค๊ตญ์ด ๊ฐ์ฒด/๋ฒ์ฒด UI์์๋ ์ผ๋ณธ์ด ํ๊ธฐ๋ฅผ
ๆฅๆ์ผ๋ก ํต์ผ (v1.0.4 tip ๋ฌธ๊ตฌ์ ์ผ๊ด์ฑ) - Applied to all 5 languages โ Chinese UIs (simplified/traditional) use
ๆฅๆfor "Japanese" to match v1.0.4 tip wording - UTF-8 / UTF-8-BOM / UTF-16์ ์์์ด ์์ด ์ ์ง โ ํน์ ์ธ์ด์ ์ข ์๋์ง ์์
- UTF-8 / UTF-8-BOM / UTF-16 remain unlabeled โ not tied to any specific language
- ์ฃผ๊ด ํํ(
(์ถ์ฒ),(์ ์ฉ)๋ฑ) ๋ฐฐ์ , ์ฌ์ค ๊ธฐ๋ฐ ์์์ด๋ง ์ฌ์ฉ (์ ์ง์ฑ ์์น) - No subjective qualifiers (e.g. "(recommended)", "(only)") โ neutral, fact-based hints only (honesty principle)
- ํ๊ตญ์ด UI ์:
-
์ฝค๋ณด๋ฐ์ค ์๋ ํ ์ค ๋์๋ง ๋ผ๋ฒจ ์ถ๊ฐ / One-line helper added beneath the combobox
- ์ ๊ท ๋ฒ์ญ ํค
merge_enc_hint: "ํ์คํ์ง ์์ผ๋ฉด UTF-8์ ์ ํํ์ธ์" ์ธ 5๊ฐ ์ธ์ด - New translation key
merge_enc_hint: "If unsure, select UTF-8" (across 5 languages) - MUTED ์์ +
font-size:11px๋ก ๊ธฐ์กด ๋์๋ง ํค๊ณผ ํต์ผ - Styled with MUTED color +
font-size:11pxto match existing helper-text tone - ๋นํ๋ก๊ทธ๋๋จธ๊ฐ 5์ด ์์ UTF-8์ด ์์ ํ ๊ธฐ๋ณธ๊ฐ์์ ํ๋จํ ์ ์๋๋ก ์ค๊ณ
- Designed so non-programmers can recognize UTF-8 as the safe default within 5 seconds
- ์ ๊ท ๋ฒ์ญ ํค
๐ง ๋ฆฌํฉํ ๋ง / Refactoring
-
ํ์ ๋ผ๋ฒจ๊ณผ ๋ด๋ถ ํค ๋ถ๋ฆฌ / Separated display labels from internal keys
- ์ ๊ท ํด๋์ค ์์
TextMergerPanel._ENC_ITEMSโ[(internal_key, i18n_key), ...]8-tuple ๋ฆฌ์คํธ - Added class constant
TextMergerPanel._ENC_ITEMSโ a list of(internal_key, i18n_key)8-tuples addItems([...])โaddItem(display, userData)ํจํด์ผ๋ก ์ ํ (userData์ stable ํค ๋ณด์กด)- Switched from
addItems([...])toaddItem(display, userData)pattern (keys stored inuserData) currentText()โcurrentData(),findText()โfindData()๋ง์ด๊ทธ๋ ์ด์ - Migrated
currentText()โcurrentData()andfindText()โfindData() apply_config()์ ๊ตฌ๋ฒ์ ํด๋ฐฑ ๋ด์ฅ:findData()์คํจ ์findText()์ฌ์๋ โ v1.0.4 ์ดํ ์ค์ ํ์ผ ์๋ ํธํ- Legacy fallback in
apply_config(): iffindData()misses, retry withfindText()โ seamless v1.0.4-and-older config compatibility retranslate()์ ์ฝค๋ณด๋ฐ์ค 8๊ฐ ์์ดํ ๋ผ๋ฒจ ๊ฐฑ์ ๋ฃจํ + ๋์๋ง ๋ผ๋ฒจ ๊ฐฑ์ ์ถ๊ฐretranslate()now iterates all 8 items updating display labels + refreshes the helper label
- ์ ๊ท ํด๋์ค ์์
-
๋ฒ์ญ ์ฌ์ ์ค๋ณต ํค 74๊ฐ ์ผ๊ด ์ ๋ฆฌ / Cleaned up 74 duplicate translation keys
- v1.0.2 ์ธ์์ธ๊ณ์์ ์๋ณ๋๋
zh_cn188๊ฐ ํค ์ค๋ณต ์ด์์ ์ค์ธก ํํฉ ์ฌ์กฐ์ฌ โ 74๊ฐ ์ค๋ณต ๋ผ์ธ ์์กด ํ์ธ - Re-audited the "188 duplicate zh_cn keys" issue identified since v1.0.2 โ 74 duplicate lines actually remaining
- ๋ถํฌ:
zh_cn69๊ฐ +ko/en/zh_tw๊ฐ 1๊ฐ +ja2๊ฐ = 74๊ฐ - Distribution:
zh_cn69 +ko/en/zh_tw1 each +ja2 = 74 - AST ํ์ฑ์ผ๋ก ๊ฐ ์ค๋ณต ๊ทธ๋ฃน์ ๋ ๊ฐ์ด ์์ ํ ์ผ์นํจ์ ๊ฒ์ฆํ ๋ค ์์ ์ญ์ โ ๋์ ์ํฅ 0
- AST-verified that each duplicate pair held identical values before deletion โ zero runtime impact
- ์ฃผ์ ํจํด:
merge_open_explorer๊ฐ 5๊ฐ ์ธ์ด ๋ชจ๋์์ ์ค๋ณต (dict ์ฌ์ฝ์ ํ์ ) /bulk_*ยทtf_*์ ๋์ฌ ํค๊ฐzh_cn์ ๋๋ ์ค๋ณต (Bulk FixerยทText Fixer ํ์ฅ ์์ ์ ์๋์น ์์ ์ค๋ณต) - Main patterns:
merge_open_explorerduplicated in all 5 languages (dict-reinsertion artifact) /bulk_*andtf_*prefix keys heavily duplicated inzh_cn(unintended duplication during Bulk Fixer / Text Fixer expansion) - ๊ฒฐ๊ณผ: 5๊ฐ ์ธ์ด ๊ฐ dict 390~391 ํค๋ก ์ฌ๋ฆผํ (
zh_cn463์ค โ 394์ค) - Result: each language dict slimmed to 390~391 keys (
zh_cn463 lines โ 394 lines)
- v1.0.2 ์ธ์์ธ๊ณ์์ ์๋ณ๋๋
๐งช ํ ์คํธ ์๋ํ / Test Automation
- ์ ๊ท ํ๊ท ํ
์คํธ 30๊ฐ ์ถ๊ฐ / Added 30 new regression tests
TestV105Regression: ์์ค ๊ฒ์ฆ 12๊ฐ (_ENC_ITEMS์์,addItemํจํด, ๋์๋ง ๋ผ๋ฒจ,currentData/findData๋ง์ด๊ทธ๋ ์ด์ , 45๊ฐ ๋ฒ์ญ ํญ๋ชฉ,ๆฅๆํ๊ธฐ ์ผ๊ด์ฑ ๋ฑ)TestV105Regression: 12 source-level checks (_ENC_ITEMSconstant,addItempattern, helper label,currentData/findDatamigration, 45 translation entries,ๆฅๆconsistency, etc.)TestV105RegressionModule: ๋ฐํ์ ๊ฒ์ฆ 6๊ฐ (APP_VERSION, 5๊ฐ ์ธ์ด ์ฌ์ ์๊ฒฐ์ฑ, ๋ผ๋ฒจ-ํค ๋งคํ,_ENC_ITEMS์์, ๋์๋ง UTF-8 ์๋ด ๋ฑ)TestV105RegressionModule: 6 runtime checks (APP_VERSION, 5-language dict completeness, label-key mapping,_ENC_ITEMSorder, UTF-8 guidance in helper, etc.)TestV105TranslationNoDuplicates: ์ค๋ณต ์ฌ๋ฐ ๋ฐฉ์ง 2๊ฐ (AST ๊ธฐ๋ฐ ์ค๋ณต 0 ๊ฒ์ฆ + ์ธ์ด๋ณ ํค ๊ฐ์ ํธ์ฐจ โค5)TestV105TranslationNoDuplicates: 2 no-duplicate-regression tests (AST-based zero duplicates + per-language key-count variance โค 5)TestV105StatusRetranslate: ์ํ ๋ฉ์์ง ์ฌ๋ฒ์ญ 10๊ฐ (์ ์ /๋ณต์๊ฐ๋ฅ/๋ณต์๋ถ๊ฐ/๋ฐฉ์ด์ ์ฒ๋ฆฌ/๋จ์ ํ ์คํธ)TestV105StatusRetranslate: 10 status-retranslation tests (static / recoverable / non-recoverable / defensive / unit)
- v1.0.4 ํ
์คํธ 2๊ฐ ์๊ทธ๋์ฒ ๋ณ๊ฒฝ์ ๋ง์ถฐ ์
๋ฐ์ดํธ (์๋ ์ ์ง) / Updated 2 v1.0.4 tests for the new signature (intent preserved)
test_text_merger_combo_has_cjk_encodings:addItems์ ๊ท์ โ_ENC_ITEMS์์ ๋ธ๋ก ๊ฒ์test_text_merger_combo_has_cjk_encodings:addItemsregex โ_ENC_ITEMSconstant block lookuptest_app_version_is_104โtest_app_version_is_104_or_later: ์ ํ ์ผ์น โ ํํ ๋น๊ต(โฅ (1,0,4))๋ก ์ํtest_app_version_is_104โtest_app_version_is_104_or_later: strict equality โ tuple comparison (โฅ (1,0,4))
๐ ๊ฒ์ฆ ๋ฒ์ / Verification Scope
- ๋จ์ ํ
์คํธ / Unit tests: 502 passing (v1.0.4: 472 + v1.0.5: 30) โ ์คํจ 0 / ์ค๋ฅ 0 / ์คํต 0 โญ
- 502 passing / 0 failed / 0 errors / 0 skipped โญ
- ์ค๊ธฐ ๊ฒ์ฆ / Manual testing:
- ๋๋กญ๋ค์ด ๋ผ๋ฒจ + ๋์๋ง ๋ฌธ๊ตฌ๋ฅผ 5๊ฐ ์ธ์ด ๋ชจ๋์์ ๊ฐ๊ฐ ์คํฌ๋ฆฐ์ท ๊ฒ์ฆ / Dropdown labels + helper text verified via screenshots across all 5 language modes
- ๋น๋ ํ ์ธ์ด ์ ํ ์ ์ํ ๋ฉ์์ง ์ฌ๋ฒ์ญ ํ๊ท ๊ฒ์ฆ (ํ์ผ ์ถ๊ฐ โ ์์ด ์ ํ โ
Ready๋ฆฌ์ + Debug Log์merge_status_del โ merge_status_ready๋ก๊ทธ ํ์ธ) / Post-build verification of status message re-translation (add files โ switch to EN โReadyreset + debug log line confirmed) - v1.0.4 ์ค์ ํ์ผ(
combo_enc: "Shift-JIS")๋ก ๊ธฐ๋ํ์ฌfindText()ํด๋ฐฑ ์ ์ ๋์ ํ์ธ / Launched with a v1.0.4 config file (combo_enc: "Shift-JIS") to confirm thefindText()fallback works correctly
- ๊ตฌ์กฐ์ ์์ ์ฑ / Structural safety:
addItem(display, userData)์ ํ์ผ๋ก ๋ด๋ถ ํค์ ํ์ ๋ผ๋ฒจ ์์ ๋ถ๋ฆฌ / Clean separation of internal keys from display labels viaaddItem(display, userData)currentData()๊ธฐ๋ฐ ์ ์ฅ โ ๊ธฐ์กด ์ค์ ์ ์ฅ ์คํค๋ง ํค(combo_enc) ์ด๋ฆ ์ ์ง /currentData()-based save preserves the existingcombo_encconfig schema key- ๋ฒ์ญ ์ฌ์ ์ค๋ณต ์ ๊ฑฐ๋ AST ๊ฐ ๋์ผ์ฑ ๊ฒ์ฆ ํ์๋ง ์คํ โ ๋์ ๋ณํ 0 / Duplicate key removal gated on AST-level value-equality check โ zero behavioral change
TextMergerPanel์ธ ๋ค๋ฅธ ํญ(Text Converter / Tag Editor / Batch Renamer / Text Fixer / Bulk Fixer) ์ํฅ 0 / No impact on other tabs (Text Converter / Tag Editor / Batch Renamer / Text Fixer / Bulk Fixer)
๐ ๋ฆด๋ฆฌ์ฆ ์๋ช / Release Signing
- v1.0.5๋ถํฐ SSH ์๋ช
๋์
/ SSH signing introduced from v1.0.5
- ์ปค๋ฐ + ํ๊ทธ ๋ชจ๋ Ed25519 SSH ํค๋ก ์๋ช โ GitHub Verified ๋ฑ์ง ํ๋ / Both commit and tag signed with Ed25519 SSH key โ GitHub Verified badge
- v1.0.1 ์ดํ Verified ๋ฑ์ง ๋ณต๊ท (v1.0.2~v1.0.4๋ ๋น์๋ช ) / Verified badge returns since v1.0.1 (v1.0.2โv1.0.4 were unsigned)
- Fingerprint:
SHA256:4H2f7lrFfI4u0YP0dpp6N9BQH2f74iKjjMRHu7lyjKI
๐ฌ ๊ฒํ / Review
- Claude Opus 4.7 ๊ธฐ๋ฐ ์ ์ ๋ถ์ ...