shoko 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.bundle/config +0 -1
- data/.rubocop.yml +35 -4
- data/Gemfile +2 -0
- data/README.md +100 -1
- data/Rakefile +80 -1
- data/Shoko.gemspec +34 -0
- data/bin/shoko +11 -5
- data/bin/start +11 -5
- data/docs/architecture/hexagonal-adherence-checklist.md +173 -0
- data/lib/shoko/adapters/base_adapter.rb +30 -0
- data/lib/{zip.rb → shoko/adapters/book_sources/archive/zip_reader.rb} +46 -32
- data/lib/shoko/adapters/book_sources/book_document.rb +177 -0
- data/lib/shoko/adapters/book_sources/book_file_probe.rb +24 -0
- data/lib/shoko/adapters/book_sources/book_finder/directory_scanner.rb +152 -0
- data/lib/shoko/adapters/book_sources/book_finder/scanner_context.rb +30 -0
- data/lib/shoko/adapters/book_sources/{epub_finder.rb → book_finder.rb} +62 -46
- data/lib/shoko/adapters/book_sources/cache_import_adapter.rb +30 -0
- data/lib/shoko/adapters/book_sources/document_loader_adapter.rb +72 -0
- data/lib/shoko/adapters/book_sources/document_service.rb +133 -169
- data/lib/shoko/adapters/book_sources/download_service.rb +22 -21
- data/lib/shoko/adapters/book_sources/epub/epub_importer.rb +266 -0
- data/lib/shoko/adapters/book_sources/epub/epub_resource_loader.rb +138 -127
- data/lib/shoko/adapters/book_sources/fb2/fb2_importer.rb +336 -0
- data/lib/shoko/adapters/book_sources/folder_scanner.rb +92 -0
- data/lib/shoko/adapters/book_sources/gutendex_client.rb +137 -110
- data/lib/shoko/adapters/book_sources/kindle/kindle_importer.rb +422 -0
- data/lib/shoko/adapters/book_sources/library_scanner.rb +144 -71
- data/lib/shoko/adapters/book_sources/metadata_reader_adapter.rb +72 -0
- data/lib/shoko/adapters/book_sources/pdf/pdf_importer.rb +364 -0
- data/lib/shoko/adapters/book_sources/rtf/rtf_importer.rb +303 -0
- data/lib/shoko/adapters/input/annotations/mouse_handler.rb +130 -126
- data/lib/shoko/adapters/input/cli.rb +439 -0
- data/lib/shoko/adapters/input/command_factory.rb +276 -201
- data/lib/shoko/adapters/input/commands.rb +77 -47
- data/lib/shoko/adapters/input/controllers/annotation_overlay_controller.rb +362 -0
- data/lib/shoko/adapters/input/controllers/dependencies/menu_controller_dependencies.rb +134 -0
- data/lib/shoko/adapters/input/controllers/dependencies/reader_controller_dependencies.rb +390 -0
- data/lib/shoko/adapters/input/controllers/dictionary/constants.rb +80 -0
- data/lib/shoko/adapters/input/controllers/dictionary/controller_support.rb +117 -0
- data/lib/shoko/adapters/input/controllers/dictionary/display_mode_support.rb +65 -0
- data/lib/shoko/adapters/input/controllers/dictionary/index.rb +7 -0
- data/lib/shoko/adapters/input/controllers/dictionary/language_pair_support.rb +190 -0
- data/lib/shoko/adapters/input/controllers/dictionary/setup_flow/download_support.rb +97 -0
- data/lib/shoko/adapters/input/controllers/dictionary/setup_flow/interaction_handlers.rb +106 -0
- data/lib/shoko/adapters/input/controllers/dictionary/setup_flow/lookup_flow.rb +106 -0
- data/lib/shoko/adapters/input/controllers/dictionary/setup_flow/popup_state_support.rb +99 -0
- data/lib/shoko/adapters/input/controllers/dictionary/setup_flow/submission_flow.rb +100 -0
- data/lib/shoko/adapters/input/controllers/dictionary/setup_flow_support.rb +26 -0
- data/lib/shoko/adapters/input/controllers/dictionary_controller.rb +304 -0
- data/lib/shoko/adapters/input/controllers/in_book_search_controller.rb +202 -0
- data/lib/shoko/adapters/input/controllers/menu/actions/dictionary_actions.rb +121 -0
- data/lib/shoko/adapters/input/controllers/menu/actions/download_actions.rb +74 -0
- data/lib/shoko/adapters/input/controllers/menu/actions/lifecycle_actions.rb +157 -0
- data/lib/shoko/adapters/input/controllers/menu/actions/navigation_actions.rb +141 -0
- data/lib/shoko/adapters/input/controllers/menu/actions/settings_actions.rb +128 -0
- data/lib/shoko/adapters/input/controllers/menu/controller.rb +430 -0
- data/lib/shoko/adapters/input/controllers/menu/input_controller.rb +210 -0
- data/lib/shoko/adapters/input/controllers/menu/intent_executor_bridge.rb +115 -0
- data/lib/shoko/adapters/input/controllers/menu/menu_workflow_bridges.rb +100 -0
- data/lib/shoko/adapters/input/controllers/menu/reader_launch_bridges.rb +78 -0
- data/lib/shoko/adapters/input/controllers/menu/state_controller.rb +123 -0
- data/lib/shoko/adapters/input/controllers/mouseable_reader.rb +243 -0
- data/lib/shoko/adapters/input/controllers/reader/event_loop.rb +100 -0
- data/lib/shoko/adapters/input/controllers/reader/input_router.rb +68 -0
- data/lib/shoko/adapters/input/controllers/reader/intent_executor_bridge.rb +107 -0
- data/lib/shoko/adapters/input/controllers/reader/lifecycle_runner.rb +117 -0
- data/lib/shoko/adapters/input/controllers/reader/render_metrics.rb +54 -0
- data/lib/shoko/adapters/input/controllers/reader/render_requester_bridge.rb +35 -0
- data/lib/shoko/adapters/input/controllers/reader/startup_loader.rb +61 -0
- data/lib/shoko/adapters/input/controllers/reader/startup_sequence.rb +64 -0
- data/lib/shoko/adapters/input/controllers/reader_controller.rb +519 -0
- data/lib/shoko/adapters/input/controllers/selection_mouse_handler.rb +212 -0
- data/lib/shoko/adapters/input/controllers/sidebar/anchor_resolver.rb +88 -0
- data/lib/shoko/adapters/input/controllers/sidebar/tab_state_orchestrator.rb +151 -0
- data/lib/shoko/adapters/input/controllers/sidebar/toc_facade.rb +71 -0
- data/lib/shoko/adapters/input/controllers/sidebar/toc_navigation.rb +77 -0
- data/lib/shoko/adapters/input/controllers/sidebar_controller.rb +309 -0
- data/lib/shoko/adapters/input/controllers/sidebar_mouse_handler.rb +201 -0
- data/lib/shoko/adapters/input/controllers/state_controller/annotation_actions.rb +119 -0
- data/lib/shoko/adapters/input/controllers/state_controller/bookmark_actions.rb +154 -0
- data/lib/shoko/adapters/input/controllers/state_controller/progress_actions.rb +149 -0
- data/lib/shoko/adapters/input/controllers/state_controller.rb +97 -0
- data/lib/shoko/adapters/input/controllers/support/message_notifier.rb +29 -0
- data/lib/shoko/adapters/input/controllers/ui_controller/delegation_facade.rb +325 -0
- data/lib/shoko/adapters/input/controllers/ui_controller/mode_switching.rb +62 -0
- data/lib/shoko/adapters/input/controllers/ui_controller/popup_actions.rb +84 -0
- data/lib/shoko/adapters/input/controllers/ui_controller.rb +109 -0
- data/lib/shoko/adapters/input/dispatcher.rb +50 -48
- data/lib/shoko/adapters/input/input_system_factory_adapter.rb +33 -0
- data/lib/shoko/adapters/input/key_classifier_adapter.rb +64 -0
- data/lib/shoko/adapters/input/reader_input_controller.rb +342 -0
- data/lib/shoko/adapters/input/validators/file_path_validator.rb +70 -63
- data/lib/shoko/adapters/input/validators/terminal_size_validator.rb +65 -60
- data/lib/shoko/adapters/monitoring/logger_adapter.rb +161 -0
- data/lib/shoko/adapters/monitoring/perf_tracer.rb +146 -142
- data/lib/shoko/adapters/monitoring/performance_monitor.rb +19 -24
- data/lib/shoko/adapters/output/clipboard/clipboard_service.rb +80 -90
- data/lib/shoko/adapters/output/formatting/formatting_service/line_assembler/image_builder.rb +118 -118
- data/lib/shoko/adapters/output/formatting/formatting_service/line_assembler/table_renderer.rb +365 -0
- data/lib/shoko/adapters/output/formatting/formatting_service/line_assembler/text_wrapper.rb +167 -103
- data/lib/shoko/adapters/output/formatting/formatting_service/line_assembler/tokenizer.rb +213 -61
- data/lib/shoko/adapters/output/formatting/formatting_service/line_assembler.rb +288 -109
- data/lib/shoko/adapters/output/formatting/formatting_service/plain_lines_builder.rb +48 -40
- data/lib/shoko/adapters/output/formatting/formatting_service.rb +243 -196
- data/lib/shoko/adapters/output/formatting/wrapped_lines_provider_adapter.rb +43 -0
- data/lib/shoko/adapters/output/formatting/wrapping_service.rb +203 -180
- data/lib/shoko/adapters/output/instrumentation_service.rb +58 -23
- data/lib/shoko/adapters/output/kitty/display_capabilities.rb +21 -0
- data/lib/shoko/adapters/output/kitty/image_transcoder.rb +53 -49
- data/lib/shoko/adapters/output/kitty/kitty_graphics.rb +96 -92
- data/lib/shoko/adapters/output/kitty/kitty_image_renderer.rb +215 -226
- data/lib/shoko/adapters/output/kitty/kitty_unicode_placeholders.rb +4 -129
- data/lib/shoko/adapters/output/kitty/resource_loader.rb +34 -0
- data/lib/shoko/adapters/output/layout/layout_metrics_adapter.rb +68 -0
- data/lib/shoko/adapters/output/notification_service.rb +19 -17
- data/lib/shoko/adapters/output/terminal/buffer.rb +364 -218
- data/lib/shoko/adapters/output/terminal/cli_progress_renderer.rb +104 -0
- data/lib/shoko/adapters/output/terminal/constants/terminal_defaults.rb +9 -5
- data/lib/shoko/adapters/output/terminal/input/decoder.rb +375 -373
- data/lib/shoko/adapters/output/terminal/input.rb +204 -123
- data/lib/shoko/adapters/output/terminal/null_runtime_config.rb +23 -0
- data/lib/shoko/adapters/output/terminal/output.rb +43 -96
- data/lib/shoko/adapters/output/terminal/terminal.rb +202 -144
- data/lib/shoko/adapters/output/terminal/terminal_sanitizer.rb +7 -232
- data/lib/shoko/adapters/output/terminal/terminal_service.rb +121 -105
- data/lib/shoko/adapters/output/terminal/terminal_session_adapter.rb +32 -0
- data/lib/shoko/adapters/output/terminal/text_metrics.rb +4 -263
- data/lib/shoko/adapters/output/terminal/text_metrics_port_adapter.rb +41 -0
- data/lib/shoko/adapters/output/terminal/text_sanitizer_adapter.rb +23 -0
- data/lib/shoko/adapters/output/terminal_capabilities_adapter.rb +23 -0
- data/lib/shoko/adapters/runtime/app_mode_runner_adapter.rb +27 -0
- data/lib/shoko/adapters/runtime/env_runtime_config_adapter.rb +169 -0
- data/lib/shoko/adapters/runtime/monotonic_clock_adapter.rb +18 -0
- data/lib/shoko/adapters/runtime/null_runtime_config.rb +21 -0
- data/lib/shoko/adapters/runtime/process_control_adapter.rb +18 -0
- data/lib/shoko/adapters/runtime/rexml_security_limits_adapter.rb +35 -0
- data/lib/shoko/adapters/runtime/session_state/actions/base_action.rb +28 -0
- data/lib/shoko/adapters/runtime/session_state/actions/quit_to_menu_action.rb +20 -0
- data/lib/shoko/adapters/runtime/session_state/actions/switch_reader_mode_action.rb +26 -0
- data/lib/shoko/adapters/runtime/session_state/actions/toggle_view_mode_action.rb +35 -0
- data/lib/shoko/adapters/runtime/session_state/actions/update_config_action.rb +30 -0
- data/lib/shoko/adapters/runtime/session_state/actions/update_field_helpers.rb +30 -0
- data/lib/shoko/adapters/runtime/session_state/actions/update_menu_action.rb +21 -0
- data/lib/shoko/adapters/runtime/session_state/actions/update_message_action.rb +26 -0
- data/lib/shoko/adapters/runtime/session_state/actions/update_pagination_state_action.rb +23 -0
- data/lib/shoko/adapters/runtime/session_state/actions/update_reader_meta_action.rb +23 -0
- data/lib/shoko/adapters/runtime/session_state/actions/update_rendered_lines_action.rb +34 -0
- data/lib/shoko/adapters/runtime/session_state/actions/update_sidebar_action.rb +42 -0
- data/lib/shoko/adapters/runtime/session_state/actions/update_state_action.rb +76 -0
- data/lib/shoko/adapters/runtime/session_state/actions/update_ui_loading_action.rb +23 -0
- data/lib/shoko/adapters/runtime/session_state/config_reader_adapter.rb +82 -0
- data/lib/shoko/adapters/runtime/session_state/event_bus.rb +85 -0
- data/lib/shoko/adapters/runtime/session_state/event_publisher_adapter.rb +24 -0
- data/lib/shoko/adapters/runtime/session_state/menu_launch_state_adapter.rb +32 -0
- data/lib/shoko/adapters/runtime/session_state/menu_state_reader_adapter.rb +246 -0
- data/lib/shoko/adapters/runtime/session_state/menu_state_writer_adapter.rb +157 -0
- data/lib/shoko/adapters/runtime/session_state/notification_writer_adapter.rb +39 -0
- data/lib/shoko/adapters/runtime/session_state/observer_registry_adapter.rb +32 -0
- data/lib/shoko/adapters/runtime/session_state/observer_state_store.rb +129 -0
- data/lib/shoko/adapters/runtime/session_state/reader_launch_state_adapter.rb +45 -0
- data/lib/shoko/adapters/runtime/session_state/reader_state_reader_adapter.rb +162 -0
- data/lib/shoko/adapters/runtime/session_state/render_state_writer_adapter.rb +58 -0
- data/lib/shoko/adapters/runtime/session_state/rendered_content_reader_adapter.rb +29 -0
- data/lib/shoko/adapters/runtime/session_state/selectors/config_selectors.rb +82 -0
- data/lib/shoko/adapters/runtime/session_state/selectors/menu_selectors.rb +90 -0
- data/lib/shoko/adapters/runtime/session_state/selectors/reader_selectors.rb +191 -0
- data/lib/shoko/adapters/runtime/session_state/sidebar_state_reader_adapter.rb +67 -0
- data/lib/shoko/adapters/runtime/session_state/state_store/change_event_builder.rb +35 -0
- data/lib/shoko/adapters/runtime/session_state/state_store/config_persistence.rb +91 -0
- data/lib/shoko/adapters/runtime/session_state/state_store/initial_state_builder.rb +113 -0
- data/lib/shoko/adapters/runtime/session_state/state_store/transition_validator.rb +83 -0
- data/lib/shoko/adapters/runtime/session_state/state_store.rb +328 -0
- data/lib/shoko/adapters/runtime/session_state/state_writer_adapter.rb +134 -0
- data/lib/shoko/adapters/runtime/session_state/ui_state_reader_adapter.rb +50 -0
- data/lib/shoko/adapters/runtime/system_wall_clock_adapter.rb +18 -0
- data/lib/shoko/adapters/runtime/uuid_generator_adapter.rb +19 -0
- data/lib/shoko/adapters/storage/atomic_file_writer.rb +52 -24
- data/lib/shoko/adapters/storage/background_worker.rb +49 -43
- data/lib/shoko/adapters/storage/background_worker_builder_adapter.rb +24 -0
- data/lib/shoko/adapters/storage/book_cache_pipeline/cache_integrity_checker.rb +36 -0
- data/lib/shoko/adapters/storage/book_cache_pipeline/cache_session.rb +150 -0
- data/lib/shoko/adapters/storage/book_cache_pipeline/cache_status.rb +34 -0
- data/lib/shoko/adapters/storage/book_cache_pipeline/fingerprint_filter.rb +52 -0
- data/lib/shoko/adapters/storage/book_cache_pipeline/load_error_handler.rb +25 -0
- data/lib/shoko/adapters/storage/book_cache_pipeline/manifest_row.rb +74 -0
- data/lib/shoko/adapters/storage/book_cache_pipeline/manifest_sha_finder.rb +169 -0
- data/lib/shoko/adapters/storage/book_cache_pipeline/payload_context.rb +21 -0
- data/lib/shoko/adapters/storage/book_cache_pipeline/pointer_file_ensurer.rb +49 -0
- data/lib/shoko/adapters/storage/book_cache_pipeline.rb +122 -596
- data/lib/shoko/adapters/storage/book_cache_pipeline_factory_adapter.rb +23 -0
- data/lib/shoko/adapters/storage/cache/epub/memory_cache.rb +73 -71
- data/lib/shoko/adapters/storage/cache/epub/persistence.rb +124 -122
- data/lib/shoko/adapters/storage/cache/epub/serializer/deserialize.rb +195 -191
- data/lib/shoko/adapters/storage/cache/epub/serializer/helpers.rb +54 -47
- data/lib/shoko/adapters/storage/cache/epub/serializer/serialize.rb +65 -62
- data/lib/shoko/adapters/storage/cache/epub/source_reference.rb +43 -41
- data/lib/shoko/adapters/storage/cache_availability_adapter.rb +105 -0
- data/lib/shoko/adapters/storage/cache_manager_adapter.rb +28 -0
- data/lib/shoko/adapters/storage/cache_paths.rb +15 -13
- data/lib/shoko/adapters/storage/cache_pointer_manager.rb +42 -40
- data/lib/shoko/adapters/storage/cache_pointer_resolver.rb +35 -0
- data/lib/shoko/adapters/storage/config_paths.rb +22 -20
- data/lib/shoko/adapters/storage/config_storage_adapter.rb +73 -0
- data/lib/shoko/adapters/storage/data_cleanup_adapter.rb +83 -0
- data/lib/shoko/adapters/storage/dictionary_availability_adapter.rb +23 -0
- data/lib/shoko/adapters/storage/dictionary_catalog_service.rb +148 -0
- data/lib/shoko/adapters/storage/dictionary_storage_adapter.rb +84 -0
- data/lib/shoko/adapters/storage/epub_cache.rb +137 -152
- data/lib/shoko/adapters/storage/file_probe_adapter.rb +26 -0
- data/lib/shoko/adapters/storage/file_writer_service.rb +18 -22
- data/lib/shoko/adapters/storage/json_cache_store/chapters.rb +104 -102
- data/lib/shoko/adapters/storage/json_cache_store/layouts.rb +52 -49
- data/lib/shoko/adapters/storage/json_cache_store/manifest.rb +125 -30
- data/lib/shoko/adapters/storage/json_cache_store/payload_helpers.rb +109 -106
- data/lib/shoko/adapters/storage/json_cache_store/resources.rb +62 -60
- data/lib/shoko/adapters/storage/json_cache_store.rb +138 -134
- data/lib/shoko/adapters/storage/lazy_file_string.rb +40 -51
- data/lib/shoko/adapters/storage/pagination_cache.rb +107 -97
- data/lib/shoko/adapters/storage/path_ops_adapter.rb +30 -0
- data/lib/shoko/adapters/storage/recent_files.rb +96 -58
- data/lib/shoko/adapters/storage/recent_files_repository.rb +27 -0
- data/lib/shoko/adapters/storage/repositories/annotation_repository.rb +144 -156
- data/lib/shoko/adapters/storage/repositories/base_repository.rb +68 -63
- data/lib/shoko/adapters/storage/repositories/bookmark_repository.rb +111 -106
- data/lib/shoko/adapters/storage/repositories/cached_library_repository.rb +100 -97
- data/lib/shoko/adapters/storage/repositories/progress_repository.rb +128 -142
- data/lib/shoko/adapters/storage/repositories/storage/annotation_file_store.rb +92 -118
- data/lib/shoko/adapters/storage/repositories/storage/base_file_store.rb +40 -0
- data/lib/shoko/adapters/storage/repositories/storage/bookmark_file_store.rb +77 -92
- data/lib/shoko/adapters/storage/repositories/storage/file_store_utils.rb +13 -9
- data/lib/shoko/adapters/storage/repositories/storage/progress_file_store.rb +34 -50
- data/lib/shoko/adapters/storage/sqlite_dictionary_adapter.rb +301 -0
- data/lib/shoko/adapters/support/lifecycle_helpers.rb +73 -0
- data/lib/shoko/adapters/ui/builders/page_setup_builder.rb +51 -0
- data/lib/shoko/adapters/ui/component_factory.rb +103 -0
- data/lib/shoko/adapters/ui/components/annotation_editor_overlay/footer_renderer.rb +84 -0
- data/lib/shoko/adapters/ui/components/annotation_editor_overlay/geometry.rb +65 -0
- data/lib/shoko/adapters/ui/components/annotation_editor_overlay/note_renderer.rb +91 -0
- data/lib/shoko/adapters/ui/components/annotation_editor_overlay_component.rb +415 -0
- data/lib/shoko/adapters/ui/components/annotations_overlay/list_renderer.rb +148 -0
- data/lib/shoko/adapters/ui/components/annotations_overlay_component.rb +210 -0
- data/lib/shoko/adapters/ui/components/base_component.rb +118 -0
- data/lib/shoko/adapters/ui/components/content_component.rb +67 -0
- data/lib/shoko/adapters/ui/components/dictionary/entry_formatter.rb +232 -0
- data/lib/shoko/adapters/ui/components/dictionary_panel_component.rb +290 -0
- data/lib/shoko/adapters/ui/components/dictionary_popup/results_flow.rb +122 -0
- data/lib/shoko/adapters/ui/components/dictionary_popup/setup_flow.rb +479 -0
- data/lib/shoko/adapters/ui/components/dictionary_popup_component.rb +280 -0
- data/lib/shoko/adapters/ui/components/enhanced_popup_menu.rb +345 -0
- data/lib/shoko/adapters/ui/components/footer_component.rb +126 -0
- data/lib/shoko/adapters/ui/components/header_component.rb +48 -0
- data/lib/shoko/adapters/ui/components/in_book_search_popup_component.rb +509 -0
- data/lib/shoko/adapters/ui/components/layouts/horizontal.rb +67 -0
- data/lib/shoko/adapters/ui/components/layouts/horizontal_three.rb +94 -0
- data/lib/shoko/adapters/ui/components/layouts/vertical.rb +77 -0
- data/lib/shoko/adapters/ui/components/main_menu_component.rb +130 -0
- data/lib/shoko/adapters/ui/components/menu_design/frame_renderer.rb +93 -0
- data/lib/shoko/adapters/ui/components/menu_design/icon_set.rb +69 -0
- data/lib/shoko/adapters/ui/components/menu_design/layout.rb +33 -0
- data/lib/shoko/adapters/ui/components/menu_design/progress_renderer.rb +36 -0
- data/lib/shoko/adapters/ui/components/menu_design/search_field_renderer.rb +41 -0
- data/lib/shoko/adapters/ui/components/menu_design/status_renderer.rb +49 -0
- data/lib/shoko/adapters/ui/components/menu_design/table_renderer.rb +59 -0
- data/lib/shoko/adapters/ui/components/menu_design/theme_tokens.rb +73 -0
- data/lib/shoko/adapters/ui/components/rect.rb +19 -0
- data/lib/shoko/adapters/ui/components/render_style.rb +125 -0
- data/lib/shoko/adapters/ui/components/screen_component.rb +28 -0
- data/lib/shoko/adapters/ui/components/screens/annotation_detail_screen_component.rb +193 -0
- data/lib/shoko/adapters/ui/components/screens/annotation_edit_screen_component.rb +298 -0
- data/lib/shoko/adapters/ui/components/screens/annotation_editor_screen_component.rb +268 -0
- data/lib/shoko/adapters/ui/components/screens/annotation_rendering_helpers.rb +462 -0
- data/lib/shoko/adapters/ui/components/screens/annotations_screen_component.rb +398 -0
- data/lib/shoko/adapters/ui/components/screens/base_screen_component.rb +53 -0
- data/lib/shoko/adapters/ui/components/screens/browse_screen_component.rb +384 -0
- data/lib/shoko/adapters/ui/components/screens/dictionary_settings_screen_component.rb +501 -0
- data/lib/shoko/adapters/ui/components/screens/download_books_screen_component.rb +352 -0
- data/lib/shoko/adapters/ui/components/screens/library_screen_component.rb +383 -0
- data/lib/shoko/adapters/ui/components/screens/loading_overlay_component.rb +63 -0
- data/lib/shoko/adapters/ui/components/screens/menu_screen_component.rb +103 -0
- data/lib/shoko/adapters/ui/components/screens/settings_screen_component.rb +324 -0
- data/lib/shoko/adapters/ui/components/sidebar/annotations_tab_renderer.rb +170 -0
- data/lib/shoko/adapters/ui/components/sidebar/bookmarks_tab_renderer.rb +160 -0
- data/lib/shoko/adapters/ui/components/sidebar/tab_header_component.rb +168 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/constants.rb +23 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/context.rb +101 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/document_model.rb +59 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/entries_calculator.rb +99 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/entry_rendering.rb +185 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/index.rb +11 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/layout/entries_list_layout.rb +81 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/layout/entry_layout_helper.rb +48 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/layout/line_index.rb +63 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/layout/visible_entry_item.rb +97 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/layout/visible_items_calculator.rb +87 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/layout.rb +7 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/renderers/component_orchestrator.rb +27 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/renderers/empty_state_renderer.rb +51 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/renderers/entries_list_renderer.rb +28 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/renderers/filter_input_renderer.rb +52 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/renderers/header_renderer.rb +176 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/renderers/scrollbar_renderer.rb +51 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/renderers.rb +8 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/scroll_metrics.rb +152 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc/tree_formatting.rb +202 -0
- data/lib/shoko/adapters/ui/components/sidebar/toc_tab_renderer.rb +132 -0
- data/lib/shoko/adapters/ui/components/sidebar_panel_component.rb +229 -0
- data/lib/shoko/adapters/ui/components/surface.rb +92 -0
- data/lib/shoko/adapters/ui/components/tooltip_overlay_component.rb +251 -0
- data/lib/shoko/adapters/ui/components/ui/annotation_list_input.rb +102 -0
- data/lib/shoko/adapters/ui/components/ui/annotation_markup.rb +456 -0
- data/lib/shoko/adapters/ui/components/ui/box_drawer.rb +37 -0
- data/lib/shoko/adapters/ui/components/ui/cursor_blink.rb +104 -0
- data/lib/shoko/adapters/ui/components/ui/list_helpers.rb +37 -0
- data/lib/shoko/adapters/ui/components/ui/overlay_layout.rb +92 -0
- data/lib/shoko/adapters/ui/components/ui/text_utils.rb +50 -0
- data/lib/shoko/adapters/ui/constants/highlighting.rb +23 -0
- data/lib/shoko/adapters/ui/constants/messages.rb +14 -0
- data/lib/shoko/adapters/ui/constants/themes.rb +81 -0
- data/lib/shoko/adapters/ui/constants/ui_constants.rb +155 -0
- data/lib/shoko/adapters/ui/dependency_sets.rb +49 -0
- data/lib/shoko/adapters/ui/menu_visual_profile.rb +10 -0
- data/lib/shoko/adapters/ui/render_registry.rb +42 -0
- data/lib/shoko/adapters/ui/rendering/frame_coordinator.rb +55 -0
- data/lib/shoko/adapters/ui/rendering/line/config_helpers.rb +58 -0
- data/lib/shoko/adapters/ui/rendering/line/inline_segment_highlighter.rb +163 -0
- data/lib/shoko/adapters/ui/rendering/line/kitty_image_line_renderer.rb +256 -0
- data/lib/shoko/adapters/ui/rendering/line/line_content_composer.rb +253 -0
- data/lib/shoko/adapters/ui/rendering/line/line_drawer.rb +96 -0
- data/lib/shoko/adapters/ui/rendering/line/line_geometry_builder.rb +133 -0
- data/lib/shoko/adapters/ui/rendering/line/render_dependencies.rb +30 -0
- data/lib/shoko/adapters/ui/rendering/line/rendered_lines_recorder.rb +73 -0
- data/lib/shoko/adapters/ui/rendering/line/wrapped_lines_fetcher.rb +140 -0
- data/lib/shoko/adapters/{output → ui}/rendering/models/line_geometry.rb +4 -4
- data/lib/shoko/adapters/{output → ui}/rendering/models/page_rendering_context.rb +1 -1
- data/lib/shoko/adapters/{output → ui}/rendering/models/render_params.rb +1 -1
- data/lib/shoko/adapters/ui/rendering/models/rendering_context.rb +67 -0
- data/lib/shoko/adapters/ui/rendering/reader_render_coordinator.rb +272 -0
- data/lib/shoko/adapters/ui/rendering/render_pipeline.rb +75 -0
- data/lib/shoko/adapters/ui/rendering/views/base_view_renderer.rb +218 -0
- data/lib/shoko/adapters/ui/rendering/views/help_renderer.rb +67 -0
- data/lib/shoko/adapters/ui/rendering/views/single_view_renderer.rb +190 -0
- data/lib/shoko/adapters/ui/rendering/views/split_view_renderer.rb +261 -0
- data/lib/shoko/adapters/ui/rendering/views/view_renderer_factory.rb +27 -0
- data/lib/shoko/adapters/ui/rendering_factory.rb +48 -0
- data/lib/shoko/adapters/ui/sessions/annotation_editor_launcher_adapter.rb +29 -0
- data/lib/shoko/adapters/ui/sessions/annotation_overlay_ui_session_adapter.rb +294 -0
- data/lib/shoko/adapters/ui/sessions/dictionary_ui_session_adapter.rb +342 -0
- data/lib/shoko/adapters/ui/sessions/in_book_search_ui_session_adapter.rb +189 -0
- data/lib/shoko/adapters/ui/view_models/reader_view_model.rb +179 -0
- data/lib/shoko/adapters/ui/view_models/reader_view_model_builder.rb +64 -0
- data/lib/shoko/application/cli_progress_presenter.rb +48 -0
- data/lib/shoko/application/pending_jump_handler.rb +55 -71
- data/lib/shoko/application/services/pagination/page_info_calculator.rb +262 -0
- data/lib/shoko/application/services/pagination/pagination_cache_preloader.rb +232 -0
- data/lib/shoko/application/services/pagination/pagination_coordinator.rb +279 -0
- data/lib/shoko/application/services/pagination/pagination_orchestrator.rb +399 -0
- data/lib/shoko/application/services/popup_position_service.rb +35 -0
- data/lib/shoko/application/services/reader/annotation_state_service.rb +53 -0
- data/lib/shoko/application/services/reader/bookmark_service.rb +318 -0
- data/lib/shoko/application/services/reader/navigation/absolute_change_applier.rb +98 -0
- data/lib/shoko/application/services/reader/navigation/absolute_layout.rb +128 -0
- data/lib/shoko/application/services/reader/navigation/absolute_strategy.rb +181 -0
- data/lib/shoko/application/services/reader/navigation/context_builder.rb +77 -0
- data/lib/shoko/application/services/reader/navigation/context_helpers.rb +77 -0
- data/lib/shoko/application/services/reader/navigation/dynamic_change_applier.rb +49 -0
- data/lib/shoko/application/services/reader/navigation/dynamic_strategy.rb +53 -0
- data/lib/shoko/application/services/reader/navigation/image_offset_snapper.rb +183 -0
- data/lib/shoko/application/services/reader/navigation/nav_context.rb +29 -0
- data/lib/shoko/application/services/reader/navigation/state_updater.rb +26 -0
- data/lib/shoko/application/services/reader/navigation/strategy_factory.rb +22 -0
- data/lib/shoko/application/services/reader/navigation_service.rb +169 -0
- data/lib/shoko/application/unified_application.rb +134 -18
- data/lib/shoko/application/use_cases/catalog_service.rb +52 -38
- data/lib/shoko/application/use_cases/command_bus.rb +170 -0
- data/lib/shoko/application/use_cases/commands/base_command.rb +125 -135
- data/lib/shoko/application/use_cases/commands/bookmark_commands.rb +70 -84
- data/lib/shoko/application/use_cases/commands/input_command_payload.rb +13 -0
- data/lib/shoko/application/use_cases/commands/menu_intent_command.rb +51 -0
- data/lib/shoko/application/use_cases/commands/navigation_commands.rb +151 -134
- data/lib/shoko/application/use_cases/commands/reader_intent_command.rb +51 -0
- data/lib/shoko/application/use_cases/commands/shared_intent_command.rb +55 -0
- data/lib/shoko/application/use_cases/intents/menu_intent_handler.rb +47 -0
- data/lib/shoko/application/use_cases/intents/reader_intent_handler.rb +47 -0
- data/lib/shoko/application/use_cases/settings_service.rb +173 -55
- data/lib/shoko/application/workflows/cli/folder_import_workflow.rb +164 -0
- data/lib/shoko/application/workflows/menu/annotation_workflow.rb +132 -0
- data/lib/shoko/application/workflows/menu/dictionary_workflow.rb +203 -0
- data/lib/shoko/application/workflows/menu/download_workflow.rb +181 -0
- data/lib/shoko/application/workflows/menu/menu_progress_presenter.rb +85 -0
- data/lib/shoko/application/workflows/menu/null_progress_presenter.rb +24 -0
- data/lib/shoko/application/workflows/menu/reader_launch/contracts.rb +70 -0
- data/lib/shoko/application/workflows/menu/reader_launch/document_preparation.rb +137 -0
- data/lib/shoko/application/workflows/menu/reader_launch/path_resolution.rb +76 -0
- data/lib/shoko/application/workflows/menu/reader_launch/progress_orchestration.rb +203 -0
- data/lib/shoko/application/workflows/menu/reader_launch/runtime_execution.rb +106 -0
- data/lib/shoko/application/workflows/menu/reader_launch_service.rb +161 -0
- data/lib/shoko/bootstrap/container_factory/controller_composition/menu_builder.rb +163 -0
- data/lib/shoko/bootstrap/container_factory/controller_composition/menu_state_controller_composer.rb +174 -0
- data/lib/shoko/bootstrap/container_factory/controller_composition/reader_builder.rb +400 -0
- data/lib/shoko/bootstrap/container_factory/controller_composition/reader_runtime_assembler.rb +267 -0
- data/lib/shoko/bootstrap/container_factory/controller_composition.rb +19 -0
- data/lib/shoko/bootstrap/container_factory/domain_application_registration.rb +340 -0
- data/lib/shoko/bootstrap/container_factory/infrastructure_registration.rb +123 -0
- data/lib/shoko/bootstrap/container_factory/port_and_repository_registration.rb +241 -0
- data/lib/shoko/bootstrap/container_factory/test_container_registration.rb +198 -0
- data/lib/shoko/bootstrap/container_factory.rb +174 -0
- data/lib/shoko/bootstrap/dependency_container.rb +142 -0
- data/lib/shoko/bootstrap/format_registry_bootstrap.rb +137 -0
- data/lib/shoko/bootstrap/runtime_bootstrap.rb +86 -0
- data/lib/shoko/core/book_formats/epub/html_processor.rb +146 -0
- data/lib/shoko/core/book_formats/epub/metadata_extractor.rb +65 -0
- data/lib/shoko/core/book_formats/epub/opf/entry_reader.rb +120 -0
- data/lib/shoko/core/book_formats/epub/opf/metadata_extractor.rb +71 -0
- data/lib/shoko/core/book_formats/epub/opf/navigation_context.rb +90 -0
- data/lib/shoko/core/book_formats/epub/opf/navigation_document_index.rb +79 -0
- data/lib/shoko/core/book_formats/epub/opf/navigation_document_scanner.rb +51 -0
- data/lib/shoko/core/book_formats/epub/opf/navigation_extractor.rb +50 -0
- data/lib/shoko/core/book_formats/epub/opf/navigation_label_resolver.rb +91 -0
- data/lib/shoko/core/book_formats/epub/opf/navigation_list_item.rb +59 -0
- data/lib/shoko/core/book_formats/epub/opf/navigation_result.rb +12 -0
- data/lib/shoko/core/book_formats/epub/opf/navigation_selector.rb +104 -0
- data/lib/shoko/core/book_formats/epub/opf/navigation_source_locator.rb +97 -0
- data/lib/shoko/core/book_formats/epub/opf/navigation_traversal.rb +108 -0
- data/lib/shoko/core/book_formats/epub/opf/navigation_walker.rb +60 -0
- data/lib/shoko/core/book_formats/epub/opf_processor.rb +115 -0
- data/lib/shoko/core/book_formats/epub/rexml_safe_parser.rb +22 -0
- data/lib/shoko/core/book_formats/epub/xhtml_content_parser.rb +803 -0
- data/lib/shoko/core/book_formats/epub/xml_text_normalizer.rb +45 -0
- data/lib/shoko/core/book_formats/fb2/fb2_content_parser.rb +324 -0
- data/lib/shoko/core/book_formats/fb2/fb2_inline_parser.rb +117 -0
- data/lib/shoko/core/book_formats/fb2/fb2_metadata_extractor.rb +68 -0
- data/lib/shoko/core/book_formats/fb2/fb2_section_flattener.rb +133 -0
- data/lib/shoko/core/book_formats/fb2/metadata_parser.rb +96 -0
- data/lib/shoko/core/book_formats/format_registry.rb +157 -0
- data/lib/shoko/core/book_formats/kindle/exth_parser.rb +169 -0
- data/lib/shoko/core/book_formats/kindle/kindle_content_parser.rb +31 -0
- data/lib/shoko/core/book_formats/kindle/kindle_metadata_extractor.rb +79 -0
- data/lib/shoko/core/book_formats/kindle/metadata_parser.rb +61 -0
- data/lib/shoko/core/book_formats/kindle/mobi_header_parser.rb +224 -0
- data/lib/shoko/core/book_formats/kindle/palmdoc_decompressor.rb +142 -0
- data/lib/shoko/core/book_formats/kindle/pdb_header_parser.rb +103 -0
- data/lib/shoko/core/book_formats/pdf/metadata_parser.rb +57 -0
- data/lib/shoko/core/book_formats/pdf/pdf_content_parser.rb +687 -0
- data/lib/shoko/core/book_formats/pdf/pdf_metadata_extractor.rb +64 -0
- data/lib/shoko/core/book_formats/pdf/pdf_reader.rb +485 -0
- data/lib/shoko/core/book_formats/pdf/pdf_text_extractor.rb +629 -0
- data/lib/shoko/core/book_formats/rtf/metadata_parser.rb +121 -0
- data/lib/shoko/core/book_formats/rtf/rtf_content_parser.rb +29 -0
- data/lib/shoko/core/book_formats/rtf/rtf_metadata_extractor.rb +73 -0
- data/lib/shoko/core/book_formats/rtf/rtf_parser.rb +767 -0
- data/lib/shoko/core/errors/dictionary_failure.rb +30 -0
- data/lib/shoko/core/events/base_domain_event.rb +30 -10
- data/lib/shoko/core/events/domain_event_bus.rb +15 -21
- data/lib/shoko/core/events/event_factory.rb +23 -0
- data/lib/shoko/core/models/annotation_selection.rb +59 -0
- data/lib/shoko/core/models/block_type.rb +51 -0
- data/lib/shoko/core/models/book_data.rb +29 -0
- data/lib/shoko/core/models/chapter.rb +5 -1
- data/lib/shoko/core/models/dictionary_catalog_entry.rb +52 -0
- data/lib/shoko/core/models/dictionary_entry.rb +163 -0
- data/lib/shoko/core/models/menu_book.rb +36 -0
- data/lib/shoko/core/models/pending_jump_payload.rb +58 -0
- data/lib/shoko/core/models/reader_settings.rb +8 -8
- data/lib/shoko/core/models/reading_progress.rb +30 -0
- data/lib/shoko/core/models/selection_anchor.rb +58 -53
- data/lib/shoko/core/ports/inbound/command_bus.rb +39 -0
- data/lib/shoko/core/ports/inbound/input_command_payload.rb +55 -0
- data/lib/shoko/core/ports/inbound/intent_dispatch_context.rb +24 -0
- data/lib/shoko/core/ports/inbound/menu_intent_handler.rb +82 -0
- data/lib/shoko/core/ports/inbound/reader_bookmark_command_context.rb +16 -0
- data/lib/shoko/core/ports/inbound/reader_intent_handler.rb +70 -0
- data/lib/shoko/core/ports/inbound/reader_navigation_command_context.rb +20 -0
- data/lib/shoko/core/ports/outbound/annotation_editor_launcher.rb +16 -0
- data/lib/shoko/core/ports/outbound/annotation_repository.rb +96 -0
- data/lib/shoko/core/ports/outbound/annotation_selection_reader.rb +17 -0
- data/lib/shoko/core/ports/outbound/annotation_view_refresher.rb +16 -0
- data/lib/shoko/core/ports/outbound/app_mode_runner.rb +20 -0
- data/lib/shoko/core/ports/outbound/async_executor.rb +26 -0
- data/lib/shoko/core/ports/outbound/background_worker_builder.rb +19 -0
- data/lib/shoko/core/ports/outbound/book_cache_pipeline_factory.rb +16 -0
- data/lib/shoko/core/ports/outbound/bookmark_repository.rb +79 -0
- data/lib/shoko/core/ports/outbound/cache_availability.rb +20 -0
- data/lib/shoko/core/ports/outbound/cache_manager.rb +28 -0
- data/lib/shoko/core/ports/outbound/cache_pointer_resolver.rb +29 -0
- data/lib/shoko/core/ports/outbound/chapter_formatter.rb +38 -0
- data/lib/shoko/core/ports/outbound/clock.rb +16 -0
- data/lib/shoko/core/ports/outbound/config_reader.rb +60 -0
- data/lib/shoko/core/ports/outbound/config_storage.rb +71 -0
- data/lib/shoko/core/ports/outbound/data_cleanup.rb +34 -0
- data/lib/shoko/core/ports/outbound/dictionary_availability.rb +21 -0
- data/lib/shoko/core/ports/outbound/dictionary_repository.rb +78 -0
- data/lib/shoko/core/ports/outbound/dictionary_storage.rb +47 -0
- data/lib/shoko/core/ports/outbound/display_capabilities.rb +20 -0
- data/lib/shoko/core/ports/outbound/document_loader.rb +20 -0
- data/lib/shoko/core/ports/outbound/event_publisher.rb +18 -0
- data/lib/shoko/core/ports/outbound/file_probe.rb +24 -0
- data/lib/shoko/core/ports/outbound/folder_importer.rb +17 -0
- data/lib/shoko/core/ports/outbound/folder_scanner.rb +18 -0
- data/lib/shoko/core/ports/outbound/id_generator.rb +16 -0
- data/lib/shoko/core/ports/outbound/instrumentation.rb +33 -0
- data/lib/shoko/core/ports/outbound/layout_metrics.rb +80 -0
- data/lib/shoko/core/ports/outbound/library_scanner.rb +48 -0
- data/lib/shoko/core/ports/outbound/line_wrapper.rb +36 -0
- data/lib/shoko/core/ports/outbound/logging.rb +67 -0
- data/lib/shoko/core/ports/outbound/menu_book_selection.rb +22 -0
- data/lib/shoko/core/ports/outbound/menu_intent_executor.rb +16 -0
- data/lib/shoko/core/ports/outbound/menu_launch_state.rb +24 -0
- data/lib/shoko/core/ports/outbound/menu_mode_switcher.rb +16 -0
- data/lib/shoko/core/ports/outbound/menu_progress_presenters.rb +16 -0
- data/lib/shoko/core/ports/outbound/menu_reader_runtime.rb +24 -0
- data/lib/shoko/core/ports/outbound/menu_workflow_runtime.rb +20 -0
- data/lib/shoko/core/ports/outbound/menu_workflow_state_reader.rb +36 -0
- data/lib/shoko/core/ports/outbound/menu_workflow_state_writer.rb +28 -0
- data/lib/shoko/core/ports/outbound/metadata_reader.rb +22 -0
- data/lib/shoko/core/ports/outbound/notification_writer.rb +20 -0
- data/lib/shoko/core/ports/outbound/observer_registry.rb +32 -0
- data/lib/shoko/core/ports/outbound/pagination_state_writer.rb +24 -0
- data/lib/shoko/core/ports/outbound/path_ops.rb +28 -0
- data/lib/shoko/core/ports/outbound/process_control.rb +16 -0
- data/lib/shoko/core/ports/outbound/progress_repository.rb +57 -0
- data/lib/shoko/core/ports/outbound/reader_chapter.rb +24 -0
- data/lib/shoko/core/ports/outbound/reader_document.rb +32 -0
- data/lib/shoko/core/ports/outbound/reader_intent_executor.rb +16 -0
- data/lib/shoko/core/ports/outbound/reader_launch_state.rb +36 -0
- data/lib/shoko/core/ports/outbound/reader_navigation_reader.rb +56 -0
- data/lib/shoko/core/ports/outbound/reader_render_requester.rb +18 -0
- data/lib/shoko/core/ports/outbound/reader_runner.rb +16 -0
- data/lib/shoko/core/ports/outbound/reader_state_writer.rb +48 -0
- data/lib/shoko/core/ports/outbound/recent_files_repository.rb +27 -0
- data/lib/shoko/core/ports/outbound/render_state_writer.rb +22 -0
- data/lib/shoko/core/ports/outbound/rendered_content_reader.rb +34 -0
- data/lib/shoko/core/ports/outbound/runtime_config.rb +113 -0
- data/lib/shoko/core/ports/outbound/sidebar_state_reader.rb +48 -0
- data/lib/shoko/core/ports/outbound/terminal_capabilities.rb +35 -0
- data/lib/shoko/core/ports/outbound/terminal_session.rb +24 -0
- data/lib/shoko/core/ports/outbound/text_metrics.rb +21 -0
- data/lib/shoko/core/ports/outbound/text_sanitizer.rb +24 -0
- data/lib/shoko/core/ports/outbound/ui_loading_writer.rb +16 -0
- data/lib/shoko/core/ports/outbound/ui_state_reader.rb +32 -0
- data/lib/shoko/core/ports/outbound/wall_clock.rb +16 -0
- data/lib/shoko/core/ports/outbound/wrapped_lines_provider.rb +25 -0
- data/lib/shoko/core/services/annotation_service.rb +39 -52
- data/lib/shoko/core/services/base_service.rb +7 -46
- data/lib/shoko/core/services/coordinate_service.rb +7 -34
- data/lib/shoko/core/services/default_display_capabilities.rb +18 -0
- data/lib/shoko/core/services/default_layout_metrics.rb +65 -0
- data/lib/shoko/core/services/default_terminal_capabilities.rb +23 -0
- data/lib/shoko/core/services/default_text_metrics.rb +44 -0
- data/lib/shoko/core/services/dictionary_service.rb +232 -0
- data/lib/shoko/core/services/document_path_resolver.rb +62 -0
- data/lib/shoko/core/services/in_book_search_service.rb +188 -0
- data/lib/shoko/core/services/inline_executor.rb +24 -0
- data/lib/shoko/core/services/layout_service.rb +34 -9
- data/lib/shoko/core/services/null_instrumentation.rb +24 -0
- data/lib/shoko/core/services/null_logger.rb +39 -0
- data/lib/shoko/core/services/page_calculator_service.rb +330 -106
- data/lib/shoko/core/services/pagination/internal/absolute_page_map_builder.rb +53 -21
- data/lib/shoko/core/services/pagination/internal/chapter_cache.rb +56 -45
- data/lib/shoko/core/services/pagination/internal/dynamic_page_map_builder.rb +165 -110
- data/lib/shoko/core/services/pagination/internal/layout_metrics_calculator.rb +51 -58
- data/lib/shoko/core/services/pagination/internal/page_hydrator.rb +115 -120
- data/lib/shoko/core/services/pagination/internal/pagination_workflow.rb +141 -128
- data/lib/shoko/core/services/progress_helper.rb +10 -10
- data/lib/shoko/core/services/selection_service.rb +62 -53
- data/lib/shoko/core/services/toc_tree_service.rb +196 -0
- data/lib/shoko/shared/contracts/session_outcome.rb +18 -0
- data/lib/shoko/shared/errors.rb +101 -3
- data/lib/shoko/{adapters/input → shared}/key_definitions.rb +18 -22
- data/lib/shoko/shared/menu_definitions.rb +76 -0
- data/lib/shoko/shared/optional_dependency.rb +70 -0
- data/lib/shoko/shared/runtime/null_runtime_config.rb +44 -0
- data/lib/shoko/{adapters/book_sources → shared}/source_fingerprint.rb +5 -5
- data/lib/shoko/shared/terminal/ansi.rb +73 -0
- data/lib/shoko/shared/terminal/kitty_unicode_placeholders.rb +137 -0
- data/lib/shoko/shared/terminal/text_metrics.rb +490 -0
- data/lib/shoko/shared/terminal/text_sanitizer.rb +12 -0
- data/lib/shoko/shared/text_sanitizer.rb +239 -0
- data/lib/shoko/shared/ui_constraints.rb +11 -0
- data/lib/shoko/shared/unicode_display_width/display_width.marshal.gz +0 -0
- data/lib/shoko/shared/unicode_display_width.rb +147 -0
- data/lib/shoko/shared/version.rb +1 -1
- data/lib/shoko/test_support/terminal_double.rb +1 -1
- data/lib/shoko/test_support/test_mode.rb +5 -19
- data/lib/shoko.rb +4 -275
- data/script/architecture/fallback_report.rb +105 -0
- data/script/bench/sidebar_toggle_layout_benchmark.rb +194 -0
- data/script/bench/snappiness_benchmark.rb +443 -0
- data/script/bench/startup_menu_benchmark.rb +114 -0
- data/tmp/rspec-results/fixtures.json +1 -0
- data/tmp/rspec-results/full-seed-10101.log +10 -0
- data/tmp/rspec-results/full-seed-1559.log +10 -0
- data/tmp/rspec-results/full-seed-20202.log +10 -0
- data/tmp/rspec-results/full-seed-30303.log +10 -0
- data/tmp/rspec-results/full-seed-49446.log +10 -0
- data/tmp/rspec-results/full-seed-52407.log +10 -0
- data/tmp/rspec-results/full-seed-5517.log +10 -0
- data/tmp/rspec-results/full-seed-56072.log +10 -0
- data/tmp/rspec-results/full-seed-61968.log +10 -0
- data/tmp/rspec-results/full-seed-63851.log +10 -0
- data/tmp/rspec-results/full-seed-65033.log +10 -0
- data/tmp/rspec-results/full-seed-87095.log +10 -0
- data/tmp/rspec-results/full-seed-97342.log +10 -0
- data/tmp/rspec-results/guardrails.json +1 -0
- data/tmp/rspec-results/required-seed-10101.json +1 -0
- data/tmp/rspec-results/required-seed-20202.json +1 -0
- data/tmp/rspec-results/required-seed-30303.json +1 -0
- data/tmp/rubocop-metrics.json +1 -0
- metadata +507 -227
- data/lib/shoko/adapters/book_sources/epub/parsers/html_processor.rb +0 -151
- data/lib/shoko/adapters/book_sources/epub/parsers/metadata_extractor.rb +0 -53
- data/lib/shoko/adapters/book_sources/epub/parsers/opf/entry_reader.rb +0 -77
- data/lib/shoko/adapters/book_sources/epub/parsers/opf/metadata_extractor.rb +0 -67
- data/lib/shoko/adapters/book_sources/epub/parsers/opf/navigation_context.rb +0 -86
- data/lib/shoko/adapters/book_sources/epub/parsers/opf/navigation_document_index.rb +0 -75
- data/lib/shoko/adapters/book_sources/epub/parsers/opf/navigation_document_scanner.rb +0 -47
- data/lib/shoko/adapters/book_sources/epub/parsers/opf/navigation_extractor.rb +0 -46
- data/lib/shoko/adapters/book_sources/epub/parsers/opf/navigation_label_resolver.rb +0 -83
- data/lib/shoko/adapters/book_sources/epub/parsers/opf/navigation_list_item.rb +0 -55
- data/lib/shoko/adapters/book_sources/epub/parsers/opf/navigation_result.rb +0 -8
- data/lib/shoko/adapters/book_sources/epub/parsers/opf/navigation_selector.rb +0 -100
- data/lib/shoko/adapters/book_sources/epub/parsers/opf/navigation_source_locator.rb +0 -93
- data/lib/shoko/adapters/book_sources/epub/parsers/opf/navigation_traversal.rb +0 -103
- data/lib/shoko/adapters/book_sources/epub/parsers/opf/navigation_walker.rb +0 -56
- data/lib/shoko/adapters/book_sources/epub/parsers/opf_processor.rb +0 -102
- data/lib/shoko/adapters/book_sources/epub/parsers/xhtml_content_parser.rb +0 -661
- data/lib/shoko/adapters/book_sources/epub/parsers/xml_text_normalizer.rb +0 -41
- data/lib/shoko/adapters/book_sources/epub_document.rb +0 -253
- data/lib/shoko/adapters/book_sources/epub_finder/directory_scanner.rb +0 -134
- data/lib/shoko/adapters/book_sources/epub_finder/scanner_context.rb +0 -28
- data/lib/shoko/adapters/book_sources/epub_importer.rb +0 -268
- data/lib/shoko/adapters/input/command_bridge.rb +0 -148
- data/lib/shoko/adapters/input/input_controller.rb +0 -250
- data/lib/shoko/adapters/monitoring/logger.rb +0 -150
- data/lib/shoko/adapters/output/render_registry.rb +0 -45
- data/lib/shoko/adapters/output/rendering/models/rendering_context.rb +0 -58
- data/lib/shoko/adapters/output/ui/builders/page_setup_builder.rb +0 -47
- data/lib/shoko/adapters/output/ui/components/annotation_editor_overlay/footer_renderer.rb +0 -80
- data/lib/shoko/adapters/output/ui/components/annotation_editor_overlay/geometry.rb +0 -61
- data/lib/shoko/adapters/output/ui/components/annotation_editor_overlay/note_renderer.rb +0 -86
- data/lib/shoko/adapters/output/ui/components/annotation_editor_overlay_component.rb +0 -234
- data/lib/shoko/adapters/output/ui/components/annotations_overlay/list_renderer.rb +0 -142
- data/lib/shoko/adapters/output/ui/components/annotations_overlay_component.rb +0 -185
- data/lib/shoko/adapters/output/ui/components/base_component.rb +0 -110
- data/lib/shoko/adapters/output/ui/components/component_interface.rb +0 -80
- data/lib/shoko/adapters/output/ui/components/content_component.rb +0 -61
- data/lib/shoko/adapters/output/ui/components/enhanced_popup_menu.rb +0 -191
- data/lib/shoko/adapters/output/ui/components/footer_component.rb +0 -120
- data/lib/shoko/adapters/output/ui/components/header_component.rb +0 -46
- data/lib/shoko/adapters/output/ui/components/layouts/horizontal.rb +0 -63
- data/lib/shoko/adapters/output/ui/components/layouts/vertical.rb +0 -73
- data/lib/shoko/adapters/output/ui/components/main_menu_component.rb +0 -103
- data/lib/shoko/adapters/output/ui/components/reading/base_view_renderer.rb +0 -199
- data/lib/shoko/adapters/output/ui/components/reading/config_helpers.rb +0 -42
- data/lib/shoko/adapters/output/ui/components/reading/help_renderer.rb +0 -62
- data/lib/shoko/adapters/output/ui/components/reading/inline_segment_highlighter.rb +0 -144
- data/lib/shoko/adapters/output/ui/components/reading/kitty_image_line_renderer.rb +0 -262
- data/lib/shoko/adapters/output/ui/components/reading/line_content_composer.rb +0 -114
- data/lib/shoko/adapters/output/ui/components/reading/line_drawer.rb +0 -87
- data/lib/shoko/adapters/output/ui/components/reading/line_geometry_builder.rb +0 -41
- data/lib/shoko/adapters/output/ui/components/reading/rendered_lines_recorder.rb +0 -64
- data/lib/shoko/adapters/output/ui/components/reading/single_view_renderer.rb +0 -156
- data/lib/shoko/adapters/output/ui/components/reading/split_view_renderer.rb +0 -221
- data/lib/shoko/adapters/output/ui/components/reading/view_renderer_factory.rb +0 -20
- data/lib/shoko/adapters/output/ui/components/reading/wrapped_lines_fetcher.rb +0 -139
- data/lib/shoko/adapters/output/ui/components/rect.rb +0 -15
- data/lib/shoko/adapters/output/ui/components/render_style.rb +0 -84
- data/lib/shoko/adapters/output/ui/components/screen_component.rb +0 -24
- data/lib/shoko/adapters/output/ui/components/screens/annotation_detail_screen_component.rb +0 -175
- data/lib/shoko/adapters/output/ui/components/screens/annotation_edit_screen_component.rb +0 -221
- data/lib/shoko/adapters/output/ui/components/screens/annotation_editor_screen_component.rb +0 -205
- data/lib/shoko/adapters/output/ui/components/screens/annotation_rendering_helpers.rb +0 -190
- data/lib/shoko/adapters/output/ui/components/screens/annotations_screen_component.rb +0 -266
- data/lib/shoko/adapters/output/ui/components/screens/base_screen_component.rb +0 -49
- data/lib/shoko/adapters/output/ui/components/screens/browse_screen_component.rb +0 -319
- data/lib/shoko/adapters/output/ui/components/screens/download_books_screen_component.rb +0 -340
- data/lib/shoko/adapters/output/ui/components/screens/library_screen_component.rb +0 -205
- data/lib/shoko/adapters/output/ui/components/screens/loading_overlay_component.rb +0 -49
- data/lib/shoko/adapters/output/ui/components/screens/menu_screen_component.rb +0 -107
- data/lib/shoko/adapters/output/ui/components/screens/settings_screen_component.rb +0 -238
- data/lib/shoko/adapters/output/ui/components/sidebar/annotations_tab_renderer.rb +0 -159
- data/lib/shoko/adapters/output/ui/components/sidebar/bookmarks_tab_renderer.rb +0 -139
- data/lib/shoko/adapters/output/ui/components/sidebar/tab_header_component.rb +0 -157
- data/lib/shoko/adapters/output/ui/components/sidebar/toc_tab_renderer.rb +0 -111
- data/lib/shoko/adapters/output/ui/components/sidebar/toc_tab_support.rb +0 -1606
- data/lib/shoko/adapters/output/ui/components/sidebar_panel_component.rb +0 -217
- data/lib/shoko/adapters/output/ui/components/surface.rb +0 -88
- data/lib/shoko/adapters/output/ui/components/tooltip_overlay_component.rb +0 -224
- data/lib/shoko/adapters/output/ui/components/ui/box_drawer.rb +0 -32
- data/lib/shoko/adapters/output/ui/components/ui/list_helpers.rb +0 -33
- data/lib/shoko/adapters/output/ui/components/ui/overlay_layout.rb +0 -79
- data/lib/shoko/adapters/output/ui/components/ui/text_utils.rb +0 -46
- data/lib/shoko/adapters/output/ui/constants/highlighting.rb +0 -21
- data/lib/shoko/adapters/output/ui/constants/messages.rb +0 -12
- data/lib/shoko/adapters/output/ui/constants/themes.rb +0 -79
- data/lib/shoko/adapters/output/ui/constants/ui_constants.rb +0 -85
- data/lib/shoko/adapters/output/ui/rendering/frame_coordinator.rb +0 -42
- data/lib/shoko/adapters/output/ui/rendering/reader_render_coordinator.rb +0 -169
- data/lib/shoko/adapters/output/ui/rendering/render_pipeline.rb +0 -55
- data/lib/shoko/adapters/storage/repositories/config_repository.rb +0 -262
- data/lib/shoko/application/annotation_editor_overlay_session.rb +0 -138
- data/lib/shoko/application/cli.rb +0 -134
- data/lib/shoko/application/controllers/menu/input_controller.rb +0 -189
- data/lib/shoko/application/controllers/menu/state_controller.rb +0 -642
- data/lib/shoko/application/controllers/menu_controller.rb +0 -469
- data/lib/shoko/application/controllers/mouseable_reader.rb +0 -421
- data/lib/shoko/application/controllers/reader_controller.rb +0 -449
- data/lib/shoko/application/controllers/state_controller.rb +0 -410
- data/lib/shoko/application/controllers/ui_controller.rb +0 -782
- data/lib/shoko/application/dependency_container.rb +0 -301
- data/lib/shoko/application/infrastructure/event_bus.rb +0 -80
- data/lib/shoko/application/infrastructure/observer_state_store.rb +0 -136
- data/lib/shoko/application/infrastructure/state_store.rb +0 -413
- data/lib/shoko/application/main_menu/menu_progress_presenter.rb +0 -83
- data/lib/shoko/application/reader_lifecycle.rb +0 -65
- data/lib/shoko/application/reader_startup_orchestrator.rb +0 -113
- data/lib/shoko/application/selectors/config_selectors.rb +0 -62
- data/lib/shoko/application/selectors/menu_selectors.rb +0 -62
- data/lib/shoko/application/selectors/reader_selectors.rb +0 -190
- data/lib/shoko/application/state/actions/base_action.rb +0 -24
- data/lib/shoko/application/state/actions/quit_to_menu_action.rb +0 -16
- data/lib/shoko/application/state/actions/switch_reader_mode_action.rb +0 -22
- data/lib/shoko/application/state/actions/toggle_view_mode_action.rb +0 -31
- data/lib/shoko/application/state/actions/update_annotation_editor_overlay_action.rb +0 -27
- data/lib/shoko/application/state/actions/update_annotations_action.rb +0 -20
- data/lib/shoko/application/state/actions/update_annotations_overlay_action.rb +0 -27
- data/lib/shoko/application/state/actions/update_bookmarks_action.rb +0 -20
- data/lib/shoko/application/state/actions/update_chapter_action.rb +0 -24
- data/lib/shoko/application/state/actions/update_config_action.rb +0 -22
- data/lib/shoko/application/state/actions/update_field_helpers.rb +0 -26
- data/lib/shoko/application/state/actions/update_menu_action.rb +0 -21
- data/lib/shoko/application/state/actions/update_message_action.rb +0 -35
- data/lib/shoko/application/state/actions/update_page_action.rb +0 -21
- data/lib/shoko/application/state/actions/update_pagination_state_action.rb +0 -21
- data/lib/shoko/application/state/actions/update_popup_menu_action.rb +0 -27
- data/lib/shoko/application/state/actions/update_reader_meta_action.rb +0 -21
- data/lib/shoko/application/state/actions/update_reader_mode_action.rb +0 -20
- data/lib/shoko/application/state/actions/update_rendered_lines_action.rb +0 -40
- data/lib/shoko/application/state/actions/update_selection_action.rb +0 -27
- data/lib/shoko/application/state/actions/update_selections_action.rb +0 -21
- data/lib/shoko/application/state/actions/update_sidebar_action.rb +0 -34
- data/lib/shoko/application/state/actions/update_ui_loading_action.rb +0 -23
- data/lib/shoko/application/ui/reader_view_model_builder.rb +0 -74
- data/lib/shoko/application/ui/view_models/reader_view_model.rb +0 -177
- data/lib/shoko/application/use_cases/commands/annotation_editor_commands.rb +0 -105
- data/lib/shoko/application/use_cases/commands/application_commands.rb +0 -208
- data/lib/shoko/application/use_cases/commands/conditional_navigation_commands.rb +0 -57
- data/lib/shoko/application/use_cases/commands/menu_commands.rb +0 -170
- data/lib/shoko/application/use_cases/commands/reader_commands.rb +0 -46
- data/lib/shoko/application/use_cases/commands/sidebar_commands.rb +0 -55
- data/lib/shoko/core/ports/annotation_repository.rb +0 -0
- data/lib/shoko/core/ports/book_repository.rb +0 -0
- data/lib/shoko/core/ports/book_source.rb +0 -0
- data/lib/shoko/core/ports/bookmark_repository.rb +0 -0
- data/lib/shoko/core/ports/cache.rb +0 -0
- data/lib/shoko/core/ports/input_handler.rb +0 -0
- data/lib/shoko/core/ports/renderer.rb +0 -0
- data/lib/shoko/core/ports/storage.rb +0 -0
- data/lib/shoko/core/services/bookmark_service.rb +0 -267
- data/lib/shoko/core/services/navigation/absolute_change_applier.rb +0 -96
- data/lib/shoko/core/services/navigation/absolute_layout.rb +0 -101
- data/lib/shoko/core/services/navigation/absolute_strategy.rb +0 -179
- data/lib/shoko/core/services/navigation/context_builder.rb +0 -52
- data/lib/shoko/core/services/navigation/context_helpers.rb +0 -63
- data/lib/shoko/core/services/navigation/dynamic_change_applier.rb +0 -50
- data/lib/shoko/core/services/navigation/dynamic_strategy.rb +0 -51
- data/lib/shoko/core/services/navigation/image_offset_snapper.rb +0 -150
- data/lib/shoko/core/services/navigation/nav_context.rb +0 -27
- data/lib/shoko/core/services/navigation/state_updater.rb +0 -29
- data/lib/shoko/core/services/navigation/strategy_factory.rb +0 -20
- data/lib/shoko/core/services/navigation_service.rb +0 -150
- data/lib/shoko/core/services/pagination/page_info_calculator.rb +0 -247
- data/lib/shoko/core/services/pagination/pagination_cache_preloader.rb +0 -173
- data/lib/shoko/core/services/pagination/pagination_coordinator.rb +0 -202
- data/lib/shoko/core/services/pagination/pagination_orchestrator.rb +0 -291
- data/zip.rb +0 -5
- /data/lib/shoko/{adapters/output/kitty → shared/terminal}/kitty_unicode_placeholders_diacritic_codepoints.txt +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":"3.13.6","messages":["Run options: exclude {requires_book_fixtures: true}"],"seed":30303,"examples":[{"id":"./spec/core/architecture/command_dispatch_guardrails_spec.rb[1:4]","description":"forbids adapter references to Application::Services::DocumentPathResolver","full_description":"Command dispatch guardrails forbids adapter references to Application::Services::DocumentPathResolver","status":"passed","file_path":"./spec/core/architecture/command_dispatch_guardrails_spec.rb","line_number":60,"run_time":0.039271693,"pending_message":null},{"id":"./spec/core/architecture/command_dispatch_guardrails_spec.rb[1:1]","description":"forbids dynamic dispatch internals in command-path classes","full_description":"Command dispatch guardrails forbids dynamic dispatch internals in command-path classes","status":"passed","file_path":"./spec/core/architecture/command_dispatch_guardrails_spec.rb","line_number":15,"run_time":0.000409919,"pending_message":null},{"id":"./spec/core/architecture/command_dispatch_guardrails_spec.rb[1:3]","description":"forbids references to removed ContextMethodCommand artifacts","full_description":"Command dispatch guardrails forbids references to removed ContextMethodCommand artifacts","status":"passed","file_path":"./spec/core/architecture/command_dispatch_guardrails_spec.rb","line_number":48,"run_time":0.059337069,"pending_message":null},{"id":"./spec/core/architecture/command_dispatch_guardrails_spec.rb[1:2]","description":"forbids silent broad rescue patterns in command-path classes","full_description":"Command dispatch guardrails forbids silent broad rescue patterns in command-path classes","status":"passed","file_path":"./spec/core/architecture/command_dispatch_guardrails_spec.rb","line_number":31,"run_time":0.000366006,"pending_message":null},{"id":"./spec/adapters/book_sources/library_scanner_spec.rb[1:2]","description":"shuts down owned executors during cleanup","full_description":"Shoko::Adapters::BookSources::LibraryScanner shuts down owned executors during cleanup","status":"passed","file_path":"./spec/adapters/book_sources/library_scanner_spec.rb","line_number":59,"run_time":0.001289087,"pending_message":null},{"id":"./spec/adapters/book_sources/library_scanner_spec.rb[1:3]","description":"builds owned executor from configured background worker builder","full_description":"Shoko::Adapters::BookSources::LibraryScanner builds owned executor from configured background worker builder","status":"passed","file_path":"./spec/adapters/book_sources/library_scanner_spec.rb","line_number":73,"run_time":0.000198211,"pending_message":null},{"id":"./spec/adapters/book_sources/library_scanner_spec.rb[1:1]","description":"submits scan work to the provided executor","full_description":"Shoko::Adapters::BookSources::LibraryScanner submits scan work to the provided executor","status":"passed","file_path":"./spec/adapters/book_sources/library_scanner_spec.rb","line_number":44,"run_time":0.000157466,"pending_message":null},{"id":"./spec/adapters/support/lifecycle_helpers_spec.rb[1:3]","description":"builds sanitized fallback titles with compound suffix and parenthetical trimming","full_description":"Shoko::Adapters::Support::LifecycleHelpers builds sanitized fallback titles with compound suffix and parenthetical trimming","status":"passed","file_path":"./spec/adapters/support/lifecycle_helpers_spec.rb","line_number":65,"run_time":0.000160651,"pending_message":null},{"id":"./spec/adapters/support/lifecycle_helpers_spec.rb[1:2]","description":"uses instrumentation when available and yields directly when missing","full_description":"Shoko::Adapters::Support::LifecycleHelpers uses instrumentation when available and yields directly when missing","status":"passed","file_path":"./spec/adapters/support/lifecycle_helpers_spec.rb","line_number":47,"run_time":0.003762015,"pending_message":null},{"id":"./spec/adapters/support/lifecycle_helpers_spec.rb[1:1]","description":"dispatches report updates to callable progress reporters","full_description":"Shoko::Adapters::Support::LifecycleHelpers dispatches report updates to callable progress reporters","status":"passed","file_path":"./spec/adapters/support/lifecycle_helpers_spec.rb","line_number":29,"run_time":0.000097472,"pending_message":null},{"id":"./spec/adapters/storage/cache_pointer_resolver_spec.rb[1:2]","description":"does not use pointer metadata fallback in strict mode","full_description":"Shoko::Adapters::Storage::CachePointerResolver does not use pointer metadata fallback in strict mode","status":"passed","file_path":"./spec/adapters/storage/cache_pointer_resolver_spec.rb","line_number":38,"run_time":0.000461545,"pending_message":null},{"id":"./spec/adapters/storage/cache_pointer_resolver_spec.rb[1:1]","description":"returns source path fallback from pointer metadata when cache payload is missing","full_description":"Shoko::Adapters::Storage::CachePointerResolver returns source path fallback from pointer metadata when cache payload is missing","status":"passed","file_path":"./spec/adapters/storage/cache_pointer_resolver_spec.rb","line_number":24,"run_time":0.000281788,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_panel_component_spec.rb[1:5:1]","description":"returns close for cancel key","full_description":"Shoko::Adapters::Ui::Components::DictionaryPanelComponent#handle_key returns close for cancel key","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_panel_component_spec.rb","line_number":77,"run_time":0.000153508,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_panel_component_spec.rb[1:1:1]","description":"toggles visibility and resets state","full_description":"Shoko::Adapters::Ui::Components::DictionaryPanelComponent#show and #hide toggles visibility and resets state","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_panel_component_spec.rb","line_number":21,"run_time":0.000720261,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_panel_component_spec.rb[1:2:2]","description":"hides when available width is below minimum","full_description":"Shoko::Adapters::Ui::Components::DictionaryPanelComponent#preferred_width hides when available width is below minimum","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_panel_component_spec.rb","line_number":39,"run_time":0.000083126,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_panel_component_spec.rb[1:2:3]","description":"returns a width when space is available","full_description":"Shoko::Adapters::Ui::Components::DictionaryPanelComponent#preferred_width returns a width when space is available","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_panel_component_spec.rb","line_number":44,"run_time":0.000114825,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_panel_component_spec.rb[1:2:1]","description":"hides the panel when terminal is too narrow","full_description":"Shoko::Adapters::Ui::Components::DictionaryPanelComponent#preferred_width hides the panel when terminal is too narrow","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_panel_component_spec.rb","line_number":34,"run_time":0.000069249,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_panel_component_spec.rb[1:3:1]","description":"cycles through entries when available","full_description":"Shoko::Adapters::Ui::Components::DictionaryPanelComponent#next_entry cycles through entries when available","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_panel_component_spec.rb","line_number":51,"run_time":0.00008043,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_panel_component_spec.rb[1:3:2]","description":"does not advance while in fuzzy mode","full_description":"Shoko::Adapters::Ui::Components::DictionaryPanelComponent#next_entry does not advance while in fuzzy mode","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_panel_component_spec.rb","line_number":58,"run_time":0.000073228,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_panel_component_spec.rb[1:4:1]","description":"toggles fuzzy mode on and off","full_description":"Shoko::Adapters::Ui::Components::DictionaryPanelComponent#toggle_fuzzy toggles fuzzy mode on and off","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_panel_component_spec.rb","line_number":66,"run_time":0.000089969,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/menu_launch_state_adapter_spec.rb[1:1]","description":"stores and clears the last opened path","full_description":"Shoko::Adapters::Runtime::SessionState::MenuLaunchStateAdapter stores and clears the last opened path","status":"passed","file_path":"./spec/adapters/runtime/session_state/menu_launch_state_adapter_spec.rb","line_number":8,"run_time":0.00009059,"pending_message":null},{"id":"./spec/application/unified_application_spec.rb[1:2]","description":"skips preload when cache is available","full_description":"Shoko::Application::UnifiedApplication skips preload when cache is available","status":"passed","file_path":"./spec/application/unified_application_spec.rb","line_number":95,"run_time":0.001308884,"pending_message":null},{"id":"./spec/application/unified_application_spec.rb[1:1]","description":"preloads document before entering the terminal when cache is missing","full_description":"Shoko::Application::UnifiedApplication preloads document before entering the terminal when cache is missing","status":"passed","file_path":"./spec/application/unified_application_spec.rb","line_number":66,"run_time":0.001819051,"pending_message":null},{"id":"./spec/core/architecture/no_implicit_null_runtime_config_spec.rb[1:1]","description":"forbids || NullRuntimeConfig.instance fallback expressions in runtime code","full_description":"No implicit NullRuntimeConfig fallback expressions forbids || NullRuntimeConfig.instance fallback expressions in runtime code","status":"passed","file_path":"./spec/core/architecture/no_implicit_null_runtime_config_spec.rb","line_number":9,"run_time":0.030643503,"pending_message":null},{"id":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb[1:2:2]","description":"strips multibyte overlap when bit 0 is set","full_description":"Shoko::Core::BookFormats::Kindle::PalmdocDecompressor.strip_trailing_data strips multibyte overlap when bit 0 is set","status":"passed","file_path":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb","line_number":66,"run_time":0.000107561,"pending_message":null},{"id":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb[1:2:1]","description":"returns data unchanged when flags are zero","full_description":"Shoko::Core::BookFormats::Kindle::PalmdocDecompressor.strip_trailing_data returns data unchanged when flags are zero","status":"passed","file_path":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb","line_number":61,"run_time":0.0000586,"pending_message":null},{"id":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb[1:2:3]","description":"strips trailing entries when flags >> 1 > 0","full_description":"Shoko::Core::BookFormats::Kindle::PalmdocDecompressor.strip_trailing_data strips trailing entries when flags >> 1 > 0","status":"passed","file_path":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb","line_number":74,"run_time":0.000061705,"pending_message":null},{"id":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb[1:1:5]","description":"decompresses LZ77 back-references correctly","full_description":"Shoko::Core::BookFormats::Kindle::PalmdocDecompressor.decompress decompresses LZ77 back-references correctly","status":"passed","file_path":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb","line_number":31,"run_time":0.000071193,"pending_message":null},{"id":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb[1:1:7]","description":"decompresses real PalmDOC data correctly","full_description":"Shoko::Core::BookFormats::Kindle::PalmdocDecompressor.decompress decompresses real PalmDOC data correctly","status":"passed","file_path":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb","line_number":48,"run_time":0.000057939,"pending_message":null},{"id":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb[1:1:1]","description":"passes through literal ASCII bytes unchanged","full_description":"Shoko::Core::BookFormats::Kindle::PalmdocDecompressor.decompress passes through literal ASCII bytes unchanged","status":"passed","file_path":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb","line_number":7,"run_time":0.000054492,"pending_message":null},{"id":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb[1:1:6]","description":"handles empty input","full_description":"Shoko::Core::BookFormats::Kindle::PalmdocDecompressor.decompress handles empty input","status":"passed","file_path":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb","line_number":44,"run_time":0.000052619,"pending_message":null},{"id":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb[1:1:2]","description":"handles literal NUL bytes","full_description":"Shoko::Core::BookFormats::Kindle::PalmdocDecompressor.decompress handles literal NUL bytes","status":"passed","file_path":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb","line_number":13,"run_time":0.000052799,"pending_message":null},{"id":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb[1:1:3]","description":"handles multi-byte literal copies (0x01-0x08)","full_description":"Shoko::Core::BookFormats::Kindle::PalmdocDecompressor.decompress handles multi-byte literal copies (0x01-0x08)","status":"passed","file_path":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb","line_number":18,"run_time":0.000070112,"pending_message":null},{"id":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb[1:1:4]","description":"handles space encoding (0xC0-0xFF)","full_description":"Shoko::Core::BookFormats::Kindle::PalmdocDecompressor.decompress handles space encoding (0xC0-0xFF)","status":"passed","file_path":"./spec/core/book_formats/kindle/palmdoc_decompressor_spec.rb","line_number":24,"run_time":0.000055585,"pending_message":null},{"id":"./spec/adapters/ui/components/ui/annotation_list_input_spec.rb[1:5]","description":"exits numbered list on empty item","full_description":"Shoko::Adapters::Ui::Components::Ui::AnnotationListInput exits numbered list on empty item","status":"passed","file_path":"./spec/adapters/ui/components/ui/annotation_list_input_spec.rb","line_number":38,"run_time":0.000110528,"pending_message":null},{"id":"./spec/adapters/ui/components/ui/annotation_list_input_spec.rb[1:4]","description":"continues numbered list on enter","full_description":"Shoko::Adapters::Ui::Components::Ui::AnnotationListInput continues numbered list on enter","status":"passed","file_path":"./spec/adapters/ui/components/ui/annotation_list_input_spec.rb","line_number":30,"run_time":0.000065232,"pending_message":null},{"id":"./spec/adapters/ui/components/ui/annotation_list_input_spec.rb[1:1]","description":"converts dash prefix into bullet when followed by space","full_description":"Shoko::Adapters::Ui::Components::Ui::AnnotationListInput converts dash prefix into bullet when followed by space","status":"passed","file_path":"./spec/adapters/ui/components/ui/annotation_list_input_spec.rb","line_number":6,"run_time":0.000064921,"pending_message":null},{"id":"./spec/adapters/ui/components/ui/annotation_list_input_spec.rb[1:2]","description":"continues bullet list on enter","full_description":"Shoko::Adapters::Ui::Components::Ui::AnnotationListInput continues bullet list on enter","status":"passed","file_path":"./spec/adapters/ui/components/ui/annotation_list_input_spec.rb","line_number":14,"run_time":0.000062958,"pending_message":null},{"id":"./spec/adapters/ui/components/ui/annotation_list_input_spec.rb[1:3]","description":"exits bullet list on empty item","full_description":"Shoko::Adapters::Ui::Components::Ui::AnnotationListInput exits bullet list on empty item","status":"passed","file_path":"./spec/adapters/ui/components/ui/annotation_list_input_spec.rb","line_number":22,"run_time":0.000063559,"pending_message":null},{"id":"./spec/adapters/storage/book_cache_pipeline/stage_components_spec.rb[1:5:1]","description":"returns in-memory payload when import succeeds but cache payload cannot be read back","full_description":"Shoko::Adapters::Storage::BookCachePipeline CacheSession fallback payload returns in-memory payload when import succeeds but cache payload cannot be read back","status":"passed","file_path":"./spec/adapters/storage/book_cache_pipeline/stage_components_spec.rb","line_number":215,"run_time":0.000455685,"pending_message":null},{"id":"./spec/adapters/storage/book_cache_pipeline/stage_components_spec.rb[1:2:2]","description":"returns nil when fingerprint is required but computed fingerprint is blank","full_description":"Shoko::Adapters::Storage::BookCachePipeline ManifestShaFinder returns nil when fingerprint is required but computed fingerprint is blank","status":"passed","file_path":"./spec/adapters/storage/book_cache_pipeline/stage_components_spec.rb","line_number":76,"run_time":0.000460845,"pending_message":null},{"id":"./spec/adapters/storage/book_cache_pipeline/stage_components_spec.rb[1:2:1]","description":"returns the same SHA with fast scan on and off","full_description":"Shoko::Adapters::Storage::BookCachePipeline ManifestShaFinder returns the same SHA with fast scan on and off","status":"passed","file_path":"./spec/adapters/storage/book_cache_pipeline/stage_components_spec.rb","line_number":33,"run_time":0.000236373,"pending_message":null},{"id":"./spec/adapters/storage/book_cache_pipeline/stage_components_spec.rb[1:3:1]","description":"returns nil when pointer source is not a valid source file","full_description":"Shoko::Adapters::Storage::BookCachePipeline PointerRebuilder returns nil when pointer source is not a valid source file","status":"passed","file_path":"./spec/adapters/storage/book_cache_pipeline/stage_components_spec.rb","line_number":136,"run_time":0.000080351,"pending_message":null},{"id":"./spec/adapters/storage/book_cache_pipeline/stage_components_spec.rb[1:4:1]","description":"removes stale pointer cache file when rebuilt path changes","full_description":"Shoko::Adapters::Storage::BookCachePipeline PointerCacheCleaner removes stale pointer cache file when rebuilt path changes","status":"passed","file_path":"./spec/adapters/storage/book_cache_pipeline/stage_components_spec.rb","line_number":149,"run_time":0.000231234,"pending_message":null},{"id":"./spec/adapters/storage/book_cache_pipeline/stage_components_spec.rb[1:1:1]","description":"drops fingerprinted rows when computed fingerprint is blank","full_description":"Shoko::Adapters::Storage::BookCachePipeline FingerprintFilter drops fingerprinted rows when computed fingerprint is blank","status":"passed","file_path":"./spec/adapters/storage/book_cache_pipeline/stage_components_spec.rb","line_number":14,"run_time":0.000287529,"pending_message":null},{"id":"./spec/adapters/output/formatting/formatting_service_spec.rb[1:5]","description":"keeps mixed-italic body lines in paragraph flow after chapter heading","full_description":"Shoko::Adapters::Output::Formatting::FormattingService keeps mixed-italic body lines in paragraph flow after chapter heading","status":"passed","file_path":"./spec/adapters/output/formatting/formatting_service_spec.rb","line_number":173,"run_time":0.001556128,"pending_message":null},{"id":"./spec/adapters/output/formatting/formatting_service_spec.rb[1:2]","description":"keeps centered and right-aligned PDF blocks aligned in wrapped output","full_description":"Shoko::Adapters::Output::Formatting::FormattingService keeps centered and right-aligned PDF blocks aligned in wrapped output","status":"passed","file_path":"./spec/adapters/output/formatting/formatting_service_spec.rb","line_number":54,"run_time":0.001089694,"pending_message":null},{"id":"./spec/adapters/output/formatting/formatting_service_spec.rb[1:1]","description":"wraps chapter content into display lines","full_description":"Shoko::Adapters::Output::Formatting::FormattingService wraps chapter content into display lines","status":"passed","file_path":"./spec/adapters/output/formatting/formatting_service_spec.rb","line_number":9,"run_time":0.001069235,"pending_message":null},{"id":"./spec/adapters/output/formatting/formatting_service_spec.rb[1:4]","description":"renders centered PDF attribution signatures as attribution paragraphs, not headings","full_description":"Shoko::Adapters::Output::Formatting::FormattingService renders centered PDF attribution signatures as attribution paragraphs, not headings","status":"passed","file_path":"./spec/adapters/output/formatting/formatting_service_spec.rb","line_number":126,"run_time":0.001126863,"pending_message":null},{"id":"./spec/adapters/output/formatting/formatting_service_spec.rb[1:3]","description":"formats cached PDF chapters with string metadata keys without leaking raw JSON","full_description":"Shoko::Adapters::Output::Formatting::FormattingService formats cached PDF chapters with string metadata keys without leaking raw JSON","status":"passed","file_path":"./spec/adapters/output/formatting/formatting_service_spec.rb","line_number":89,"run_time":0.0017254150000000001,"pending_message":null},{"id":"./spec/adapters/output/formatting/formatting_service_spec.rb[1:6]","description":"renders mixed-case epigraph attributions as attribution paragraphs","full_description":"Shoko::Adapters::Output::Formatting::FormattingService renders mixed-case epigraph attributions as attribution paragraphs","status":"passed","file_path":"./spec/adapters/output/formatting/formatting_service_spec.rb","line_number":216,"run_time":0.001771853,"pending_message":null},{"id":"./spec/core/architecture/command_bus_guardrails_spec.rb[1:1]","description":"keeps semantic commands disjoint from intent command namespaces","full_description":"Command bus guardrails keeps semantic commands disjoint from intent command namespaces","status":"passed","file_path":"./spec/core/architecture/command_bus_guardrails_spec.rb","line_number":15,"run_time":0.000078798,"pending_message":null},{"id":"./spec/core/architecture/command_bus_guardrails_spec.rb[1:4]","description":"requires intent commands to be referenced by input adapters","full_description":"Command bus guardrails requires intent commands to be referenced by input adapters","status":"passed","file_path":"./spec/core/architecture/command_bus_guardrails_spec.rb","line_number":48,"run_time":0.162518405,"pending_message":null},{"id":"./spec/core/architecture/command_bus_guardrails_spec.rb[1:3]","description":"forbids legacy reflective passthrough command artifacts","full_description":"Command bus guardrails forbids legacy reflective passthrough command artifacts","status":"passed","file_path":"./spec/core/architecture/command_bus_guardrails_spec.rb","line_number":38,"run_time":0.000299171,"pending_message":null},{"id":"./spec/core/architecture/command_bus_guardrails_spec.rb[1:2]","description":"routes shared reader/menu symbols through explicit shared intent symbols","full_description":"Command bus guardrails routes shared reader/menu symbols through explicit shared intent symbols","status":"passed","file_path":"./spec/core/architecture/command_bus_guardrails_spec.rb","line_number":29,"run_time":0.00014962,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/observer_state_store_spec.rb[1:2]","description":"notifies observers for parent paths","full_description":"Shoko::Adapters::Runtime::SessionState::ObserverStateStore notifies observers for parent paths","status":"passed","file_path":"./spec/adapters/runtime/session_state/observer_state_store_spec.rb","line_number":50,"run_time":0.001560466,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/observer_state_store_spec.rb[1:5]","description":"loads config values even when optional symbol fields are nil","full_description":"Shoko::Adapters::Runtime::SessionState::ObserverStateStore loads config values even when optional symbol fields are nil","status":"passed","file_path":"./spec/adapters/runtime/session_state/observer_state_store_spec.rb","line_number":86,"run_time":0.000347562,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/observer_state_store_spec.rb[1:3]","description":"notifies a path observer only once when using set","full_description":"Shoko::Adapters::Runtime::SessionState::ObserverStateStore notifies a path observer only once when using set","status":"passed","file_path":"./spec/adapters/runtime/session_state/observer_state_store_spec.rb","line_number":62,"run_time":0.000420549,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/observer_state_store_spec.rb[1:6]","description":"keeps valid config values when others are invalid","full_description":"Shoko::Adapters::Runtime::SessionState::ObserverStateStore keeps valid config values when others are invalid","status":"passed","file_path":"./spec/adapters/runtime/session_state/observer_state_store_spec.rb","line_number":97,"run_time":0.000352771,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/observer_state_store_spec.rb[1:4]","description":"does not notify observers when set is a no-op","full_description":"Shoko::Adapters::Runtime::SessionState::ObserverStateStore does not notify observers when set is a no-op","status":"passed","file_path":"./spec/adapters/runtime/session_state/observer_state_store_spec.rb","line_number":74,"run_time":0.00036238,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/observer_state_store_spec.rb[1:1]","description":"notifies observers for specific paths","full_description":"Shoko::Adapters::Runtime::SessionState::ObserverStateStore notifies observers for specific paths","status":"passed","file_path":"./spec/adapters/runtime/session_state/observer_state_store_spec.rb","line_number":38,"run_time":0.000412513,"pending_message":null},{"id":"./spec/core/architecture/catalog_scan_state_guardrails_spec.rb[1:1]","description":"forbids direct scan_status/scan_message mutation outside catalog service","full_description":"Catalog scan-state guardrails forbids direct scan_status/scan_message mutation outside catalog service","status":"passed","file_path":"./spec/core/architecture/catalog_scan_state_guardrails_spec.rb","line_number":12,"run_time":0.010474873,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch/progress_orchestration_spec.rb[1:1]","description":"runs launch flow with progress overlay and clears presenter","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunch::ProgressOrchestration runs launch flow with progress overlay and clears presenter","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch/progress_orchestration_spec.rb","line_number":47,"run_time":0.000602039,"pending_message":null},{"id":"./spec/adapters/runtime/app_mode_runner_adapter_spec.rb[1:1]","description":"runs reader mode through reader builder","full_description":"Shoko::Adapters::Runtime::AppModeRunnerAdapter runs reader mode through reader builder","status":"passed","file_path":"./spec/adapters/runtime/app_mode_runner_adapter_spec.rb","line_number":18,"run_time":0.000274795,"pending_message":null},{"id":"./spec/adapters/runtime/app_mode_runner_adapter_spec.rb[1:2]","description":"runs menu mode through menu builder","full_description":"Shoko::Adapters::Runtime::AppModeRunnerAdapter runs menu mode through menu builder","status":"passed","file_path":"./spec/adapters/runtime/app_mode_runner_adapter_spec.rb","line_number":27,"run_time":0.000250269,"pending_message":null},{"id":"./spec/core/book_formats/fb2/metadata_parser_spec.rb[1:1:1]","description":"extracts canonical metadata from FB2 title-info","full_description":"Shoko::Core::BookFormats::Fb2::MetadataParser.parse_document extracts canonical metadata from FB2 title-info","status":"passed","file_path":"./spec/core/book_formats/fb2/metadata_parser_spec.rb","line_number":31,"run_time":0.001195552,"pending_message":null},{"id":"./spec/core/book_formats/fb2/metadata_parser_spec.rb[1:2:2]","description":"is used by Fb2Importer metadata extraction","full_description":"Shoko::Core::BookFormats::Fb2::MetadataParser delegation is used by Fb2Importer metadata extraction","status":"passed","file_path":"./spec/core/book_formats/fb2/metadata_parser_spec.rb","line_number":66,"run_time":0.000684373,"pending_message":null},{"id":"./spec/core/book_formats/fb2/metadata_parser_spec.rb[1:2:1]","description":"is used by Fb2MetadataExtractor and preserves extractor output shape","full_description":"Shoko::Core::BookFormats::Fb2::MetadataParser delegation is used by Fb2MetadataExtractor and preserves extractor output shape","status":"passed","file_path":"./spec/core/book_formats/fb2/metadata_parser_spec.rb","line_number":46,"run_time":0.000505518,"pending_message":null},{"id":"./spec/core/architecture/constructor_dependency_budget_spec.rb[1:1]","description":"limits constructor arity in controller and wiring classes","full_description":"Constructor dependency budget limits constructor arity in controller and wiring classes","status":"passed","file_path":"./spec/core/architecture/constructor_dependency_budget_spec.rb","line_number":158,"run_time":0.080106496,"pending_message":null},{"id":"./spec/core/architecture/constructor_dependency_budget_spec.rb[1:2]","description":"keeps critical dependency objects bounded and cohesive","full_description":"Constructor dependency budget keeps critical dependency objects bounded and cohesive","status":"passed","file_path":"./spec/core/architecture/constructor_dependency_budget_spec.rb","line_number":173,"run_time":0.000130354,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/menu_workflow_bridges_spec.rb[4:1]","description":"delegates reader launch to menu state controller","full_description":"Shoko::Adapters::Input::Controllers::Menu::ReaderRunnerBridge delegates reader launch to menu state controller","status":"passed","file_path":"./spec/adapters/input/controllers/menu/menu_workflow_bridges_spec.rb","line_number":66,"run_time":0.000314951,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_migration_guardrails_spec.rb[1:3]","description":"forbids reflection-style collaborator probing in CLI workflows","full_description":"Hexagonal migration guardrails forbids reflection-style collaborator probing in CLI workflows","status":"passed","file_path":"./spec/core/architecture/hexagonal_migration_guardrails_spec.rb","line_number":132,"run_time":0.000294753,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_migration_guardrails_spec.rb[1:6]","description":"forbids synthetic error-document fallbacks in book loading pipeline","full_description":"Hexagonal migration guardrails forbids synthetic error-document fallbacks in book loading pipeline","status":"passed","file_path":"./spec/core/architecture/hexagonal_migration_guardrails_spec.rb","line_number":172,"run_time":0.000403356,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_migration_guardrails_spec.rb[1:2]","description":"forbids callback-style pagination rendering hooks in application layer","full_description":"Hexagonal migration guardrails forbids callback-style pagination rendering hooks in application layer","status":"passed","file_path":"./spec/core/architecture/hexagonal_migration_guardrails_spec.rb","line_number":111,"run_time":0.002924453,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_migration_guardrails_spec.rb[1:8]","description":"forbids untyped collaborator validation patterns in workflow constructors","full_description":"Hexagonal migration guardrails forbids untyped collaborator validation patterns in workflow constructors","status":"passed","file_path":"./spec/core/architecture/hexagonal_migration_guardrails_spec.rb","line_number":233,"run_time":0.000924483,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_migration_guardrails_spec.rb[1:4]","description":"forbids backend-specific error-string diagnosis in core dictionary service","full_description":"Hexagonal migration guardrails forbids backend-specific error-string diagnosis in core dictionary service","status":"passed","file_path":"./spec/core/architecture/hexagonal_migration_guardrails_spec.rb","line_number":141,"run_time":0.000233418,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_migration_guardrails_spec.rb[1:7]","description":"enforces broad-rescue policy in hardening scope (strict core/app + allowlisted boundaries only)","full_description":"Hexagonal migration guardrails enforces broad-rescue policy in hardening scope (strict core/app + allowlisted boundaries only)","status":"passed","file_path":"./spec/core/architecture/hexagonal_migration_guardrails_spec.rb","line_number":196,"run_time":0.000425518,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_migration_guardrails_spec.rb[1:5]","description":"forbids reflection-based dispatch and collaborator probing in strict migration scope","full_description":"Hexagonal migration guardrails forbids reflection-based dispatch and collaborator probing in strict migration scope","status":"passed","file_path":"./spec/core/architecture/hexagonal_migration_guardrails_spec.rb","line_number":157,"run_time":0.024304757,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_migration_guardrails_spec.rb[1:1]","description":"requires split pagination session keywords in application orchestrator callsites (AST)","full_description":"Hexagonal migration guardrails requires split pagination session keywords in application orchestrator callsites (AST)","status":"passed","file_path":"./spec/core/architecture/hexagonal_migration_guardrails_spec.rb","line_number":103,"run_time":0.048543018,"pending_message":null},{"id":"./spec/adapters/input/controllers/reader/lifecycle_runner_spec.rb[1:2]","description":"builds background worker with logger and upgrades inline async executor","full_description":"Shoko::Adapters::Input::Controllers::Reader::LifecycleRunner builds background worker with logger and upgrades inline async executor","status":"passed","file_path":"./spec/adapters/input/controllers/reader/lifecycle_runner_spec.rb","line_number":48,"run_time":0.000220764,"pending_message":null},{"id":"./spec/adapters/input/controllers/reader/lifecycle_runner_spec.rb[1:1]","description":"reuses async executor when it already behaves like a background worker","full_description":"Shoko::Adapters::Input::Controllers::Reader::LifecycleRunner reuses async executor when it already behaves like a background worker","status":"passed","file_path":"./spec/adapters/input/controllers/reader/lifecycle_runner_spec.rb","line_number":27,"run_time":0.000085651,"pending_message":null},{"id":"./spec/adapters/input/controllers/reader/lifecycle_runner_spec.rb[1:3]","description":"raises when no builder is configured and async executor is not reusable","full_description":"Shoko::Adapters::Input::Controllers::Reader::LifecycleRunner raises when no builder is configured and async executor is not reusable","status":"passed","file_path":"./spec/adapters/input/controllers/reader/lifecycle_runner_spec.rb","line_number":65,"run_time":0.000823004,"pending_message":null},{"id":"./spec/core/models/dictionary_entry_spec.rb[2:1]","description":"reports found results when entries are present","full_description":"Shoko::Core::Models::DictionaryResult reports found results when entries are present","status":"passed","file_path":"./spec/core/models/dictionary_entry_spec.rb","line_number":75,"run_time":0.000117019,"pending_message":null},{"id":"./spec/core/models/dictionary_entry_spec.rb[2:2]","description":"reports empty when entries are missing or empty","full_description":"Shoko::Core::Models::DictionaryResult reports empty when entries are missing or empty","status":"passed","file_path":"./spec/core/models/dictionary_entry_spec.rb","line_number":81,"run_time":0.000072987,"pending_message":null},{"id":"./spec/adapters/ui/sessions/annotation_editor_launcher_adapter_spec.rb[1:1]","description":"delegates editor opening to annotation overlay session","full_description":"Shoko::Adapters::Ui::Sessions::AnnotationEditorLauncherAdapter delegates editor opening to annotation overlay session","status":"passed","file_path":"./spec/adapters/ui/sessions/annotation_editor_launcher_adapter_spec.rb","line_number":9,"run_time":0.00023459,"pending_message":null},{"id":"./spec/adapters/input/reader_input_controller_spec.rb[1:2:1]","description":"dispatches 'b' to add_bookmark","full_description":"Shoko::Adapters::Input::ReaderInputController read-mode bookmark binding dispatches 'b' to add_bookmark","status":"passed","file_path":"./spec/adapters/input/reader_input_controller_spec.rb","line_number":98,"run_time":0.000358141,"pending_message":null},{"id":"./spec/adapters/input/reader_input_controller_spec.rb[1:1:1]","description":"dispatches 'q' to quit_to_menu","full_description":"Shoko::Adapters::Input::ReaderInputController read-mode quit binding dispatches 'q' to quit_to_menu","status":"passed","file_path":"./spec/adapters/input/reader_input_controller_spec.rb","line_number":56,"run_time":0.00021834,"pending_message":null},{"id":"./spec/adapters/input/reader_input_controller_spec.rb[1:3:2]","description":"does not fall through to read bindings while in dictionary mode","full_description":"Shoko::Adapters::Input::ReaderInputController modal isolation does not fall through to read bindings while in dictionary mode","status":"passed","file_path":"./spec/adapters/input/reader_input_controller_spec.rb","line_number":192,"run_time":0.000179697,"pending_message":null},{"id":"./spec/adapters/input/reader_input_controller_spec.rb[1:3:3]","description":"does not fall through to read bindings while in in-book search mode","full_description":"Shoko::Adapters::Input::ReaderInputController modal isolation does not fall through to read bindings while in in-book search mode","status":"passed","file_path":"./spec/adapters/input/reader_input_controller_spec.rb","line_number":208,"run_time":0.000160611,"pending_message":null},{"id":"./spec/adapters/input/reader_input_controller_spec.rb[1:3:1]","description":"does not fall through to read bindings while in annotation editor mode","full_description":"Shoko::Adapters::Input::ReaderInputController modal isolation does not fall through to read bindings while in annotation editor mode","status":"passed","file_path":"./spec/adapters/input/reader_input_controller_spec.rb","line_number":176,"run_time":0.000171151,"pending_message":null},{"id":"./spec/core/book_formats/pdf/metadata_parser_spec.rb[1:2:2]","description":"is used by PdfImporter metadata extraction and preserves author_str","full_description":"Shoko::Core::BookFormats::Pdf::MetadataParser delegation is used by PdfImporter metadata extraction and preserves author_str","status":"passed","file_path":"./spec/core/book_formats/pdf/metadata_parser_spec.rb","line_number":58,"run_time":0.000713638,"pending_message":null},{"id":"./spec/core/book_formats/pdf/metadata_parser_spec.rb[1:2:1]","description":"is used by PdfMetadataExtractor and preserves extractor output shape","full_description":"Shoko::Core::BookFormats::Pdf::MetadataParser delegation is used by PdfMetadataExtractor and preserves extractor output shape","status":"passed","file_path":"./spec/core/book_formats/pdf/metadata_parser_spec.rb","line_number":27,"run_time":0.000726132,"pending_message":null},{"id":"./spec/core/book_formats/pdf/metadata_parser_spec.rb[1:1:1]","description":"normalizes PDF info fields into canonical metadata keys","full_description":"Shoko::Core::BookFormats::Pdf::MetadataParser.parse normalizes PDF info fields into canonical metadata keys","status":"passed","file_path":"./spec/core/book_formats/pdf/metadata_parser_spec.rb","line_number":10,"run_time":0.000085721,"pending_message":null},{"id":"./spec/core/architecture/zero_fallback_completion_spec.rb[1:3]","description":"forbids controller loopback in application intent handlers","full_description":"Zero fallback completion guardrails forbids controller loopback in application intent handlers","status":"passed","file_path":"./spec/core/architecture/zero_fallback_completion_spec.rb","line_number":45,"run_time":0.000164569,"pending_message":null},{"id":"./spec/core/architecture/zero_fallback_completion_spec.rb[1:2]","description":"forbids inline rescue expressions across runtime code","full_description":"Zero fallback completion guardrails forbids inline rescue expressions across runtime code","status":"passed","file_path":"./spec/core/architecture/zero_fallback_completion_spec.rb","line_number":27,"run_time":0.027734748,"pending_message":null},{"id":"./spec/core/architecture/zero_fallback_completion_spec.rb[1:4]","description":"forbids bootstrap session-context coupling in application layer","full_description":"Zero fallback completion guardrails forbids bootstrap session-context coupling in application layer","status":"passed","file_path":"./spec/core/architecture/zero_fallback_completion_spec.rb","line_number":56,"run_time":0.00396268,"pending_message":null},{"id":"./spec/core/architecture/zero_fallback_completion_spec.rb[1:5]","description":"enforces symbol-only command execution contract","full_description":"Zero fallback completion guardrails enforces symbol-only command execution contract","status":"passed","file_path":"./spec/core/architecture/zero_fallback_completion_spec.rb","line_number":65,"run_time":0.000164889,"pending_message":null},{"id":"./spec/core/architecture/zero_fallback_completion_spec.rb[1:1]","description":"forbids bare rescue assignment syntax across runtime code","full_description":"Zero fallback completion guardrails forbids bare rescue assignment syntax across runtime code","status":"passed","file_path":"./spec/core/architecture/zero_fallback_completion_spec.rb","line_number":20,"run_time":0.037038976,"pending_message":null},{"id":"./spec/adapters/input/controllers/annotation_overlay_controller_spec.rb[1:2]","description":"saves annotation when editor session returns a save event payload","full_description":"Shoko::Adapters::Input::Controllers::AnnotationOverlayController saves annotation when editor session returns a save event payload","status":"passed","file_path":"./spec/adapters/input/controllers/annotation_overlay_controller_spec.rb","line_number":33,"run_time":0.000870152,"pending_message":null},{"id":"./spec/adapters/input/controllers/annotation_overlay_controller_spec.rb[1:1]","description":"ignores non-hash editor payloads from session outcomes","full_description":"Shoko::Adapters::Input::Controllers::AnnotationOverlayController ignores non-hash editor payloads from session outcomes","status":"passed","file_path":"./spec/adapters/input/controllers/annotation_overlay_controller_spec.rb","line_number":20,"run_time":0.000429486,"pending_message":null},{"id":"./spec/application/use_cases/commands/bookmark_command_spec.rb[1:1]","description":"executes add bookmark when bookmark_service is present","full_description":"Shoko::Application::UseCases::Commands::BookmarkCommandFactory executes add bookmark when bookmark_service is present","status":"passed","file_path":"./spec/application/use_cases/commands/bookmark_command_spec.rb","line_number":6,"run_time":0.000202019,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_metadata_extractor_spec.rb[1:1:2]","description":"raises malformed metadata error for non-existent file","full_description":"Shoko::Core::BookFormats::Rtf::RtfMetadataExtractor.from_file raises malformed metadata error for non-existent file","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_metadata_extractor_spec.rb","line_number":74,"run_time":0.000185016,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_metadata_extractor_spec.rb[1:1:3]","description":"raises malformed metadata error for invalid file","full_description":"Shoko::Core::BookFormats::Rtf::RtfMetadataExtractor.from_file raises malformed metadata error for invalid file","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_metadata_extractor_spec.rb","line_number":79,"run_time":0.000389781,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:33]","description":"handles first line indent","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles first line indent","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":284,"run_time":0.000696136,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:6]","description":"handles underline formatting","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles underline formatting","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":54,"run_time":0.000119063,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:2]","description":"handles bold formatting","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles bold formatting","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":16,"run_time":0.000157866,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:3]","description":"turns bold off with \\b0","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse turns bold off with \\b0","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":26,"run_time":0.000102933,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:32]","description":"handles tab characters","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles tab characters","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":276,"run_time":0.000120757,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:15]","description":"handles negative Unicode values","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles negative Unicode values","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":132,"run_time":0.000086963,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:10]","description":"handles emdash named character","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles emdash named character","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":90,"run_time":0.000097222,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:13]","description":"handles hex escapes with CP1252","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles hex escapes with CP1252","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":115,"run_time":0.000761408,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:11]","description":"handles endash named character","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles endash named character","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":98,"run_time":0.000098555,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:9]","description":"handles paragraph breaks","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles paragraph breaks","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":81,"run_time":0.000119905,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:30]","description":"handles literal backslash","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles literal backslash","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":260,"run_time":0.000088646,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:12]","description":"handles smart quotes","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles smart quotes","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":106,"run_time":0.000094828,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:4]","description":"handles italic formatting","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles italic formatting","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":35,"run_time":0.000166282,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:21]","description":"handles justify alignment","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles justify alignment","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":182,"run_time":0.000124694,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:18]","description":"parses info block metadata","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse parses info block metadata","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":160,"run_time":0.000115747,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:23]","description":"handles \\plain reset","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles \\plain reset","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":197,"run_time":0.000112701,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:25]","description":"skips picture destinations","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse skips picture destinations","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":215,"run_time":0.000094717,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:16]","description":"parses font table","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse parses font table","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":141,"run_time":0.000096541,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:14]","description":"handles Unicode escapes","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles Unicode escapes","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":123,"run_time":0.000094688,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:27]","description":"handles page break markers","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles page break markers","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":235,"run_time":0.000106139,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:19]","description":"parses info creation date","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse parses info creation date","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":168,"run_time":0.000123301,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:7]","description":"handles strikethrough formatting","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles strikethrough formatting","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":62,"run_time":0.000085761,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:28]","description":"handles empty input gracefully","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles empty input gracefully","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":243,"run_time":0.000087013,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:8]","description":"handles superscript and subscript","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles superscript and subscript","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":70,"run_time":0.000109225,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:20]","description":"handles center alignment","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles center alignment","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":175,"run_time":0.000082474,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:5]","description":"handles nested bold and italic","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles nested bold and italic","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":45,"run_time":0.000116188,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:29]","description":"handles literal braces","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles literal braces","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":251,"run_time":0.000100408,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:22]","description":"handles font size","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles font size","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":189,"run_time":0.000113653,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:24]","description":"handles \\pard paragraph reset","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles \\pard paragraph reset","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":207,"run_time":0.000122319,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:31]","description":"handles non-breaking space","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse handles non-breaking space","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":268,"run_time":0.000082334,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:17]","description":"parses color table","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse parses color table","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":149,"run_time":0.000136696,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:1]","description":"parses minimal RTF document","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse parses minimal RTF document","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":7,"run_time":0.000120316,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_parser_spec.rb[1:1:26]","description":"skips ignorable destinations with \\*","full_description":"Shoko::Core::BookFormats::Rtf::RtfParser#parse skips ignorable destinations with \\*","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_parser_spec.rb","line_number":225,"run_time":0.000096992,"pending_message":null},{"id":"./spec/zip/size_limits_spec.rb[1:1]","description":"raises when entry sizes exceed limits","full_description":"Zip::SizeLimits raises when entry sizes exceed limits","status":"passed","file_path":"./spec/zip/size_limits_spec.rb","line_number":6,"run_time":0.00014406,"pending_message":null},{"id":"./spec/core/ports/inbound/menu_intent_handler_spec.rb[1:2]","description":"raises NotImplementedError for unimplemented methods by default","full_description":"Shoko::Core::Ports::Inbound::MenuIntentHandler raises NotImplementedError for unimplemented methods by default","status":"passed","file_path":"./spec/core/ports/inbound/menu_intent_handler_spec.rb","line_number":78,"run_time":0.000123872,"pending_message":null},{"id":"./spec/core/ports/inbound/menu_intent_handler_spec.rb[1:1]","description":"defines explicit menu intent symbols","full_description":"Shoko::Core::Ports::Inbound::MenuIntentHandler defines explicit menu intent symbols","status":"passed","file_path":"./spec/core/ports/inbound/menu_intent_handler_spec.rb","line_number":12,"run_time":0.000072375,"pending_message":null},{"id":"./spec/adapters/output/formatting/line_assembler_spec.rb[1:1]","description":"tokenizes newlines into explicit newline tokens","full_description":"Shoko::Adapters::Output::Formatting::FormattingService::LineAssembler tokenizes newlines into explicit newline tokens","status":"passed","file_path":"./spec/adapters/output/formatting/line_assembler_spec.rb","line_number":29,"run_time":0.000393699,"pending_message":null},{"id":"./spec/adapters/output/formatting/line_assembler_spec.rb[1:7]","description":"splits oversized tokens so lines stay within width constraints","full_description":"Shoko::Adapters::Output::Formatting::FormattingService::LineAssembler splits oversized tokens so lines stay within width constraints","status":"passed","file_path":"./spec/adapters/output/formatting/line_assembler_spec.rb","line_number":110,"run_time":0.000392246,"pending_message":null},{"id":"./spec/adapters/output/formatting/line_assembler_spec.rb[1:9]","description":"renders table blocks using box drawing glyphs","full_description":"Shoko::Adapters::Output::Formatting::FormattingService::LineAssembler renders table blocks using box drawing glyphs","status":"passed","file_path":"./spec/adapters/output/formatting/line_assembler_spec.rb","line_number":146,"run_time":0.001094623,"pending_message":null},{"id":"./spec/adapters/output/formatting/line_assembler_spec.rb[1:2]","description":"returns the same tokens with tokenize cache enabled and disabled","full_description":"Shoko::Adapters::Output::Formatting::FormattingService::LineAssembler returns the same tokens with tokenize cache enabled and disabled","status":"passed","file_path":"./spec/adapters/output/formatting/line_assembler_spec.rb","line_number":35,"run_time":0.000472967,"pending_message":null},{"id":"./spec/adapters/output/formatting/line_assembler_spec.rb[1:4]","description":"produces identical wrapped output with token width hints enabled and disabled","full_description":"Shoko::Adapters::Output::Formatting::FormattingService::LineAssembler produces identical wrapped output with token width hints enabled and disabled","status":"passed","file_path":"./spec/adapters/output/formatting/line_assembler_spec.rb","line_number":67,"run_time":0.000451807,"pending_message":null},{"id":"./spec/adapters/output/formatting/line_assembler_spec.rb[1:12]","description":"keeps multiline centered quote bars vertically aligned","full_description":"Shoko::Adapters::Output::Formatting::FormattingService::LineAssembler keeps multiline centered quote bars vertically aligned","status":"passed","file_path":"./spec/adapters/output/formatting/line_assembler_spec.rb","line_number":212,"run_time":0.000652153,"pending_message":null},{"id":"./spec/adapters/output/formatting/line_assembler_spec.rb[1:5]","description":"creates image tokens when inline image rendering is enabled","full_description":"Shoko::Adapters::Output::Formatting::FormattingService::LineAssembler creates image tokens when inline image rendering is enabled","status":"passed","file_path":"./spec/adapters/output/formatting/line_assembler_spec.rb","line_number":92,"run_time":0.000136946,"pending_message":null},{"id":"./spec/adapters/output/formatting/line_assembler_spec.rb[1:3]","description":"reuses frozen tokenized output when tokenize cache is enabled","full_description":"Shoko::Adapters::Output::Formatting::FormattingService::LineAssembler reuses frozen tokenized output when tokenize cache is enabled","status":"passed","file_path":"./spec/adapters/output/formatting/line_assembler_spec.rb","line_number":52,"run_time":0.000209513,"pending_message":null},{"id":"./spec/adapters/output/formatting/line_assembler_spec.rb[1:6]","description":"wraps lines with list prefixes and continuation indentation","full_description":"Shoko::Adapters::Output::Formatting::FormattingService::LineAssembler wraps lines with list prefixes and continuation indentation","status":"passed","file_path":"./spec/adapters/output/formatting/line_assembler_spec.rb","line_number":98,"run_time":0.000244058,"pending_message":null},{"id":"./spec/adapters/output/formatting/line_assembler_spec.rb[1:10]","description":"applies center alignment to paragraph lines","full_description":"Shoko::Adapters::Output::Formatting::FormattingService::LineAssembler applies center alignment to paragraph lines","status":"passed","file_path":"./spec/adapters/output/formatting/line_assembler_spec.rb","line_number":184,"run_time":0.000206958,"pending_message":null},{"id":"./spec/adapters/output/formatting/line_assembler_spec.rb[1:8]","description":"splits tokens that overflow list continuation width","full_description":"Shoko::Adapters::Output::Formatting::FormattingService::LineAssembler splits tokens that overflow list continuation width","status":"passed","file_path":"./spec/adapters/output/formatting/line_assembler_spec.rb","line_number":128,"run_time":0.000254076,"pending_message":null},{"id":"./spec/adapters/output/formatting/line_assembler_spec.rb[1:11]","description":"treats legacy blockquote blocks as quote blocks during wrapping","full_description":"Shoko::Adapters::Output::Formatting::FormattingService::LineAssembler treats legacy blockquote blocks as quote blocks during wrapping","status":"passed","file_path":"./spec/adapters/output/formatting/line_assembler_spec.rb","line_number":198,"run_time":0.000215584,"pending_message":null},{"id":"./spec/application/workflows/cli/folder_import_workflow_spec.rb[1:3:1]","description":"fails fast when importer raises","full_description":"Shoko::Application::Workflows::Cli::FolderImportWorkflow#import fails fast when importer raises","status":"passed","file_path":"./spec/application/workflows/cli/folder_import_workflow_spec.rb","line_number":139,"run_time":0.000209974,"pending_message":null},{"id":"./spec/application/workflows/cli/folder_import_workflow_spec.rb[1:3:2]","description":"returns a report when all imports succeed","full_description":"Shoko::Application::Workflows::Cli::FolderImportWorkflow#import returns a report when all imports succeed","status":"passed","file_path":"./spec/application/workflows/cli/folder_import_workflow_spec.rb","line_number":170,"run_time":0.000087313,"pending_message":null},{"id":"./spec/application/workflows/cli/folder_import_workflow_spec.rb[1:1:2]","description":"rejects importer that does not implement FolderImporter port","full_description":"Shoko::Application::Workflows::Cli::FolderImportWorkflow constructor contracts rejects importer that does not implement FolderImporter port","status":"passed","file_path":"./spec/application/workflows/cli/folder_import_workflow_spec.rb","line_number":81,"run_time":0.000082715,"pending_message":null},{"id":"./spec/application/workflows/cli/folder_import_workflow_spec.rb[1:1:1]","description":"rejects scanner that does not implement FolderScanner port","full_description":"Shoko::Application::Workflows::Cli::FolderImportWorkflow constructor contracts rejects scanner that does not implement FolderScanner port","status":"passed","file_path":"./spec/application/workflows/cli/folder_import_workflow_spec.rb","line_number":72,"run_time":0.00008518,"pending_message":null},{"id":"./spec/application/workflows/cli/folder_import_workflow_spec.rb[1:2:2]","description":"raises contract mismatch when scanner returns non-entry records","full_description":"Shoko::Application::Workflows::Cli::FolderImportWorkflow#discover raises contract mismatch when scanner returns non-entry records","status":"passed","file_path":"./spec/application/workflows/cli/folder_import_workflow_spec.rb","line_number":127,"run_time":0.000083116,"pending_message":null},{"id":"./spec/application/workflows/cli/folder_import_workflow_spec.rb[1:2:1]","description":"normalizes and counts discovered documents by format group","full_description":"Shoko::Application::Workflows::Cli::FolderImportWorkflow#discover normalizes and counts discovered documents by format group","status":"passed","file_path":"./spec/application/workflows/cli/folder_import_workflow_spec.rb","line_number":92,"run_time":0.000102923,"pending_message":null},{"id":"./spec/adapters/book_sources/archive/zip_reader_entries_spec.rb[1:1]","description":"exposes central directory entries through #entries","full_description":"Zip::File exposes central directory entries through #entries","status":"passed","file_path":"./spec/adapters/book_sources/archive/zip_reader_entries_spec.rb","line_number":6,"run_time":0.00038908,"pending_message":null},{"id":"./spec/core/architecture/menu_state_controller_guardrails_spec.rb[1:1]","description":"forbids compatibility shim classes","full_description":"Menu state controller guardrails forbids compatibility shim classes","status":"passed","file_path":"./spec/core/architecture/menu_state_controller_guardrails_spec.rb","line_number":10,"run_time":0.00013160599999999999,"pending_message":null},{"id":"./spec/core/architecture/menu_state_controller_guardrails_spec.rb[1:2]","description":"forbids fallback branches that bypass injected factories","full_description":"Menu state controller guardrails forbids fallback branches that bypass injected factories","status":"passed","file_path":"./spec/core/architecture/menu_state_controller_guardrails_spec.rb","line_number":17,"run_time":0.000104416,"pending_message":null},{"id":"./spec/core/architecture/no_legacy_factory_keys_spec.rb[1:1]","description":"forbids legacy document/background factory key usage in runtime source","full_description":"No legacy factory keys in runtime wiring forbids legacy document/background factory key usage in runtime source","status":"passed","file_path":"./spec/core/architecture/no_legacy_factory_keys_spec.rb","line_number":19,"run_time":0.04622412,"pending_message":null},{"id":"./spec/adapters/ui/components/render_style_spec.rb[1:4]","description":"uses accent color for keyword segments","full_description":"Shoko::Adapters::Ui::Components::RenderStyle uses accent color for keyword segments","status":"passed","file_path":"./spec/adapters/ui/components/render_style_spec.rb","line_number":21,"run_time":0.00013344,"pending_message":null},{"id":"./spec/adapters/ui/components/render_style_spec.rb[1:5]","description":"applies underline and strikethrough ANSI styles when segment styles request them","full_description":"Shoko::Adapters::Ui::Components::RenderStyle applies underline and strikethrough ANSI styles when segment styles request them","status":"passed","file_path":"./spec/adapters/ui/components/render_style_spec.rb","line_number":26,"run_time":0.0000802,"pending_message":null},{"id":"./spec/adapters/ui/components/render_style_spec.rb[1:2]","description":"falls back to primary color when highlighting is disabled","full_description":"Shoko::Adapters::Ui::Components::RenderStyle falls back to primary color when highlighting is disabled","status":"passed","file_path":"./spec/adapters/ui/components/render_style_spec.rb","line_number":11,"run_time":0.000064231,"pending_message":null},{"id":"./spec/adapters/ui/components/render_style_spec.rb[1:3]","description":"treats legacy blockquote metadata as quote styling","full_description":"Shoko::Adapters::Ui::Components::RenderStyle treats legacy blockquote metadata as quote styling","status":"passed","file_path":"./spec/adapters/ui/components/render_style_spec.rb","line_number":16,"run_time":0.000057848,"pending_message":null},{"id":"./spec/adapters/ui/components/render_style_spec.rb[1:1]","description":"uses quote color when highlighting is enabled","full_description":"Shoko::Adapters::Ui::Components::RenderStyle uses quote color when highlighting is enabled","status":"passed","file_path":"./spec/adapters/ui/components/render_style_spec.rb","line_number":6,"run_time":0.000057518,"pending_message":null},{"id":"./spec/adapters/ui/components/render_style_spec.rb[1:6]","description":"renders superscript and subscript styles with transformed glyphs","full_description":"Shoko::Adapters::Ui::Components::RenderStyle renders superscript and subscript styles with transformed glyphs","status":"passed","file_path":"./spec/adapters/ui/components/render_style_spec.rb","line_number":33,"run_time":0.00008534,"pending_message":null},{"id":"./spec/core/architecture/no_stale_optional_resolution_spec.rb[1:1]","description":"forbids optional ternary resolution branches that resolve identically","full_description":"No stale optional resolution scaffolding forbids optional ternary resolution branches that resolve identically","status":"passed","file_path":"./spec/core/architecture/no_stale_optional_resolution_spec.rb","line_number":9,"run_time":0.026179081,"pending_message":null},{"id":"./spec/adapters/input/command_factory_spec.rb[1:5]","description":"builds reader control commands for semantic bookmark action only","full_description":"Shoko::Adapters::Input::CommandFactory builds reader control commands for semantic bookmark action only","status":"passed","file_path":"./spec/adapters/input/command_factory_spec.rb","line_number":88,"run_time":0.000353263,"pending_message":null},{"id":"./spec/adapters/input/command_factory_spec.rb[1:3]","description":"builds exit commands mapped to cancel keys","full_description":"Shoko::Adapters::Input::CommandFactory builds exit commands mapped to cancel keys","status":"passed","file_path":"./spec/adapters/input/command_factory_spec.rb","line_number":76,"run_time":0.00021349,"pending_message":null},{"id":"./spec/adapters/input/command_factory_spec.rb[1:2]","description":"builds menu selection commands that invoke the handler","full_description":"Shoko::Adapters::Input::CommandFactory builds menu selection commands that invoke the handler","status":"passed","file_path":"./spec/adapters/input/command_factory_spec.rb","line_number":66,"run_time":0.000368251,"pending_message":null},{"id":"./spec/adapters/input/command_factory_spec.rb[1:1]","description":"builds navigation commands that update menu selection","full_description":"Shoko::Adapters::Input::CommandFactory builds navigation commands that update menu selection","status":"passed","file_path":"./spec/adapters/input/command_factory_spec.rb","line_number":57,"run_time":0.000602019,"pending_message":null},{"id":"./spec/adapters/input/command_factory_spec.rb[1:4]","description":"builds reader navigation commands for page movement","full_description":"Shoko::Adapters::Input::CommandFactory builds reader navigation commands for page movement","status":"passed","file_path":"./spec/adapters/input/command_factory_spec.rb","line_number":82,"run_time":0.000164559,"pending_message":null},{"id":"./spec/adapters/input/command_factory_spec.rb[1:7]","description":"uses explicit menu state reader/writer from context","full_description":"Shoko::Adapters::Input::CommandFactory uses explicit menu state reader/writer from context","status":"passed","file_path":"./spec/adapters/input/command_factory_spec.rb","line_number":114,"run_time":0.000411632,"pending_message":null},{"id":"./spec/adapters/input/command_factory_spec.rb[1:8]","description":"ignores non-printable input characters","full_description":"Shoko::Adapters::Input::CommandFactory ignores non-printable input characters","status":"passed","file_path":"./spec/adapters/input/command_factory_spec.rb","line_number":123,"run_time":0.000567815,"pending_message":null},{"id":"./spec/adapters/input/command_factory_spec.rb[1:6]","description":"handles text input commands for insert, backspace, and delete","full_description":"Shoko::Adapters::Input::CommandFactory handles text input commands for insert, backspace, and delete","status":"passed","file_path":"./spec/adapters/input/command_factory_spec.rb","line_number":95,"run_time":0.000535675,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_metadata_extractor_spec.rb[1:5]","description":"raises malformed metadata error for invalid file","full_description":"Shoko::Core::BookFormats::Kindle::KindleMetadataExtractor raises malformed metadata error for invalid file","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_metadata_extractor_spec.rb","line_number":70,"run_time":0.000289293,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_metadata_extractor_spec.rb[1:4]","description":"raises malformed metadata error for non-existent file","full_description":"Shoko::Core::BookFormats::Kindle::KindleMetadataExtractor raises malformed metadata error for non-existent file","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_metadata_extractor_spec.rb","line_number":65,"run_time":0.000114134,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/reader_launch_bridges_spec.rb[2:2]","description":"delegates draw_screen and switch_mode to menu","full_description":"Shoko::Adapters::Input::Controllers::Menu::ReaderLaunchRuntimeBridge delegates draw_screen and switch_mode to menu","status":"passed","file_path":"./spec/adapters/input/controllers/menu/reader_launch_bridges_spec.rb","line_number":54,"run_time":0.000358562,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/reader_launch_bridges_spec.rb[2:1]","description":"builds and runs reader controller through the provided builder","full_description":"Shoko::Adapters::Input::Controllers::Menu::ReaderLaunchRuntimeBridge builds and runs reader controller through the provided builder","status":"passed","file_path":"./spec/adapters/input/controllers/menu/reader_launch_bridges_spec.rb","line_number":43,"run_time":0.000199293,"pending_message":null},{"id":"./spec/application/use_cases/reader_intent_handler_spec.rb[1:3]","description":"enforces typed executor dependency","full_description":"Shoko::Application::UseCases::Intents::ReaderIntentHandler enforces typed executor dependency","status":"passed","file_path":"./spec/application/use_cases/reader_intent_handler_spec.rb","line_number":42,"run_time":0.000100168,"pending_message":null},{"id":"./spec/application/use_cases/reader_intent_handler_spec.rb[1:2]","description":"raises for unsupported intents","full_description":"Shoko::Application::UseCases::Intents::ReaderIntentHandler raises for unsupported intents","status":"passed","file_path":"./spec/application/use_cases/reader_intent_handler_spec.rb","line_number":38,"run_time":0.000401062,"pending_message":null},{"id":"./spec/application/use_cases/reader_intent_handler_spec.rb[1:1]","description":"delegates supported intents to the executor","full_description":"Shoko::Application::UseCases::Intents::ReaderIntentHandler delegates supported intents to the executor","status":"passed","file_path":"./spec/application/use_cases/reader_intent_handler_spec.rb","line_number":30,"run_time":0.000084328,"pending_message":null},{"id":"./spec/application/pending_jump_handler_spec.rb[1:1]","description":"applies pending jump using injected services and clears pending payload","full_description":"Shoko::Application::PendingJumpHandler applies pending jump using injected services and clears pending payload","status":"passed","file_path":"./spec/application/pending_jump_handler_spec.rb","line_number":45,"run_time":0.000623069,"pending_message":null},{"id":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb[1:3:1]","description":"opens popup only on right-click press inside selected range and anchors to click position","full_description":"Shoko::Adapters::Input::Controllers::SelectionMouseHandler#handle_popup_context_click opens popup only on right-click press inside selected range and anchors to click position","status":"passed","file_path":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb","line_number":142,"run_time":0.000415819,"pending_message":null},{"id":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb[1:3:2]","description":"does not open popup when right-click is outside selected range","full_description":"Shoko::Adapters::Input::Controllers::SelectionMouseHandler#handle_popup_context_click does not open popup when right-click is outside selected range","status":"passed","file_path":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb","line_number":161,"run_time":0.000488527,"pending_message":null},{"id":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb[1:1:4:2]","description":"returns false when sqlite3 is missing","full_description":"Shoko::Adapters::Input::Controllers::SelectionMouseHandler#dictionary_lookup_available? when dictionary backend is enabled returns false when sqlite3 is missing","status":"passed","file_path":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb","line_number":85,"run_time":0.000071083,"pending_message":null},{"id":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb[1:1:4:1]","description":"returns true when sqlite3 is available","full_description":"Shoko::Adapters::Input::Controllers::SelectionMouseHandler#dictionary_lookup_available? when dictionary backend is enabled returns true when sqlite3 is available","status":"passed","file_path":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb","line_number":81,"run_time":0.000062998,"pending_message":null},{"id":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb[1:1:2:1]","description":"returns true when sqlite3 is installed","full_description":"Shoko::Adapters::Input::Controllers::SelectionMouseHandler#dictionary_lookup_available? when dictionary backend is auto and no databases are present returns true when sqlite3 is installed","status":"passed","file_path":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb","line_number":64,"run_time":0.00006351,"pending_message":null},{"id":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb[1:1:5:1]","description":"returns true when sqlite3 is available","full_description":"Shoko::Adapters::Input::Controllers::SelectionMouseHandler#dictionary_lookup_available? when enabled via environment variable override returns true when sqlite3 is available","status":"passed","file_path":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb","line_number":97,"run_time":0.000064161,"pending_message":null},{"id":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb[1:1:1:1]","description":"returns false even if sqlite3 is installed","full_description":"Shoko::Adapters::Input::Controllers::SelectionMouseHandler#dictionary_lookup_available? when dictionary backend is disabled returns false even if sqlite3 is installed","status":"passed","file_path":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb","line_number":56,"run_time":0.000063089,"pending_message":null},{"id":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb[1:1:3:1]","description":"returns true when sqlite3 is available","full_description":"Shoko::Adapters::Input::Controllers::SelectionMouseHandler#dictionary_lookup_available? when dictionary backend is auto and databases are present returns true when sqlite3 is available","status":"passed","file_path":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb","line_number":73,"run_time":0.000065423,"pending_message":null},{"id":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb[1:2:1]","description":"does not open popup immediately for a non-empty selection","full_description":"Shoko::Adapters::Input::Controllers::SelectionMouseHandler#handle_selection_end does not open popup immediately for a non-empty selection","status":"passed","file_path":"./spec/adapters/input/controllers/selection_mouse_handler_spec.rb","line_number":106,"run_time":0.000304311,"pending_message":null},{"id":"./spec/adapters/ui/components/enhanced_popup_menu_spec.rb[1:4:1]","description":"blends menu text with a tinted backdrop from the underlying row text","full_description":"Shoko::Adapters::Ui::Components::EnhancedPopupMenu glass rendering blends menu text with a tinted backdrop from the underlying row text","status":"passed","file_path":"./spec/adapters/ui/components/enhanced_popup_menu_spec.rb","line_number":130,"run_time":0.000714119,"pending_message":null},{"id":"./spec/adapters/ui/components/enhanced_popup_menu_spec.rb[1:1:1]","description":"omits lookup when dictionary is disabled","full_description":"Shoko::Adapters::Ui::Components::EnhancedPopupMenu default actions omits lookup when dictionary is disabled","status":"passed","file_path":"./spec/adapters/ui/components/enhanced_popup_menu_spec.rb","line_number":26,"run_time":0.000209042,"pending_message":null},{"id":"./spec/adapters/ui/components/enhanced_popup_menu_spec.rb[1:1:2]","description":"includes lookup when dictionary is enabled","full_description":"Shoko::Adapters::Ui::Components::EnhancedPopupMenu default actions includes lookup when dictionary is enabled","status":"passed","file_path":"./spec/adapters/ui/components/enhanced_popup_menu_spec.rb","line_number":35,"run_time":0.000208842,"pending_message":null},{"id":"./spec/adapters/ui/components/enhanced_popup_menu_spec.rb[1:1:3]","description":"includes clipboard action when available","full_description":"Shoko::Adapters::Ui::Components::EnhancedPopupMenu default actions includes clipboard action when available","status":"passed","file_path":"./spec/adapters/ui/components/enhanced_popup_menu_spec.rb","line_number":43,"run_time":0.000227316,"pending_message":null},{"id":"./spec/adapters/ui/components/enhanced_popup_menu_spec.rb[1:3:1]","description":"uses explicit anchor position when provided","full_description":"Shoko::Adapters::Ui::Components::EnhancedPopupMenu positioning uses explicit anchor position when provided","status":"passed","file_path":"./spec/adapters/ui/components/enhanced_popup_menu_spec.rb","line_number":81,"run_time":0.000295444,"pending_message":null},{"id":"./spec/adapters/ui/components/enhanced_popup_menu_spec.rb[1:2:2]","description":"does not change selection when hover stays on same row","full_description":"Shoko::Adapters::Ui::Components::EnhancedPopupMenu#handle_hover does not change selection when hover stays on same row","status":"passed","file_path":"./spec/adapters/ui/components/enhanced_popup_menu_spec.rb","line_number":67,"run_time":0.000417944,"pending_message":null},{"id":"./spec/adapters/ui/components/enhanced_popup_menu_spec.rb[1:2:1]","description":"updates selected item when hovering over another row","full_description":"Shoko::Adapters::Ui::Components::EnhancedPopupMenu#handle_hover updates selected item when hovering over another row","status":"passed","file_path":"./spec/adapters/ui/components/enhanced_popup_menu_spec.rb","line_number":56,"run_time":0.000324488,"pending_message":null},{"id":"./spec/application/services/popup_position_service_spec.rb[1:1]","description":"positions popup below selection when there is room","full_description":"Shoko::Application::Services::PopupPositionService positions popup below selection when there is room","status":"passed","file_path":"./spec/application/services/popup_position_service_spec.rb","line_number":9,"run_time":0.000112591,"pending_message":null},{"id":"./spec/application/services/popup_position_service_spec.rb[1:2]","description":"clamps popup horizontally and vertically to stay on-screen","full_description":"Shoko::Application::Services::PopupPositionService clamps popup horizontally and vertically to stay on-screen","status":"passed","file_path":"./spec/application/services/popup_position_service_spec.rb","line_number":15,"run_time":0.000099426,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:4:1]","description":"builds and runs the application via injected hooks","full_description":"Shoko::Adapters::Input::CLI.run builds and runs the application via injected hooks","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":203,"run_time":0.000659146,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:4:2]","description":"surfaces application factory errors","full_description":"Shoko::Adapters::Input::CLI.run surfaces application factory errors","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":216,"run_time":0.000462417,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:1:5]","description":"parses --log-level LEVEL","full_description":"Shoko::Adapters::Input::CLI option parsing parses --log-level LEVEL","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":35,"run_time":0.000274434,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:1:6]","description":"parses --profile PATH","full_description":"Shoko::Adapters::Input::CLI option parsing parses --profile PATH","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":40,"run_time":0.000317215,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:1:9]","description":"prints version for -v and exits with status 0","full_description":"Shoko::Adapters::Input::CLI option parsing prints version for -v and exits with status 0","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":57,"run_time":0.00134371,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:1:1]","description":"parses empty arguments","full_description":"Shoko::Adapters::Input::CLI option parsing parses empty arguments","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":13,"run_time":0.00029334,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:1:10]","description":"prints version for --version and exits with status 0","full_description":"Shoko::Adapters::Input::CLI option parsing prints version for --version and exits with status 0","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":69,"run_time":0.000309461,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:1:8]","description":"parses combined options and file","full_description":"Shoko::Adapters::Input::CLI option parsing parses combined options and file","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":50,"run_time":0.000272311,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:1:4]","description":"parses --log PATH","full_description":"Shoko::Adapters::Input::CLI option parsing parses --log PATH","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":30,"run_time":0.00026093,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:1:3]","description":"parses --debug flag","full_description":"Shoko::Adapters::Input::CLI option parsing parses --debug flag","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":25,"run_time":0.000270998,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:1:2]","description":"parses -d flag","full_description":"Shoko::Adapters::Input::CLI option parsing parses -d flag","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":20,"run_time":0.00024534,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:1:7]","description":"leaves file argument in args","full_description":"Shoko::Adapters::Input::CLI option parsing leaves file argument in args","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":45,"run_time":0.000234069,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:2:7]","description":"returns false when DEBUG env is no","full_description":"Shoko::Adapters::Input::CLI.debug_enabled? returns false when DEBUG env is no","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":123,"run_time":0.000171521,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:2:2]","description":"returns false when options[:debug] is false and DEBUG not set","full_description":"Shoko::Adapters::Input::CLI.debug_enabled? returns false when options[:debug] is false and DEBUG not set","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":88,"run_time":0.000151975,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:2:3]","description":"returns true when DEBUG env is set to 1","full_description":"Shoko::Adapters::Input::CLI.debug_enabled? returns true when DEBUG env is set to 1","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":95,"run_time":0.000151283,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:2:1]","description":"returns true when options[:debug] is true","full_description":"Shoko::Adapters::Input::CLI.debug_enabled? returns true when options[:debug] is true","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":83,"run_time":0.000159109,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:2:4]","description":"returns true when DEBUG env is set to true","full_description":"Shoko::Adapters::Input::CLI.debug_enabled? returns true when DEBUG env is set to true","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":102,"run_time":0.000135744,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:2:8]","description":"returns false when DEBUG env is off","full_description":"Shoko::Adapters::Input::CLI.debug_enabled? returns false when DEBUG env is off","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":130,"run_time":0.000141285,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:2:6]","description":"returns false when DEBUG env is false","full_description":"Shoko::Adapters::Input::CLI.debug_enabled? returns false when DEBUG env is false","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":116,"run_time":0.000184927,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:2:5]","description":"returns false when DEBUG env is 0","full_description":"Shoko::Adapters::Input::CLI.debug_enabled? returns false when DEBUG env is 0","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":109,"run_time":0.000225252,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:3:3]","description":"returns :error as default","full_description":"Shoko::Adapters::Input::CLI.logger_level returns :error as default","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":153,"run_time":0.000158778,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:3:2]","description":"returns configured level when specified","full_description":"Shoko::Adapters::Input::CLI.logger_level returns configured level when specified","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":146,"run_time":0.000131958,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:3:4]","description":"keeps DEBUG env precedence over explicit --log-level when DEBUG is truthy","full_description":"Shoko::Adapters::Input::CLI.logger_level keeps DEBUG env precedence over explicit --log-level when DEBUG is truthy","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":160,"run_time":0.000161042,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:3:5]","description":"keeps --debug option precedence over explicit --log-level when DEBUG env is falsey","full_description":"Shoko::Adapters::Input::CLI.logger_level keeps --debug option precedence over explicit --log-level when DEBUG env is falsey","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":167,"run_time":0.00012802,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:3:9]","description":"returns nil for invalid log level","full_description":"Shoko::Adapters::Input::CLI.logger_level returns nil for invalid log level","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":193,"run_time":0.000131827,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:3:8]","description":"normalizes log level strings","full_description":"Shoko::Adapters::Input::CLI.logger_level normalizes log level strings","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":188,"run_time":0.000133,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:3:6]","description":"uses explicit --log-level when DEBUG env is falsey and --debug is off","full_description":"Shoko::Adapters::Input::CLI.logger_level uses explicit --log-level when DEBUG env is falsey and --debug is off","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":174,"run_time":0.000133991,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:3:1]","description":"returns :debug when debug is enabled","full_description":"Shoko::Adapters::Input::CLI.logger_level returns :debug when debug is enabled","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":139,"run_time":0.000136275,"pending_message":null},{"id":"./spec/adapters/input/cli_spec.rb[1:3:7]","description":"uses SHOKO_LOG_LEVEL when no option is set and DEBUG env is falsey","full_description":"Shoko::Adapters::Input::CLI.logger_level uses SHOKO_LOG_LEVEL when no option is set and DEBUG env is falsey","status":"passed","file_path":"./spec/adapters/input/cli_spec.rb","line_number":181,"run_time":0.000152807,"pending_message":null},{"id":"./spec/adapters/storage/cache_availability_adapter_spec.rb[1:3]","description":"returns true for valid cache pointer files","full_description":"Shoko::Adapters::Storage::CacheAvailabilityAdapter returns true for valid cache pointer files","status":"passed","file_path":"./spec/adapters/storage/cache_availability_adapter_spec.rb","line_number":71,"run_time":0.001884033,"pending_message":null},{"id":"./spec/adapters/storage/cache_availability_adapter_spec.rb[1:2]","description":"returns false when payload is missing","full_description":"Shoko::Adapters::Storage::CacheAvailabilityAdapter returns false when payload is missing","status":"passed","file_path":"./spec/adapters/storage/cache_availability_adapter_spec.rb","line_number":51,"run_time":0.000611396,"pending_message":null},{"id":"./spec/adapters/storage/cache_availability_adapter_spec.rb[1:1]","description":"returns true when manifest and payload exist for the source","full_description":"Shoko::Adapters::Storage::CacheAvailabilityAdapter returns true when manifest and payload exist for the source","status":"passed","file_path":"./spec/adapters/storage/cache_availability_adapter_spec.rb","line_number":28,"run_time":0.000437861,"pending_message":null},{"id":"./spec/adapters/runtime/env_runtime_config_adapter_spec.rb[1:1]","description":"parses typed runtime config values from env-like input","full_description":"Shoko::Adapters::Runtime::EnvRuntimeConfigAdapter parses typed runtime config values from env-like input","status":"passed","file_path":"./spec/adapters/runtime/env_runtime_config_adapter_spec.rb","line_number":6,"run_time":0.000198853,"pending_message":null},{"id":"./spec/adapters/runtime/env_runtime_config_adapter_spec.rb[1:2]","description":"falls back to defaults for invalid values","full_description":"Shoko::Adapters::Runtime::EnvRuntimeConfigAdapter falls back to defaults for invalid values","status":"passed","file_path":"./spec/adapters/runtime/env_runtime_config_adapter_spec.rb","line_number":48,"run_time":0.000093445,"pending_message":null},{"id":"./spec/adapters/input/controllers/dictionary_controller_spec.rb[1:1:11]","description":"remembers manual source per book only","full_description":"Shoko::Adapters::Input::Controllers::DictionaryController setup flow remembers manual source per book only","status":"passed","file_path":"./spec/adapters/input/controllers/dictionary_controller_spec.rb","line_number":278,"run_time":0.002105729,"pending_message":null},{"id":"./spec/adapters/input/controllers/dictionary_controller_spec.rb[1:1:2]","description":"prompts for source language when metadata language is missing","full_description":"Shoko::Adapters::Input::Controllers::DictionaryController setup flow prompts for source language when metadata language is missing","status":"passed","file_path":"./spec/adapters/input/controllers/dictionary_controller_spec.rb","line_number":159,"run_time":0.000845125,"pending_message":null},{"id":"./spec/adapters/input/controllers/dictionary_controller_spec.rb[1:1:6]","description":"supports swapping source and target with S in target stage","full_description":"Shoko::Adapters::Input::Controllers::DictionaryController setup flow supports swapping source and target with S in target stage","status":"passed","file_path":"./spec/adapters/input/controllers/dictionary_controller_spec.rb","line_number":206,"run_time":0.000921648,"pending_message":null},{"id":"./spec/adapters/input/controllers/dictionary_controller_spec.rb[1:1:9]","description":"shows an error when exact pair is missing from catalog","full_description":"Shoko::Adapters::Input::Controllers::DictionaryController setup flow shows an error when exact pair is missing from catalog","status":"passed","file_path":"./spec/adapters/input/controllers/dictionary_controller_spec.rb","line_number":253,"run_time":0.001099412,"pending_message":null},{"id":"./spec/adapters/input/controllers/dictionary_controller_spec.rb[1:1:1]","description":"uses metadata language and starts at target prompt when source is known","full_description":"Shoko::Adapters::Input::Controllers::DictionaryController setup flow uses metadata language and starts at target prompt when source is known","status":"passed","file_path":"./spec/adapters/input/controllers/dictionary_controller_spec.rb","line_number":151,"run_time":0.000809137,"pending_message":null},{"id":"./spec/adapters/input/controllers/dictionary_controller_spec.rb[1:1:10]","description":"shows download errors inside setup popup","full_description":"Shoko::Adapters::Input::Controllers::DictionaryController setup flow shows download errors inside setup popup","status":"passed","file_path":"./spec/adapters/input/controllers/dictionary_controller_spec.rb","line_number":266,"run_time":0.001194139,"pending_message":null},{"id":"./spec/adapters/input/controllers/dictionary_controller_spec.rb[1:1:5]","description":"supports suggestion selection and tab apply in setup","full_description":"Shoko::Adapters::Input::Controllers::DictionaryController setup flow supports suggestion selection and tab apply in setup","status":"passed","file_path":"./spec/adapters/input/controllers/dictionary_controller_spec.rb","line_number":190,"run_time":0.001083922,"pending_message":null},{"id":"./spec/adapters/input/controllers/dictionary_controller_spec.rb[1:1:7]","description":"auto-downloads exact pair and performs lookup","full_description":"Shoko::Adapters::Input::Controllers::DictionaryController setup flow auto-downloads exact pair and performs lookup","status":"passed","file_path":"./spec/adapters/input/controllers/dictionary_controller_spec.rb","line_number":219,"run_time":0.001289158,"pending_message":null},{"id":"./spec/adapters/input/controllers/dictionary_controller_spec.rb[1:1:8]","description":"normalizes language names entered in setup before catalog matching","full_description":"Shoko::Adapters::Input::Controllers::DictionaryController setup flow normalizes language names entered in setup before catalog matching","status":"passed","file_path":"./spec/adapters/input/controllers/dictionary_controller_spec.rb","line_number":235,"run_time":0.002109676,"pending_message":null},{"id":"./spec/adapters/input/controllers/dictionary_controller_spec.rb[1:1:3]","description":"validates manual source language input","full_description":"Shoko::Adapters::Input::Controllers::DictionaryController setup flow validates manual source language input","status":"passed","file_path":"./spec/adapters/input/controllers/dictionary_controller_spec.rb","line_number":168,"run_time":0.000880531,"pending_message":null},{"id":"./spec/adapters/input/controllers/dictionary_controller_spec.rb[1:1:4]","description":"prompts for target language each setup invocation","full_description":"Shoko::Adapters::Input::Controllers::DictionaryController setup flow prompts for target language each setup invocation","status":"passed","file_path":"./spec/adapters/input/controllers/dictionary_controller_spec.rb","line_number":179,"run_time":0.000886202,"pending_message":null},{"id":"./spec/adapters/output/terminal/terminal_session_adapter_spec.rb[1:1]","description":"delegates setup/cleanup/size to terminal service","full_description":"Shoko::Adapters::Output::Terminal::TerminalSessionAdapter delegates setup/cleanup/size to terminal service","status":"passed","file_path":"./spec/adapters/output/terminal/terminal_session_adapter_spec.rb","line_number":9,"run_time":0.00021903,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/inline_segment_highlighter_spec.rb[1:2]","description":"skips highlighting for code blocks","full_description":"Shoko::Adapters::Ui::Components::Reading::InlineSegmentHighlighter skips highlighting for code blocks","status":"passed","file_path":"./spec/adapters/ui/components/reading/inline_segment_highlighter_spec.rb","line_number":26,"run_time":0.000078427,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/inline_segment_highlighter_spec.rb[1:1]","description":"applies quote and keyword styles to matching ranges","full_description":"Shoko::Adapters::Ui::Components::Reading::InlineSegmentHighlighter applies quote and keyword styles to matching ranges","status":"passed","file_path":"./spec/adapters/ui/components/reading/inline_segment_highlighter_spec.rb","line_number":8,"run_time":0.000135594,"pending_message":null},{"id":"./spec/adapters/ui/rendering/frame_coordinator_spec.rb[1:1]","description":"renders loading overlay without raising","full_description":"Shoko::Adapters::Ui::Rendering::FrameCoordinator renders loading overlay without raising","status":"passed","file_path":"./spec/adapters/ui/rendering/frame_coordinator_spec.rb","line_number":35,"run_time":0.000621315,"pending_message":null},{"id":"./spec/core/ports/outbound/menu_and_runtime_ports_spec.rb[1:2]","description":"defines MenuWorkflowStateWriter contract methods","full_description":"Menu and runtime outbound port contracts defines MenuWorkflowStateWriter contract methods","status":"passed","file_path":"./spec/core/ports/outbound/menu_and_runtime_ports_spec.rb","line_number":38,"run_time":0.000128451,"pending_message":null},{"id":"./spec/core/ports/outbound/menu_and_runtime_ports_spec.rb[1:5]","description":"defines AnnotationEditorLauncher contract methods","full_description":"Menu and runtime outbound port contracts defines AnnotationEditorLauncher contract methods","status":"passed","file_path":"./spec/core/ports/outbound/menu_and_runtime_ports_spec.rb","line_number":71,"run_time":0.000073959,"pending_message":null},{"id":"./spec/core/ports/outbound/menu_and_runtime_ports_spec.rb[1:1]","description":"defines MenuWorkflowStateReader contract methods","full_description":"Menu and runtime outbound port contracts defines MenuWorkflowStateReader contract methods","status":"passed","file_path":"./spec/core/ports/outbound/menu_and_runtime_ports_spec.rb","line_number":24,"run_time":0.000107491,"pending_message":null},{"id":"./spec/core/ports/outbound/menu_and_runtime_ports_spec.rb[1:6]","description":"defines WallClock and IdGenerator contract methods","full_description":"Menu and runtime outbound port contracts defines WallClock and IdGenerator contract methods","status":"passed","file_path":"./spec/core/ports/outbound/menu_and_runtime_ports_spec.rb","line_number":80,"run_time":0.000083667,"pending_message":null},{"id":"./spec/core/ports/outbound/menu_and_runtime_ports_spec.rb[1:3]","description":"defines TerminalSession contract methods","full_description":"Menu and runtime outbound port contracts defines TerminalSession contract methods","status":"passed","file_path":"./spec/core/ports/outbound/menu_and_runtime_ports_spec.rb","line_number":50,"run_time":0.00008545,"pending_message":null},{"id":"./spec/core/ports/outbound/menu_and_runtime_ports_spec.rb[1:4]","description":"defines AppModeRunner contract methods","full_description":"Menu and runtime outbound port contracts defines AppModeRunner contract methods","status":"passed","file_path":"./spec/core/ports/outbound/menu_and_runtime_ports_spec.rb","line_number":61,"run_time":0.000093154,"pending_message":null},{"id":"./spec/adapters/book_sources/document_service_spec.rb[1:1:1]","description":"propagates non-Shoko exceptions from BookDocument construction","full_description":"Shoko::Adapters::BookSources::DocumentService#load_document propagates non-Shoko exceptions from BookDocument construction","status":"passed","file_path":"./spec/adapters/book_sources/document_service_spec.rb","line_number":11,"run_time":0.000350868,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/download_books_screen_component_spec.rb[1:4]","description":"renders coherent download layout in light mode at 120x40","full_description":"Shoko::Adapters::Ui::Components::Screens::DownloadBooksScreenComponent renders coherent download layout in light mode at 120x40","status":"passed","file_path":"./spec/adapters/ui/components/screens/download_books_screen_component_spec.rb","line_number":33,"run_time":0.00169071,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/download_books_screen_component_spec.rb[1:2]","description":"renders coherent download layout in light mode at 80x24","full_description":"Shoko::Adapters::Ui::Components::Screens::DownloadBooksScreenComponent renders coherent download layout in light mode at 80x24","status":"passed","file_path":"./spec/adapters/ui/components/screens/download_books_screen_component_spec.rb","line_number":33,"run_time":0.001090425,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/download_books_screen_component_spec.rb[1:3]","description":"renders coherent download layout in dark mode at 120x40","full_description":"Shoko::Adapters::Ui::Components::Screens::DownloadBooksScreenComponent renders coherent download layout in dark mode at 120x40","status":"passed","file_path":"./spec/adapters/ui/components/screens/download_books_screen_component_spec.rb","line_number":33,"run_time":0.001193579,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/download_books_screen_component_spec.rb[1:1]","description":"renders coherent download layout in dark mode at 80x24","full_description":"Shoko::Adapters::Ui::Components::Screens::DownloadBooksScreenComponent renders coherent download layout in dark mode at 80x24","status":"passed","file_path":"./spec/adapters/ui/components/screens/download_books_screen_component_spec.rb","line_number":33,"run_time":0.0011145,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/kitty_image_line_renderer_spec.rb[1:1]","description":"raises when rendering fails","full_description":"Shoko::Adapters::Ui::Components::Reading::KittyImageLineRenderer raises when rendering fails","status":"passed","file_path":"./spec/adapters/ui/components/reading/kitty_image_line_renderer_spec.rb","line_number":25,"run_time":0.00015464,"pending_message":null},{"id":"./spec/core/events/event_factory_spec.rb[1:1]","description":"builds domain events with injected metadata","full_description":"Shoko::Core::Events::EventFactory builds domain events with injected metadata","status":"passed","file_path":"./spec/core/events/event_factory_spec.rb","line_number":12,"run_time":0.000202379,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:2:3]","description":"provides download screen via main_menu_component","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller screen components provides download screen via main_menu_component","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":83,"run_time":0.001671575,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:2:1]","description":"provides browse screen via main_menu_component","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller screen components provides browse screen via main_menu_component","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":75,"run_time":0.00070369,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:2:4]","description":"provides annotations screen via main_menu_component","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller screen components provides annotations screen via main_menu_component","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":87,"run_time":0.00083729,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:2:2]","description":"provides settings screen via main_menu_component","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller screen components provides settings screen via main_menu_component","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":79,"run_time":0.000745278,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:4:1]","description":"prefers cache pointer open_path over epub_path when both are available","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller library path resolution prefers cache pointer open_path over epub_path when both are available","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":106,"run_time":0.00101314,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:4:2]","description":"returns nil when cache pointer is unavailable","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller library path resolution returns nil when cache pointer is unavailable","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":121,"run_time":0.00081562,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:5:1]","description":"toggles metadata visibility in library mode","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller library metadata drawer toggles metadata visibility in library mode","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":141,"run_time":0.00083194,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:1:2]","description":"exposes observer_registry","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller initialization exposes observer_registry","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":20,"run_time":0.001239835,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:1:7]","description":"creates frame_coordinator","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller initialization creates frame_coordinator","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":45,"run_time":0.000677119,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:1:5]","description":"creates catalog service","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller initialization creates catalog service","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":35,"run_time":0.000614192,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:1:6]","description":"creates terminal service","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller initialization creates terminal service","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":40,"run_time":0.000649788,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:1:3]","description":"does not expose a container service-locator surface","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller initialization does not expose a container service-locator surface","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":25,"run_time":0.000770034,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:1:9]","description":"creates state_controller","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller initialization creates state_controller","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":55,"run_time":0.000712947,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:1:4]","description":"creates main_menu_component","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller initialization creates main_menu_component","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":30,"run_time":0.000719389,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:1:1]","description":"creates successfully with dependency container","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller initialization creates successfully with dependency container","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":15,"run_time":0.000635121,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:1:11]","description":"input_controller has dispatcher","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller initialization input_controller has dispatcher","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":65,"run_time":0.000574808,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:1:10]","description":"creates input_controller","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller initialization creates input_controller","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":60,"run_time":0.00074143,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:1:8]","description":"creates render_pipeline","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller initialization creates render_pipeline","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":50,"run_time":0.000646823,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:3:1]","description":"does not include adapter key definitions directly","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller key classification via DI does not include adapter key definitions directly","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":96,"run_time":0.000635031,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:6:2]","description":"opens selected book from browse-screen filtered list instead of stale controller list","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller browse search selection opens selected book from browse-screen filtered list instead of stale controller list","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":178,"run_time":0.000718628,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:6:1]","description":"keeps browse results filtered when new catalog entries are assigned during active search","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller browse search selection keeps browse results filtered when new catalog entries are assigned during active search","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":158,"run_time":0.000705703,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/controller_spec.rb[1:6:3]","description":"exits browse search mode when pressing escape","full_description":"Shoko::Adapters::Input::Controllers::Menu::Controller browse search selection exits browse search mode when pressing escape","status":"passed","file_path":"./spec/adapters/input/controllers/menu/controller_spec.rb","line_number":194,"run_time":0.000820569,"pending_message":null},{"id":"./spec/adapters/ui/sessions/in_book_search_ui_session_adapter_spec.rb[1:2]","description":"delegates key handling and result updates","full_description":"Shoko::Adapters::Ui::Sessions::InBookSearchUiSessionAdapter delegates key handling and result updates","status":"passed","file_path":"./spec/adapters/ui/sessions/in_book_search_ui_session_adapter_spec.rb","line_number":47,"run_time":0.000482545,"pending_message":null},{"id":"./spec/adapters/ui/sessions/in_book_search_ui_session_adapter_spec.rb[1:3]","description":"closes popup and returns to read mode","full_description":"Shoko::Adapters::Ui::Sessions::InBookSearchUiSessionAdapter closes popup and returns to read mode","status":"passed","file_path":"./spec/adapters/ui/sessions/in_book_search_ui_session_adapter_spec.rb","line_number":58,"run_time":0.000287479,"pending_message":null},{"id":"./spec/adapters/ui/sessions/in_book_search_ui_session_adapter_spec.rb[1:1]","description":"opens search popup and updates reader mode","full_description":"Shoko::Adapters::Ui::Sessions::InBookSearchUiSessionAdapter opens search popup and updates reader mode","status":"passed","file_path":"./spec/adapters/ui/sessions/in_book_search_ui_session_adapter_spec.rb","line_number":33,"run_time":0.000284975,"pending_message":null},{"id":"./spec/adapters/ui/sessions/in_book_search_ui_session_adapter_spec.rb[1:4]","description":"returns failure outcomes and logs when popup actions raise","full_description":"Shoko::Adapters::Ui::Sessions::InBookSearchUiSessionAdapter returns failure outcomes and logs when popup actions raise","status":"passed","file_path":"./spec/adapters/ui/sessions/in_book_search_ui_session_adapter_spec.rb","line_number":67,"run_time":0.000613871,"pending_message":null},{"id":"./spec/core/architecture/no_standard_error_rescue_spec.rb[1:1]","description":"forbids rescue StandardError in lib/shoko runtime sources","full_description":"No StandardError rescues in runtime code forbids rescue StandardError in lib/shoko runtime sources","status":"passed","file_path":"./spec/core/architecture/no_standard_error_rescue_spec.rb","line_number":9,"run_time":0.033017104,"pending_message":null},{"id":"./spec/core/architecture/strict_hexagonal_wiring_spec.rb[1:3]","description":"forbids adapters/input from referencing adapters/ui constants directly","full_description":"Strict hexagonal wiring boundaries forbids adapters/input from referencing adapters/ui constants directly","status":"passed","file_path":"./spec/core/architecture/strict_hexagonal_wiring_spec.rb","line_number":76,"run_time":0.006000432,"pending_message":null},{"id":"./spec/core/architecture/strict_hexagonal_wiring_spec.rb[1:1]","description":"forbids adapters from requiring application files","full_description":"Strict hexagonal wiring boundaries forbids adapters from requiring application files","status":"passed","file_path":"./spec/core/architecture/strict_hexagonal_wiring_spec.rb","line_number":40,"run_time":0.028013201,"pending_message":null},{"id":"./spec/core/architecture/strict_hexagonal_wiring_spec.rb[1:2]","description":"forbids adapters from referencing application constants","full_description":"Strict hexagonal wiring boundaries forbids adapters from referencing application constants","status":"passed","file_path":"./spec/core/architecture/strict_hexagonal_wiring_spec.rb","line_number":58,"run_time":0.029129634,"pending_message":null},{"id":"./spec/core/book_formats/kindle/exth_parser_spec.rb[1:6]","description":"parses language","full_description":"Shoko::Core::BookFormats::Kindle::ExthParser parses language","status":"passed","file_path":"./spec/core/book_formats/kindle/exth_parser_spec.rb","line_number":55,"run_time":0.000269796,"pending_message":null},{"id":"./spec/core/book_formats/kindle/exth_parser_spec.rb[1:3]","description":"parses updated title","full_description":"Shoko::Core::BookFormats::Kindle::ExthParser parses updated title","status":"passed","file_path":"./spec/core/book_formats/kindle/exth_parser_spec.rb","line_number":37,"run_time":0.000126797,"pending_message":null},{"id":"./spec/core/book_formats/kindle/exth_parser_spec.rb[1:2]","description":"parses multiple authors","full_description":"Shoko::Core::BookFormats::Kindle::ExthParser parses multiple authors","status":"passed","file_path":"./spec/core/book_formats/kindle/exth_parser_spec.rb","line_number":27,"run_time":0.000077726,"pending_message":null},{"id":"./spec/core/book_formats/kindle/exth_parser_spec.rb[1:1]","description":"parses author metadata","full_description":"Shoko::Core::BookFormats::Kindle::ExthParser parses author metadata","status":"passed","file_path":"./spec/core/book_formats/kindle/exth_parser_spec.rb","line_number":20,"run_time":0.000068028,"pending_message":null},{"id":"./spec/core/book_formats/kindle/exth_parser_spec.rb[1:11]","description":"returns nil for missing records","full_description":"Shoko::Core::BookFormats::Kindle::ExthParser returns nil for missing records","status":"passed","file_path":"./spec/core/book_formats/kindle/exth_parser_spec.rb","line_number":85,"run_time":0.000067206,"pending_message":null},{"id":"./spec/core/book_formats/kindle/exth_parser_spec.rb[1:4]","description":"parses publisher","full_description":"Shoko::Core::BookFormats::Kindle::ExthParser parses publisher","status":"passed","file_path":"./spec/core/book_formats/kindle/exth_parser_spec.rb","line_number":43,"run_time":0.000131086,"pending_message":null},{"id":"./spec/core/book_formats/kindle/exth_parser_spec.rb[1:7]","description":"parses description","full_description":"Shoko::Core::BookFormats::Kindle::ExthParser parses description","status":"passed","file_path":"./spec/core/book_formats/kindle/exth_parser_spec.rb","line_number":61,"run_time":0.000066475,"pending_message":null},{"id":"./spec/core/book_formats/kindle/exth_parser_spec.rb[1:12]","description":"handles invalid EXTH gracefully","full_description":"Shoko::Core::BookFormats::Kindle::ExthParser handles invalid EXTH gracefully","status":"passed","file_path":"./spec/core/book_formats/kindle/exth_parser_spec.rb","line_number":93,"run_time":0.000068338,"pending_message":null},{"id":"./spec/core/book_formats/kindle/exth_parser_spec.rb[1:13]","description":"handles truncated data gracefully","full_description":"Shoko::Core::BookFormats::Kindle::ExthParser handles truncated data gracefully","status":"passed","file_path":"./spec/core/book_formats/kindle/exth_parser_spec.rb","line_number":100,"run_time":0.000079599,"pending_message":null},{"id":"./spec/core/book_formats/kindle/exth_parser_spec.rb[1:8]","description":"parses ISBN","full_description":"Shoko::Core::BookFormats::Kindle::ExthParser parses ISBN","status":"passed","file_path":"./spec/core/book_formats/kindle/exth_parser_spec.rb","line_number":67,"run_time":0.00006399,"pending_message":null},{"id":"./spec/core/book_formats/kindle/exth_parser_spec.rb[1:9]","description":"parses ASIN","full_description":"Shoko::Core::BookFormats::Kindle::ExthParser parses ASIN","status":"passed","file_path":"./spec/core/book_formats/kindle/exth_parser_spec.rb","line_number":73,"run_time":0.000060884,"pending_message":null},{"id":"./spec/core/book_formats/kindle/exth_parser_spec.rb[1:5]","description":"parses publishing date","full_description":"Shoko::Core::BookFormats::Kindle::ExthParser parses publishing date","status":"passed","file_path":"./spec/core/book_formats/kindle/exth_parser_spec.rb","line_number":49,"run_time":0.000058801,"pending_message":null},{"id":"./spec/core/book_formats/kindle/exth_parser_spec.rb[1:10]","description":"parses subject","full_description":"Shoko::Core::BookFormats::Kindle::ExthParser parses subject","status":"passed","file_path":"./spec/core/book_formats/kindle/exth_parser_spec.rb","line_number":79,"run_time":0.00005846,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:5:1]","description":"allows subclasses to customize invalid transition handling","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore subclass customization allows subclasses to customize invalid transition handling","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":212,"run_time":0.000531146,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:1:1]","description":"captures state transition context","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore StateUpdateError captures state transition context","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":35,"run_time":0.000161182,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:1:2]","description":"rejects negative right_page","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? reader transitions rejects negative right_page","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":59,"run_time":0.000222868,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:1:1]","description":"rejects negative left_page","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? reader transitions rejects negative left_page","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":54,"run_time":0.000232937,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:1:4]","description":"rejects negative current_page_index","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? reader transitions rejects negative current_page_index","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":69,"run_time":0.000213039,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:1:3]","description":"rejects negative single_page","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? reader transitions rejects negative single_page","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":64,"run_time":0.000205786,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:1:6]","description":"rejects current_chapter exceeding total_chapters","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? reader transitions rejects current_chapter exceeding total_chapters","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":83,"run_time":0.00020799,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:1:5]","description":"allows valid page values","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? reader transitions allows valid page values","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":74,"run_time":0.000256541,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:1:8]","description":"allows current_chapter when total_chapters is 0","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? reader transitions allows current_chapter when total_chapters is 0","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":95,"run_time":0.000206347,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:1:7]","description":"allows current_chapter within bounds","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? reader transitions allows current_chapter within bounds","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":89,"run_time":0.000206818,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:3:1]","description":"rejects negative sidebar_toc_selected","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? sidebar transitions rejects negative sidebar_toc_selected","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":127,"run_time":0.000215674,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:3:2]","description":"rejects negative sidebar_annotations_selected","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? sidebar transitions rejects negative sidebar_annotations_selected","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":132,"run_time":0.000224841,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:3:3]","description":"rejects negative sidebar_bookmarks_selected","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? sidebar transitions rejects negative sidebar_bookmarks_selected","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":137,"run_time":0.000197951,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:3:4]","description":"rejects invalid sidebar_active_tab","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? sidebar transitions rejects invalid sidebar_active_tab","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":142,"run_time":0.000225233,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:3:5]","description":"allows valid sidebar_active_tab values","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? sidebar transitions allows valid sidebar_active_tab values","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":147,"run_time":0.000519194,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:2:2]","description":"allows current_page_index within bounds","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? pagination transitions allows current_page_index within bounds","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":109,"run_time":0.000225212,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:2:1]","description":"rejects current_page_index exceeding dynamic_total_pages","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? pagination transitions rejects current_page_index exceeding dynamic_total_pages","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":103,"run_time":0.000230893,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:2:4]","description":"rejects negative dynamic_total_pages","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? pagination transitions rejects negative dynamic_total_pages","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":120,"run_time":0.000201708,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:2:2:3]","description":"rejects negative total_pages","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#valid_transition? pagination transitions rejects negative total_pages","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":115,"run_time":0.00019692,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:3:2]","description":"includes context in StateUpdateError","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#update with validation includes context in StateUpdateError","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":163,"run_time":0.000243988,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:3:3]","description":"allows valid transitions","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#update with validation allows valid transitions","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":170,"run_time":0.000348463,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:3:4]","description":"does not update state on invalid transition","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#update with validation does not update state on invalid transition","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":175,"run_time":0.000230973,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:3:1]","description":"raises StateUpdateError for invalid transitions","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#update with validation raises StateUpdateError for invalid transitions","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":157,"run_time":0.000242565,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:4:1]","description":"raises StateUpdateError with string reason","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#handle_invalid_transition raises StateUpdateError with string reason","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":187,"run_time":0.00022409,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb[1:4:2]","description":"raises StateUpdateError with default message for boolean false","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore#handle_invalid_transition raises StateUpdateError with default message for boolean false","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_transition_validation_spec.rb","line_number":193,"run_time":0.000220162,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/menu_screen_component_spec.rb[1:3]","description":"renders coherent shell in dark mode at 120x40","full_description":"Shoko::Adapters::Ui::Components::Screens::MenuScreenComponent renders coherent shell in dark mode at 120x40","status":"passed","file_path":"./spec/adapters/ui/components/screens/menu_screen_component_spec.rb","line_number":19,"run_time":0.001396228,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/menu_screen_component_spec.rb[1:4]","description":"renders coherent shell in light mode at 120x40","full_description":"Shoko::Adapters::Ui::Components::Screens::MenuScreenComponent renders coherent shell in light mode at 120x40","status":"passed","file_path":"./spec/adapters/ui/components/screens/menu_screen_component_spec.rb","line_number":19,"run_time":0.000965781,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/menu_screen_component_spec.rb[1:2]","description":"renders coherent shell in light mode at 80x24","full_description":"Shoko::Adapters::Ui::Components::Screens::MenuScreenComponent renders coherent shell in light mode at 80x24","status":"passed","file_path":"./spec/adapters/ui/components/screens/menu_screen_component_spec.rb","line_number":19,"run_time":0.000447279,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/menu_screen_component_spec.rb[1:1]","description":"renders coherent shell in dark mode at 80x24","full_description":"Shoko::Adapters::Ui::Components::Screens::MenuScreenComponent renders coherent shell in dark mode at 80x24","status":"passed","file_path":"./spec/adapters/ui/components/screens/menu_screen_component_spec.rb","line_number":19,"run_time":0.000345568,"pending_message":null},{"id":"./spec/core/book_formats/fb2/fb2_importer_zip_spec.rb[1:1]","description":"imports .fb2.zip files with nested FB2 entries","full_description":"Shoko::Adapters::BookSources::Fb2::Fb2Importer imports .fb2.zip files with nested FB2 entries","status":"passed","file_path":"./spec/core/book_formats/fb2/fb2_importer_zip_spec.rb","line_number":6,"run_time":0.001897378,"pending_message":null},{"id":"./spec/core/services/document_path_resolver_spec.rb[1:1]","description":"resolves canonical path through cache pointer source path","full_description":"Shoko::Core::Services::DocumentPathResolver resolves canonical path through cache pointer source path","status":"passed","file_path":"./spec/core/services/document_path_resolver_spec.rb","line_number":74,"run_time":0.000101992,"pending_message":null},{"id":"./spec/core/services/document_path_resolver_spec.rb[1:2]","description":"matches canonical document paths after expansion","full_description":"Shoko::Core::Services::DocumentPathResolver matches canonical document paths after expansion","status":"passed","file_path":"./spec/core/services/document_path_resolver_spec.rb","line_number":95,"run_time":0.000076964,"pending_message":null},{"id":"./spec/core/services/document_path_resolver_spec.rb[1:3]","description":"raises when cache pointer resolution fails","full_description":"Shoko::Core::Services::DocumentPathResolver raises when cache pointer resolution fails","status":"passed","file_path":"./spec/core/services/document_path_resolver_spec.rb","line_number":115,"run_time":0.000104696,"pending_message":null},{"id":"./spec/core/architecture/state_store_guardrails_spec.rb[1:2]","description":"requires runtime state-store persistence collaborators to rely on config_storage.file_exist?","full_description":"State store guardrails requires runtime state-store persistence collaborators to rely on config_storage.file_exist?","status":"passed","file_path":"./spec/core/architecture/state_store_guardrails_spec.rb","line_number":25,"run_time":0.000162675,"pending_message":null},{"id":"./spec/core/architecture/state_store_guardrails_spec.rb[1:1]","description":"forbids direct filesystem probes in runtime state stores","full_description":"State store guardrails forbids direct filesystem probes in runtime state stores","status":"passed","file_path":"./spec/core/architecture/state_store_guardrails_spec.rb","line_number":8,"run_time":0.000130614,"pending_message":null},{"id":"./spec/adapters/input/controllers/in_book_search_controller_spec.rb[1:2:2]","description":"runs search on submit_query","full_description":"Shoko::Adapters::Input::Controllers::InBookSearchController input intents runs search on submit_query","status":"passed","file_path":"./spec/adapters/input/controllers/in_book_search_controller_spec.rb","line_number":77,"run_time":0.000800682,"pending_message":null},{"id":"./spec/adapters/input/controllers/in_book_search_controller_spec.rb[1:2:4]","description":"jumps to selected result and closes popup on open_result","full_description":"Shoko::Adapters::Input::Controllers::InBookSearchController input intents jumps to selected result and closes popup on open_result","status":"passed","file_path":"./spec/adapters/input/controllers/in_book_search_controller_spec.rb","line_number":100,"run_time":0.000600156,"pending_message":null},{"id":"./spec/adapters/input/controllers/in_book_search_controller_spec.rb[1:2:3]","description":"closes popup on close event","full_description":"Shoko::Adapters::Input::Controllers::InBookSearchController input intents closes popup on close event","status":"passed","file_path":"./spec/adapters/input/controllers/in_book_search_controller_spec.rb","line_number":91,"run_time":0.000566933,"pending_message":null},{"id":"./spec/adapters/input/controllers/in_book_search_controller_spec.rb[1:2:1]","description":"does not run search while typing","full_description":"Shoko::Adapters::Input::Controllers::InBookSearchController input intents does not run search while typing","status":"passed","file_path":"./spec/adapters/input/controllers/in_book_search_controller_spec.rb","line_number":67,"run_time":0.000525966,"pending_message":null},{"id":"./spec/adapters/input/controllers/in_book_search_controller_spec.rb[1:1:1]","description":"shows popup, updates state, and activates modal mode","full_description":"Shoko::Adapters::Input::Controllers::InBookSearchController#open_in_book_search shows popup, updates state, and activates modal mode","status":"passed","file_path":"./spec/adapters/input/controllers/in_book_search_controller_spec.rb","line_number":58,"run_time":0.000446918,"pending_message":null},{"id":"./spec/core/architecture/no_proc_type_fallbacks_spec.rb[1:1]","description":"forbids is_a?(Proc) fallback probing in runtime source","full_description":"No Proc type fallback checks in runtime code forbids is_a?(Proc) fallback probing in runtime source","status":"passed","file_path":"./spec/core/architecture/no_proc_type_fallbacks_spec.rb","line_number":19,"run_time":0.035106972,"pending_message":null},{"id":"./spec/adapters/storage/repositories/annotation_repository_spec.rb[1:1:1]","description":"returns the newly added annotation deterministically by id diff","full_description":"Shoko::Adapters::Storage::Repositories::AnnotationRepository#add_for_book returns the newly added annotation deterministically by id diff","status":"passed","file_path":"./spec/adapters/storage/repositories/annotation_repository_spec.rb","line_number":15,"run_time":0.00053864,"pending_message":null},{"id":"./spec/adapters/storage/repositories/annotation_repository_spec.rb[1:1:2]","description":"raises PersistenceError when underlying storage add fails","full_description":"Shoko::Adapters::Storage::Repositories::AnnotationRepository#add_for_book raises PersistenceError when underlying storage add fails","status":"passed","file_path":"./spec/adapters/storage/repositories/annotation_repository_spec.rb","line_number":40,"run_time":0.000317355,"pending_message":null},{"id":"./spec/adapters/storage/repositories/annotation_repository_spec.rb[1:2:1]","description":"returns true when storage updates successfully","full_description":"Shoko::Adapters::Storage::Repositories::AnnotationRepository#update_note returns true when storage updates successfully","status":"passed","file_path":"./spec/adapters/storage/repositories/annotation_repository_spec.rb","line_number":58,"run_time":0.000315672,"pending_message":null},{"id":"./spec/adapters/storage/repositories/annotation_repository_spec.rb[1:2:2]","description":"returns false when storage does not update","full_description":"Shoko::Adapters::Storage::Repositories::AnnotationRepository#update_note returns false when storage does not update","status":"passed","file_path":"./spec/adapters/storage/repositories/annotation_repository_spec.rb","line_number":64,"run_time":0.000178755,"pending_message":null},{"id":"./spec/adapters/ui/sessions/annotation_overlay_ui_session_adapter_spec.rb[1:3]","description":"opens editor, handles editor events, and exposes editor context","full_description":"Shoko::Adapters::Ui::Sessions::AnnotationOverlayUiSessionAdapter opens editor, handles editor events, and exposes editor context","status":"passed","file_path":"./spec/adapters/ui/sessions/annotation_overlay_ui_session_adapter_spec.rb","line_number":74,"run_time":0.000522741,"pending_message":null},{"id":"./spec/adapters/ui/sessions/annotation_overlay_ui_session_adapter_spec.rb[1:1]","description":"opens and closes annotations overlay with outcomes","full_description":"Shoko::Adapters::Ui::Sessions::AnnotationOverlayUiSessionAdapter opens and closes annotations overlay with outcomes","status":"passed","file_path":"./spec/adapters/ui/sessions/annotation_overlay_ui_session_adapter_spec.rb","line_number":56,"run_time":0.000496501,"pending_message":null},{"id":"./spec/adapters/ui/sessions/annotation_overlay_ui_session_adapter_spec.rb[1:5]","description":"logs and returns failed outcomes when overlay interaction raises","full_description":"Shoko::Adapters::Ui::Sessions::AnnotationOverlayUiSessionAdapter logs and returns failed outcomes when overlay interaction raises","status":"passed","file_path":"./spec/adapters/ui/sessions/annotation_overlay_ui_session_adapter_spec.rb","line_number":102,"run_time":0.000626685,"pending_message":null},{"id":"./spec/adapters/ui/sessions/annotation_overlay_ui_session_adapter_spec.rb[1:2]","description":"wraps overlay events in outcome payloads","full_description":"Shoko::Adapters::Ui::Sessions::AnnotationOverlayUiSessionAdapter wraps overlay events in outcome payloads","status":"passed","file_path":"./spec/adapters/ui/sessions/annotation_overlay_ui_session_adapter_spec.rb","line_number":67,"run_time":0.000354194,"pending_message":null},{"id":"./spec/adapters/ui/sessions/annotation_overlay_ui_session_adapter_spec.rb[1:4]","description":"does not expose non-event editor return values as payloads","full_description":"Shoko::Adapters::Ui::Sessions::AnnotationOverlayUiSessionAdapter does not expose non-event editor return values as payloads","status":"passed","file_path":"./spec/adapters/ui/sessions/annotation_overlay_ui_session_adapter_spec.rb","line_number":93,"run_time":0.000473899,"pending_message":null},{"id":"./spec/adapters/book_sources/download_service_spec.rb[1:2:3]","description":"raises when book has no epub format","full_description":"Shoko::Adapters::BookSources::DownloadService#download raises when book has no epub format","status":"passed","file_path":"./spec/adapters/book_sources/download_service_spec.rb","line_number":95,"run_time":0.000297909,"pending_message":null},{"id":"./spec/adapters/book_sources/download_service_spec.rb[1:2:1]","description":"downloads epub and reports non-existing result","full_description":"Shoko::Adapters::BookSources::DownloadService#download downloads epub and reports non-existing result","status":"passed","file_path":"./spec/adapters/book_sources/download_service_spec.rb","line_number":67,"run_time":0.000558076,"pending_message":null},{"id":"./spec/adapters/book_sources/download_service_spec.rb[1:2:2]","description":"returns existing when destination file already exists","full_description":"Shoko::Adapters::BookSources::DownloadService#download returns existing when destination file already exists","status":"passed","file_path":"./spec/adapters/book_sources/download_service_spec.rb","line_number":83,"run_time":0.000392155,"pending_message":null},{"id":"./spec/adapters/book_sources/download_service_spec.rb[1:1:1]","description":"normalizes client payload into book list hashes","full_description":"Shoko::Adapters::BookSources::DownloadService#search normalizes client payload into book list hashes","status":"passed","file_path":"./spec/adapters/book_sources/download_service_spec.rb","line_number":22,"run_time":0.000352531,"pending_message":null},{"id":"./spec/core/services/bookmark_service_spec.rb[1:2]","description":"publishes BookmarkRemoved through the domain event bus when removing a bookmark","full_description":"Shoko::Application::Services::Reader::BookmarkService publishes BookmarkRemoved through the domain event bus when removing a bookmark","status":"passed","file_path":"./spec/core/services/bookmark_service_spec.rb","line_number":59,"run_time":0.000654267,"pending_message":null},{"id":"./spec/core/services/bookmark_service_spec.rb[1:3]","description":"publishes BookmarkNavigated through the domain event bus when jumping to a bookmark","full_description":"Shoko::Application::Services::Reader::BookmarkService publishes BookmarkNavigated through the domain event bus when jumping to a bookmark","status":"passed","file_path":"./spec/core/services/bookmark_service_spec.rb","line_number":65,"run_time":0.000497053,"pending_message":null},{"id":"./spec/core/services/bookmark_service_spec.rb[1:1]","description":"publishes BookmarkAdded through the domain event bus when adding a bookmark","full_description":"Shoko::Application::Services::Reader::BookmarkService publishes BookmarkAdded through the domain event bus when adding a bookmark","status":"passed","file_path":"./spec/core/services/bookmark_service_spec.rb","line_number":53,"run_time":0.000456837,"pending_message":null},{"id":"./spec/adapters/output/terminal/text_metrics_spec.rb[1:3:1]","description":"pads the right side to the requested width","full_description":"Shoko::Shared::Terminal::TextMetrics.pad_right pads the right side to the requested width","status":"passed","file_path":"./spec/adapters/output/terminal/text_metrics_spec.rb","line_number":93,"run_time":0.000114004,"pending_message":null},{"id":"./spec/adapters/output/terminal/text_metrics_spec.rb[1:5:1]","description":"splits long unbroken words to stay within width","full_description":"Shoko::Shared::Terminal::TextMetrics.wrap_plain_text splits long unbroken words to stay within width","status":"passed","file_path":"./spec/adapters/output/terminal/text_metrics_spec.rb","line_number":111,"run_time":0.000191449,"pending_message":null},{"id":"./spec/adapters/output/terminal/text_metrics_spec.rb[1:5:3]","description":"returns the same wrapped result with wrap cache enabled and disabled","full_description":"Shoko::Shared::Terminal::TextMetrics.wrap_plain_text returns the same wrapped result with wrap cache enabled and disabled","status":"passed","file_path":"./spec/adapters/output/terminal/text_metrics_spec.rb","line_number":129,"run_time":0.000580469,"pending_message":null},{"id":"./spec/adapters/output/terminal/text_metrics_spec.rb[1:5:2]","description":"preserves surrounding words while splitting long tokens","full_description":"Shoko::Shared::Terminal::TextMetrics.wrap_plain_text preserves surrounding words while splitting long tokens","status":"passed","file_path":"./spec/adapters/output/terminal/text_metrics_spec.rb","line_number":120,"run_time":0.000153688,"pending_message":null},{"id":"./spec/adapters/output/terminal/text_metrics_spec.rb[1:1:6]","description":"treats keycap emoji sequences as double-width glyphs","full_description":"Shoko::Shared::Terminal::TextMetrics.visible_length treats keycap emoji sequences as double-width glyphs","status":"passed","file_path":"./spec/adapters/output/terminal/text_metrics_spec.rb","line_number":32,"run_time":0.000076543,"pending_message":null},{"id":"./spec/adapters/output/terminal/text_metrics_spec.rb[1:1:2]","description":"counts wide CJK characters as width 2","full_description":"Shoko::Shared::Terminal::TextMetrics.visible_length counts wide CJK characters as width 2","status":"passed","file_path":"./spec/adapters/output/terminal/text_metrics_spec.rb","line_number":12,"run_time":0.000077024,"pending_message":null},{"id":"./spec/adapters/output/terminal/text_metrics_spec.rb[1:1:5]","description":"treats ZWJ emoji sequences as double-width glyphs","full_description":"Shoko::Shared::Terminal::TextMetrics.visible_length treats ZWJ emoji sequences as double-width glyphs","status":"passed","file_path":"./spec/adapters/output/terminal/text_metrics_spec.rb","line_number":27,"run_time":0.000067947,"pending_message":null},{"id":"./spec/adapters/output/terminal/text_metrics_spec.rb[1:1:3]","description":"treats combining marks as zero-width in grapheme clusters","full_description":"Shoko::Shared::Terminal::TextMetrics.visible_length treats combining marks as zero-width in grapheme clusters","status":"passed","file_path":"./spec/adapters/output/terminal/text_metrics_spec.rb","line_number":17,"run_time":0.00009044,"pending_message":null},{"id":"./spec/adapters/output/terminal/text_metrics_spec.rb[1:1:1]","description":"ignores ANSI sequences and expands tabs","full_description":"Shoko::Shared::Terminal::TextMetrics.visible_length ignores ANSI sequences and expands tabs","status":"passed","file_path":"./spec/adapters/output/terminal/text_metrics_spec.rb","line_number":7,"run_time":0.000060323,"pending_message":null},{"id":"./spec/adapters/output/terminal/text_metrics_spec.rb[1:1:8]","description":"returns the same width with ASCII fast path enabled and disabled","full_description":"Shoko::Shared::Terminal::TextMetrics.visible_length returns the same width with ASCII fast path enabled and disabled","status":"passed","file_path":"./spec/adapters/output/terminal/text_metrics_spec.rb","line_number":53,"run_time":0.000229861,"pending_message":null},{"id":"./spec/adapters/output/terminal/text_metrics_spec.rb[1:1:7]","description":"returns the same width with cache enabled and disabled","full_description":"Shoko::Shared::Terminal::TextMetrics.visible_length returns the same width with cache enabled and disabled","status":"passed","file_path":"./spec/adapters/output/terminal/text_metrics_spec.rb","line_number":37,"run_time":0.000183033,"pending_message":null},{"id":"./spec/adapters/output/terminal/text_metrics_spec.rb[1:1:4]","description":"treats emoji modifiers as a single double-width glyph","full_description":"Shoko::Shared::Terminal::TextMetrics.visible_length treats emoji modifiers as a single double-width glyph","status":"passed","file_path":"./spec/adapters/output/terminal/text_metrics_spec.rb","line_number":22,"run_time":0.000066374,"pending_message":null},{"id":"./spec/adapters/output/terminal/text_metrics_spec.rb[1:4:1]","description":"wraps lines on width boundaries without losing content","full_description":"Shoko::Shared::Terminal::TextMetrics.wrap_cells wraps lines on width boundaries without losing content","status":"passed","file_path":"./spec/adapters/output/terminal/text_metrics_spec.rb","line_number":101,"run_time":0.000098524,"pending_message":null},{"id":"./spec/adapters/output/terminal/text_metrics_spec.rb[1:2:3]","description":"returns the same result with ASCII fast path enabled and disabled","full_description":"Shoko::Shared::Terminal::TextMetrics.truncate_to returns the same result with ASCII fast path enabled and disabled","status":"passed","file_path":"./spec/adapters/output/terminal/text_metrics_spec.rb","line_number":77,"run_time":0.000555642,"pending_message":null},{"id":"./spec/adapters/output/terminal/text_metrics_spec.rb[1:2:1]","description":"clips text to the requested width","full_description":"Shoko::Shared::Terminal::TextMetrics.truncate_to clips text to the requested width","status":"passed","file_path":"./spec/adapters/output/terminal/text_metrics_spec.rb","line_number":69,"run_time":0.000068288,"pending_message":null},{"id":"./spec/adapters/output/terminal/text_metrics_spec.rb[1:2:2]","description":"treats newlines as spaces when truncating","full_description":"Shoko::Shared::Terminal::TextMetrics.truncate_to treats newlines as spaces when truncating","status":"passed","file_path":"./spec/adapters/output/terminal/text_metrics_spec.rb","line_number":73,"run_time":0.000059151,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/settings_screen_component_spec.rb[1:3]","description":"marks kitty images disabled when config is nil","full_description":"Shoko::Adapters::Ui::Components::Screens::SettingsScreenComponent marks kitty images disabled when config is nil","status":"passed","file_path":"./spec/adapters/ui/components/screens/settings_screen_component_spec.rb","line_number":24,"run_time":0.000171371,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/settings_screen_component_spec.rb[1:1]","description":"marks kitty images disabled when config is false","full_description":"Shoko::Adapters::Ui::Components::Screens::SettingsScreenComponent marks kitty images disabled when config is false","status":"passed","file_path":"./spec/adapters/ui/components/screens/settings_screen_component_spec.rb","line_number":14,"run_time":0.00009591,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/settings_screen_component_spec.rb[1:2]","description":"marks kitty images enabled when config is true","full_description":"Shoko::Adapters::Ui::Components::Screens::SettingsScreenComponent marks kitty images enabled when config is true","status":"passed","file_path":"./spec/adapters/ui/components/screens/settings_screen_component_spec.rb","line_number":19,"run_time":0.000073949,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/settings_screen_component_spec.rb[1:4:3]","description":"renders coherent settings shell in dark mode at 120x40","full_description":"Shoko::Adapters::Ui::Components::Screens::SettingsScreenComponent render snapshots renders coherent settings shell in dark mode at 120x40","status":"passed","file_path":"./spec/adapters/ui/components/screens/settings_screen_component_spec.rb","line_number":65,"run_time":0.002736701,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/settings_screen_component_spec.rb[1:4:1]","description":"renders coherent settings shell in dark mode at 80x24","full_description":"Shoko::Adapters::Ui::Components::Screens::SettingsScreenComponent render snapshots renders coherent settings shell in dark mode at 80x24","status":"passed","file_path":"./spec/adapters/ui/components/screens/settings_screen_component_spec.rb","line_number":65,"run_time":0.000861035,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/settings_screen_component_spec.rb[1:4:2]","description":"renders coherent settings shell in light mode at 80x24","full_description":"Shoko::Adapters::Ui::Components::Screens::SettingsScreenComponent render snapshots renders coherent settings shell in light mode at 80x24","status":"passed","file_path":"./spec/adapters/ui/components/screens/settings_screen_component_spec.rb","line_number":65,"run_time":0.001217723,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/settings_screen_component_spec.rb[1:4:4]","description":"renders coherent settings shell in light mode at 120x40","full_description":"Shoko::Adapters::Ui::Components::Screens::SettingsScreenComponent render snapshots renders coherent settings shell in light mode at 120x40","status":"passed","file_path":"./spec/adapters/ui/components/screens/settings_screen_component_spec.rb","line_number":65,"run_time":0.001229014,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch/path_resolution_spec.rb[1:1]","description":"delegates canonical path and source path resolution","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunch::PathResolution delegates canonical path and source path resolution","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch/path_resolution_spec.rb","line_number":28,"run_time":0.000279013,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch/path_resolution_spec.rb[1:2]","description":"validates cache paths through cache pointer resolver","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunch::PathResolution validates cache paths through cache pointer resolver","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch/path_resolution_spec.rb","line_number":33,"run_time":0.000360526,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:1]","description":"creates a valid container","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container creates a valid container","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":16,"run_time":0.000411662,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:7:3]","description":"resolves settings_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container application services resolves settings_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":254,"run_time":0.000670858,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:7:2]","description":"resolves download_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container application services resolves download_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":250,"run_time":0.000231153,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:7:1]","description":"resolves catalog_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container application services resolves catalog_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":246,"run_time":0.00021814,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:4:3]","description":"resolves instrumentation port","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container core ports resolves instrumentation port","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":94,"run_time":0.000220353,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:4:1]","description":"resolves text_metrics port","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container core ports resolves text_metrics port","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":84,"run_time":0.000210565,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:4:4]","description":"resolves async_executor port","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container core ports resolves async_executor port","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":100,"run_time":0.000190667,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:4:6]","description":"resolves data_cleanup port","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container core ports resolves data_cleanup port","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":112,"run_time":0.00019218,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:4:5]","description":"resolves dictionary_storage port","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container core ports resolves dictionary_storage port","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":106,"run_time":0.000182041,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:4:2]","description":"resolves display_capabilities port","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container core ports resolves display_capabilities port","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":89,"run_time":0.000224321,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:2:4]","description":"resolves logger instance","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container infrastructure services resolves logger instance","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":33,"run_time":0.000195347,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:2:2]","description":"resolves global_state","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container infrastructure services resolves global_state","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":25,"run_time":0.000347632,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:2:6]","description":"resolves pagination_cache module","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container infrastructure services resolves pagination_cache module","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":41,"run_time":0.000210906,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:2:1]","description":"resolves event_bus","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container infrastructure services resolves event_bus","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":21,"run_time":0.000181801,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:2:5]","description":"resolves performance_monitor class","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container infrastructure services resolves performance_monitor class","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":37,"run_time":0.000177322,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:2:3]","description":"resolves domain_event_bus","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container infrastructure services resolves domain_event_bus","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":29,"run_time":0.000217919,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:2:7]","description":"resolves cache_paths module","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container infrastructure services resolves cache_paths module","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":45,"run_time":0.000216225,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:6:9]","description":"resolves annotation_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container domain services resolves annotation_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":199,"run_time":0.000369874,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:6:8]","description":"resolves layout_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container domain services resolves layout_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":195,"run_time":0.000195777,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:6:5]","description":"resolves coordinate_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container domain services resolves coordinate_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":183,"run_time":0.000213701,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:6:12]","description":"builds dictionary_repository in auto mode even when sqlite is unavailable","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container domain services builds dictionary_repository in auto mode even when sqlite is unavailable","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":213,"run_time":0.000470112,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:6:3]","description":"resolves navigation_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container domain services resolves navigation_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":175,"run_time":0.00044236,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:6:7]","description":"resolves selection_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container domain services resolves selection_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":191,"run_time":0.000201097,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:6:13]","description":"does not build dictionary_repository when backend is disabled","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container domain services does not build dictionary_repository when backend is disabled","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":219,"run_time":0.000547376,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:6:10]","description":"resolves core_annotation_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container domain services resolves core_annotation_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":203,"run_time":0.000230522,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:6:1]","description":"resolves domain_event_factory","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container domain services resolves domain_event_factory","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":167,"run_time":0.000196609,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:6:6]","description":"resolves popup_position_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container domain services resolves popup_position_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":187,"run_time":0.000365365,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:6:14]","description":"builds dictionary_repository when backend is enabled","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container domain services builds dictionary_repository when backend is enabled","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":227,"run_time":0.00047971,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:6:4]","description":"resolves bookmark_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container domain services resolves bookmark_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":179,"run_time":0.000393077,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:6:15]","description":"builds dictionary_repository when env enables sqlite","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container domain services builds dictionary_repository when env enables sqlite","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":236,"run_time":0.000443121,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:6:2]","description":"resolves page_calculator","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container domain services resolves page_calculator","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":171,"run_time":0.000386214,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:6:11]","description":"builds dictionary_repository in auto mode when sqlite is available","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container domain services builds dictionary_repository in auto mode when sqlite is available","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":207,"run_time":0.000431049,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:8:2]","description":"resolves annotation_repository","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container repository services resolves annotation_repository","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":264,"run_time":0.000195116,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:8:3]","description":"resolves progress_repository","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container repository services resolves progress_repository","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":268,"run_time":0.000199194,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:8:1]","description":"resolves bookmark_repository","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container repository services resolves bookmark_repository","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":260,"run_time":0.000193773,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:10:2]","description":"resolves epub_cache_predicate as callable","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container factory services resolves epub_cache_predicate as callable","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":300,"run_time":0.000183825,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:10:1]","description":"resolves epub_cache_factory as callable","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container factory services resolves epub_cache_factory as callable","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":295,"run_time":0.000183084,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:10:4]","description":"resolves xhtml_parser_factory as callable","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container factory services resolves xhtml_parser_factory as callable","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":310,"run_time":0.000206938,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:10:3]","description":"resolves background_worker_builder as typed port","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container factory services resolves background_worker_builder as typed port","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":305,"run_time":0.000195126,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:10:5]","description":"resolves document_loader as typed port","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container factory services resolves document_loader as typed port","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":315,"run_time":0.000359584,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:12:2]","description":"falls back to XHTML parser when format is absent","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container .build_format_parser_resolver falls back to XHTML parser when format is absent","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":346,"run_time":0.000169508,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:12:1]","description":"uses format-specific parser when chapter metadata keys are strings","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container .build_format_parser_resolver uses format-specific parser when chapter metadata keys are strings","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":336,"run_time":0.000190367,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:11:2]","description":"returns same event_bus instance","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container singleton behavior returns same event_bus instance","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":328,"run_time":0.000283972,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:11:1]","description":"returns same instance for singleton services","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container singleton behavior returns same instance for singleton services","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":322,"run_time":0.000422542,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:9:1]","description":"fails to resolve removed aliases","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container removed compatibility container keys fails to resolve removed aliases","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":275,"run_time":0.000385704,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:3:2]","description":"resolves state_writer adapter","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container hexagonal adapters resolves state_writer adapter","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":56,"run_time":0.000343664,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:3:5]","description":"state_writer implements StateWriter port","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container hexagonal adapters state_writer implements StateWriter port","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":73,"run_time":0.000368821,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:3:4]","description":"config_reader implements ConfigReader port","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container hexagonal adapters config_reader implements ConfigReader port","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":66,"run_time":0.00033588,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:3:3]","description":"resolves rendered_content_reader adapter","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container hexagonal adapters resolves rendered_content_reader adapter","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":61,"run_time":0.000377087,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:3:1]","description":"resolves config_reader adapter","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container hexagonal adapters resolves config_reader adapter","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":51,"run_time":0.000344797,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:5:8]","description":"resolves kitty_image_renderer","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container output services resolves kitty_image_renderer","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":153,"run_time":0.000475231,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:5:2]","description":"resolves terminal_session adapter","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container output services resolves terminal_session adapter","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":124,"run_time":0.000199043,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:5:5]","description":"resolves clipboard_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container output services resolves clipboard_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":136,"run_time":0.000197189,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:5:1]","description":"resolves terminal_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container output services resolves terminal_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":120,"run_time":0.00019761,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:5:3]","description":"resolves wrapping_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container output services resolves wrapping_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":128,"run_time":0.000378149,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:5:6]","description":"resolves notification_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container output services resolves notification_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":140,"run_time":0.000344055,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:5:9]","description":"resolves file_writer","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container output services resolves file_writer","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":157,"run_time":0.000186219,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:5:4]","description":"resolves formatting_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container output services resolves formatting_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":132,"run_time":0.000202299,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:5:7]","description":"wires notification_service to write reader messages","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container output services wires notification_service to write reader messages","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":144,"run_time":0.000456866,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:1:5:10]","description":"resolves instrumentation_service","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.create_default_container output services resolves instrumentation_service","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":161,"run_time":0.000197661,"pending_message":null},{"id":"./spec/application/dependency_container_spec.rb[1:1:2:1]","description":"builds a unified application with injected dependencies","full_description":"Shoko::Bootstrap::DependencyContainer Shoko::Bootstrap::ContainerFactory.build_unified_application builds a unified application with injected dependencies","status":"passed","file_path":"./spec/application/dependency_container_spec.rb","line_number":359,"run_time":0.000461495,"pending_message":null},{"id":"./spec/adapters/runtime/system_wall_clock_adapter_spec.rb[1:1]","description":"returns a UTC Time instance","full_description":"Shoko::Adapters::Runtime::SystemWallClockAdapter returns a UTC Time instance","status":"passed","file_path":"./spec/adapters/runtime/system_wall_clock_adapter_spec.rb","line_number":6,"run_time":0.000074971,"pending_message":null},{"id":"./spec/core/architecture/port_contract_usage_guardrails_spec.rb[1:1]","description":"limits application-layer calls to the declared outbound port methods","full_description":"Outbound port contract usage limits application-layer calls to the declared outbound port methods","status":"passed","file_path":"./spec/core/architecture/port_contract_usage_guardrails_spec.rb","line_number":31,"run_time":0.021856656,"pending_message":null},{"id":"./spec/adapters/output/terminal/terminal_service_spec.rb[1:2]","description":"does not force cleanup when never setup","full_description":"Shoko::Adapters::Output::Terminal::TerminalService does not force cleanup when never setup","status":"passed","file_path":"./spec/adapters/output/terminal/terminal_service_spec.rb","line_number":27,"run_time":0.000431198,"pending_message":null},{"id":"./spec/adapters/output/terminal/terminal_service_spec.rb[1:1]","description":"cleans up only once when cleanup is called multiple times","full_description":"Shoko::Adapters::Output::Terminal::TerminalService cleans up only once when cleanup is called multiple times","status":"passed","file_path":"./spec/adapters/output/terminal/terminal_service_spec.rb","line_number":17,"run_time":0.00035217,"pending_message":null},{"id":"./spec/adapters/output/terminal/terminal_service_spec.rb[1:3]","description":"force cleans up once after setup","full_description":"Shoko::Adapters::Output::Terminal::TerminalService force cleans up once after setup","status":"passed","file_path":"./spec/adapters/output/terminal/terminal_service_spec.rb","line_number":35,"run_time":0.000369904,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch/contracts_spec.rb[1:3]","description":"defines RuntimeExecution and ProgressOrchestration contract methods","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunch::Contracts defines RuntimeExecution and ProgressOrchestration contract methods","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch/contracts_spec.rb","line_number":33,"run_time":0.000156644,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch/contracts_spec.rb[1:2]","description":"defines DocumentPreparation contract methods","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunch::Contracts defines DocumentPreparation contract methods","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch/contracts_spec.rb","line_number":19,"run_time":0.000108834,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch/contracts_spec.rb[1:1]","description":"defines PathResolution contract methods","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunch::Contracts defines PathResolution contract methods","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch/contracts_spec.rb","line_number":12,"run_time":0.000077816,"pending_message":null},{"id":"./spec/application/use_cases/command_bus_spec.rb[1:1]","description":"builds semantic commands from explicit registry entries","full_description":"Shoko::Application::UseCases::CommandBus builds semantic commands from explicit registry entries","status":"passed","file_path":"./spec/application/use_cases/command_bus_spec.rb","line_number":8,"run_time":0.000083186,"pending_message":null},{"id":"./spec/application/use_cases/command_bus_spec.rb[1:2]","description":"builds explicit reader intent commands for adapter actions","full_description":"Shoko::Application::UseCases::CommandBus builds explicit reader intent commands for adapter actions","status":"passed","file_path":"./spec/application/use_cases/command_bus_spec.rb","line_number":14,"run_time":0.00010114,"pending_message":null},{"id":"./spec/application/use_cases/command_bus_spec.rb[1:3]","description":"executes reader intents with typed payload","full_description":"Shoko::Application::UseCases::CommandBus executes reader intents with typed payload","status":"passed","file_path":"./spec/application/use_cases/command_bus_spec.rb","line_number":55,"run_time":0.000129834,"pending_message":null},{"id":"./spec/application/use_cases/command_bus_spec.rb[1:5]","description":"returns :error when semantic command context fails typed contract validation","full_description":"Shoko::Application::UseCases::CommandBus returns :error when semantic command context fails typed contract validation","status":"passed","file_path":"./spec/application/use_cases/command_bus_spec.rb","line_number":106,"run_time":0.000129353,"pending_message":null},{"id":"./spec/application/use_cases/command_bus_spec.rb[1:4]","description":"rejects unknown symbols outside the command whitelist","full_description":"Shoko::Application::UseCases::CommandBus rejects unknown symbols outside the command whitelist","status":"passed","file_path":"./spec/application/use_cases/command_bus_spec.rb","line_number":100,"run_time":0.000073958,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/event_bus_spec.rb[1:1]","description":"delivers emitted events to subscribers","full_description":"Shoko::Adapters::Runtime::SessionState::EventBus delivers emitted events to subscribers","status":"passed","file_path":"./spec/adapters/runtime/session_state/event_bus_spec.rb","line_number":8,"run_time":0.000187762,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/event_bus_spec.rb[1:2]","description":"re-raises subscriber errors","full_description":"Shoko::Adapters::Runtime::SessionState::EventBus re-raises subscriber errors","status":"passed","file_path":"./spec/adapters/runtime/session_state/event_bus_spec.rb","line_number":19,"run_time":0.000157155,"pending_message":null},{"id":"./spec/application/services/pagination/page_info_calculator_spec.rb[1:1]","description":"calculates dynamic single page info","full_description":"Shoko::Application::Services::Pagination::PageInfoCalculator calculates dynamic single page info","status":"passed","file_path":"./spec/application/services/pagination/page_info_calculator_spec.rb","line_number":46,"run_time":0.000311333,"pending_message":null},{"id":"./spec/application/services/pagination/page_info_calculator_spec.rb[1:3]","description":"calls pagination orchestrator session with strict split-port keywords in absolute mode","full_description":"Shoko::Application::Services::Pagination::PageInfoCalculator calls pagination orchestrator session with strict split-port keywords in absolute mode","status":"passed","file_path":"./spec/application/services/pagination/page_info_calculator_spec.rb","line_number":88,"run_time":0.000364062,"pending_message":null},{"id":"./spec/application/services/pagination/page_info_calculator_spec.rb[1:2]","description":"calculates absolute split page info and builds page map when needed","full_description":"Shoko::Application::Services::Pagination::PageInfoCalculator calculates absolute split page info and builds page map when needed","status":"passed","file_path":"./spec/application/services/pagination/page_info_calculator_spec.rb","line_number":63,"run_time":0.000364513,"pending_message":null},{"id":"./spec/adapters/storage/pagination_cache_spec.rb[1:2:2]","description":"defaults to :base for legacy keys without layout variant","full_description":"Shoko::Adapters::Storage::PaginationCache.parse_layout_key defaults to :base for legacy keys without layout variant","status":"passed","file_path":"./spec/adapters/storage/pagination_cache_spec.rb","line_number":28,"run_time":0.000088727,"pending_message":null},{"id":"./spec/adapters/storage/pagination_cache_spec.rb[1:2:1]","description":"parses keys with explicit layout variants","full_description":"Shoko::Adapters::Storage::PaginationCache.parse_layout_key parses keys with explicit layout variants","status":"passed","file_path":"./spec/adapters/storage/pagination_cache_spec.rb","line_number":15,"run_time":0.000065693,"pending_message":null},{"id":"./spec/adapters/storage/pagination_cache_spec.rb[1:1:1]","description":"includes layout variant and image mode in generated keys","full_description":"Shoko::Adapters::Storage::PaginationCache.layout_key includes layout variant and image mode in generated keys","status":"passed","file_path":"./spec/adapters/storage/pagination_cache_spec.rb","line_number":7,"run_time":0.000058359,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch_service_spec.rb[1:4]","description":"delegates run_reader to runtime execution with ensure callback","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunchService delegates run_reader to runtime execution with ensure callback","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch_service_spec.rb","line_number":127,"run_time":0.001499682,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch_service_spec.rb[1:2]","description":"reports file not found for missing selected book path","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunchService reports file not found for missing selected book path","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch_service_spec.rb","line_number":114,"run_time":0.000687269,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch_service_spec.rb[1:1]","description":"opens selected book through progress flow when file exists","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunchService opens selected book through progress flow when file exists","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch_service_spec.rb","line_number":107,"run_time":0.000579357,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch_service_spec.rb[1:6]","description":"delegates cache path validation to path resolution","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunchService delegates cache path validation to path resolution","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch_service_spec.rb","line_number":144,"run_time":0.00052772,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch_service_spec.rb[1:5]","description":"delegates load_and_open_with_progress to progress orchestration","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunchService delegates load_and_open_with_progress to progress orchestration","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch_service_spec.rb","line_number":135,"run_time":0.000552456,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch_service_spec.rb[1:8]","description":"rejects untyped collaborators during dependency validation","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunchService rejects untyped collaborators during dependency validation","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch_service_spec.rb","line_number":158,"run_time":0.000603011,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch_service_spec.rb[1:3]","description":"delegates open_book to progress flow when file exists","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunchService delegates open_book to progress flow when file exists","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch_service_spec.rb","line_number":122,"run_time":0.000610235,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch_service_spec.rb[1:7]","description":"delegates ensure_reader_document_for through document preparation","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunchService delegates ensure_reader_document_for through document preparation","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch_service_spec.rb","line_number":148,"run_time":0.000561432,"pending_message":null},{"id":"./spec/adapters/output/notification_service_spec.rb[1:1:1]","description":"shows messages through the injected notification writer","full_description":"Shoko::Adapters::Output::NotificationService#set_message shows messages through the injected notification writer","status":"passed","file_path":"./spec/adapters/output/notification_service_spec.rb","line_number":9,"run_time":0.000261731,"pending_message":null},{"id":"./spec/adapters/output/notification_service_spec.rb[1:1:2]","description":"clears immediately when duration is zero","full_description":"Shoko::Adapters::Output::NotificationService#set_message clears immediately when duration is zero","status":"passed","file_path":"./spec/adapters/output/notification_service_spec.rb","line_number":18,"run_time":0.000211837,"pending_message":null},{"id":"./spec/adapters/output/notification_service_spec.rb[1:2:1]","description":"clears elapsed messages","full_description":"Shoko::Adapters::Output::NotificationService#tick clears elapsed messages","status":"passed","file_path":"./spec/adapters/output/notification_service_spec.rb","line_number":31,"run_time":0.000274465,"pending_message":null},{"id":"./spec/application/workflows/menu/download_workflow_spec.rb[1:1]","description":"requires menu_runtime","full_description":"Shoko::Application::Workflows::Menu::DownloadWorkflow requires menu_runtime","status":"passed","file_path":"./spec/application/workflows/menu/download_workflow_spec.rb","line_number":41,"run_time":0.000416,"pending_message":null},{"id":"./spec/application/workflows/menu/download_workflow_spec.rb[1:2:1]","description":"refreshes catalog scan through runtime bridge after successful download","full_description":"Shoko::Application::Workflows::Menu::DownloadWorkflow#download_book refreshes catalog scan through runtime bridge after successful download","status":"passed","file_path":"./spec/application/workflows/menu/download_workflow_spec.rb","line_number":55,"run_time":0.00055453,"pending_message":null},{"id":"./spec/core/services/layout_service_spec.rb[1:5]","description":"calculates sidebar width with a minimum threshold","full_description":"Shoko::Core::Services::LayoutService calculates sidebar width with a minimum threshold","status":"passed","file_path":"./spec/core/services/layout_service_spec.rb","line_number":31,"run_time":0.000073197,"pending_message":null},{"id":"./spec/core/services/layout_service_spec.rb[1:2]","description":"adjusts height for relaxed line spacing","full_description":"Shoko::Core::Services::LayoutService adjusts height for relaxed line spacing","status":"passed","file_path":"./spec/core/services/layout_service_spec.rb","line_number":14,"run_time":0.000058279,"pending_message":null},{"id":"./spec/core/services/layout_service_spec.rb[1:4]","description":"reduces effective content width when sidebar is visible","full_description":"Shoko::Core::Services::LayoutService reduces effective content width when sidebar is visible","status":"passed","file_path":"./spec/core/services/layout_service_spec.rb","line_number":23,"run_time":0.000058209,"pending_message":null},{"id":"./spec/core/services/layout_service_spec.rb[1:3]","description":"calculates centered padding without going negative","full_description":"Shoko::Core::Services::LayoutService calculates centered padding without going negative","status":"passed","file_path":"./spec/core/services/layout_service_spec.rb","line_number":18,"run_time":0.00005376,"pending_message":null},{"id":"./spec/core/services/layout_service_spec.rb[1:1]","description":"calculates metrics for split view","full_description":"Shoko::Core::Services::LayoutService calculates metrics for split view","status":"passed","file_path":"./spec/core/services/layout_service_spec.rb","line_number":8,"run_time":0.000066434,"pending_message":null},{"id":"./spec/core/architecture/controller_composition_guardrails_spec.rb[1:1]","description":"allows reader controller graph construction only in bootstrap composition","full_description":"Controller composition boundaries allows reader controller graph construction only in bootstrap composition","status":"passed","file_path":"./spec/core/architecture/controller_composition_guardrails_spec.rb","line_number":25,"run_time":3.992934114,"pending_message":null},{"id":"./spec/adapters/output/formatting/format_parity_golden_spec.rb[1:1]","description":"renders equivalent heading/quote/paragraph structure for epub, fb2, pdf, rtf, and kindle","full_description":"Formatting parity across book formats renders equivalent heading/quote/paragraph structure for epub, fb2, pdf, rtf, and kindle","status":"passed","file_path":"./spec/adapters/output/formatting/format_parity_golden_spec.rb","line_number":42,"run_time":0.004034856,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/reader_launch_state_adapter_spec.rb[1:1]","description":"stores and clears the preloaded document","full_description":"Shoko::Adapters::Runtime::SessionState::ReaderLaunchStateAdapter stores and clears the preloaded document","status":"passed","file_path":"./spec/adapters/runtime/session_state/reader_launch_state_adapter_spec.rb","line_number":8,"run_time":0.000105278,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/reader_launch_state_adapter_spec.rb[1:2]","description":"stores and clears the background worker","full_description":"Shoko::Adapters::Runtime::SessionState::ReaderLaunchStateAdapter stores and clears the background worker","status":"passed","file_path":"./spec/adapters/runtime/session_state/reader_launch_state_adapter_spec.rb","line_number":18,"run_time":0.000082385,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/annotations_screen_component_spec.rb[1:2]","description":"renders list workspace and preview for selected annotation","full_description":"Shoko::Adapters::Ui::Components::Screens::AnnotationsScreenComponent renders list workspace and preview for selected annotation","status":"passed","file_path":"./spec/adapters/ui/components/screens/annotations_screen_component_spec.rb","line_number":59,"run_time":0.002224752,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/annotations_screen_component_spec.rb[1:1]","description":"renders an empty state without raising","full_description":"Shoko::Adapters::Ui::Components::Screens::AnnotationsScreenComponent renders an empty state without raising","status":"passed","file_path":"./spec/adapters/ui/components/screens/annotations_screen_component_spec.rb","line_number":47,"run_time":0.000273222,"pending_message":null},{"id":"./spec/adapters/ui/components/menu_design/status_renderer_spec.rb[1:1]","description":"right-aligns status text within the provided content width","full_description":"Shoko::Adapters::Ui::Components::MenuDesign::StatusRenderer right-aligns status text within the provided content width","status":"passed","file_path":"./spec/adapters/ui/components/menu_design/status_renderer_spec.rb","line_number":14,"run_time":0.000258205,"pending_message":null},{"id":"./spec/adapters/book_sources/cache_import_adapter_spec.rb[1:1]","description":"returns :skipped when document is already cached","full_description":"Shoko::Adapters::BookSources::CacheImportAdapter returns :skipped when document is already cached","status":"passed","file_path":"./spec/adapters/book_sources/cache_import_adapter_spec.rb","line_number":15,"run_time":0.000313598,"pending_message":null},{"id":"./spec/adapters/book_sources/cache_import_adapter_spec.rb[1:4]","description":"propagates importer failures for workflow-level aggregation","full_description":"Shoko::Adapters::BookSources::CacheImportAdapter propagates importer failures for workflow-level aggregation","status":"passed","file_path":"./spec/adapters/book_sources/cache_import_adapter_spec.rb","line_number":45,"run_time":0.000195988,"pending_message":null},{"id":"./spec/adapters/book_sources/cache_import_adapter_spec.rb[1:2]","description":"returns :imported when document is newly built","full_description":"Shoko::Adapters::BookSources::CacheImportAdapter returns :imported when document is newly built","status":"passed","file_path":"./spec/adapters/book_sources/cache_import_adapter_spec.rb","line_number":25,"run_time":0.00019203,"pending_message":null},{"id":"./spec/adapters/book_sources/cache_import_adapter_spec.rb[1:3]","description":"propagates BookParseError when the document service raises malformed-book input","full_description":"Shoko::Adapters::BookSources::CacheImportAdapter propagates BookParseError when the document service raises malformed-book input","status":"passed","file_path":"./spec/adapters/book_sources/cache_import_adapter_spec.rb","line_number":35,"run_time":0.000200265,"pending_message":null},{"id":"./spec/core/services/pagination/internal/absolute_page_map_builder_spec.rb[1:1]","description":"uses text metrics fallback wrapping when wrapper is nil","full_description":"Shoko::Core::Services::Pagination::Internal::AbsolutePageMapBuilder uses text metrics fallback wrapping when wrapper is nil","status":"passed","file_path":"./spec/core/services/pagination/internal/absolute_page_map_builder_spec.rb","line_number":25,"run_time":0.000226034,"pending_message":null},{"id":"./spec/core/services/pagination/internal/absolute_page_map_builder_spec.rb[1:2]","description":"raises when neither wrapper nor text metrics are provided","full_description":"Shoko::Core::Services::Pagination::Internal::AbsolutePageMapBuilder raises when neither wrapper nor text metrics are provided","status":"passed","file_path":"./spec/core/services/pagination/internal/absolute_page_map_builder_spec.rb","line_number":37,"run_time":0.000097252,"pending_message":null},{"id":"./spec/core/architecture/no_bare_string_raise_spec.rb[1:1]","description":"forbids raise with string literals in lib/shoko runtime sources","full_description":"No bare string raises in runtime code forbids raise with string literals in lib/shoko runtime sources","status":"passed","file_path":"./spec/core/architecture/no_bare_string_raise_spec.rb","line_number":9,"run_time":0.035064373,"pending_message":null},{"id":"./spec/core/architecture/no_cross_adapter_runtime_coupling_spec.rb[1:1]","description":"forbids output adapters from referencing runtime adapter namespace directly","full_description":"No cross-adapter runtime coupling forbids output adapters from referencing runtime adapter namespace directly","status":"passed","file_path":"./spec/core/architecture/no_cross_adapter_runtime_coupling_spec.rb","line_number":13,"run_time":0.00075193,"pending_message":null},{"id":"./spec/core/architecture/no_cross_adapter_runtime_coupling_spec.rb[1:2]","description":"forbids document loader adapter from direct storage pipeline construction","full_description":"No cross-adapter runtime coupling forbids document loader adapter from direct storage pipeline construction","status":"passed","file_path":"./spec/core/architecture/no_cross_adapter_runtime_coupling_spec.rb","line_number":25,"run_time":0.000115196,"pending_message":null},{"id":"./spec/adapters/storage/json_cache_store_manifest_cache_spec.rb[1:3]","description":"reads manifest file every time when cache is disabled","full_description":"Shoko::Adapters::Storage::JsonCacheStore reads manifest file every time when cache is disabled","status":"passed","file_path":"./spec/adapters/storage/json_cache_store_manifest_cache_spec.rb","line_number":57,"run_time":0.000625153,"pending_message":null},{"id":"./spec/adapters/storage/json_cache_store_manifest_cache_spec.rb[1:1]","description":"returns identical manifest rows with cache enabled and disabled","full_description":"Shoko::Adapters::Storage::JsonCacheStore returns identical manifest rows with cache enabled and disabled","status":"passed","file_path":"./spec/adapters/storage/json_cache_store_manifest_cache_spec.rb","line_number":33,"run_time":0.00027726,"pending_message":null},{"id":"./spec/adapters/storage/json_cache_store_manifest_cache_spec.rb[1:2]","description":"reads manifest file once when cache is enabled","full_description":"Shoko::Adapters::Storage::JsonCacheStore reads manifest file once when cache is enabled","status":"passed","file_path":"./spec/adapters/storage/json_cache_store_manifest_cache_spec.rb","line_number":45,"run_time":0.000397426,"pending_message":null},{"id":"./spec/adapters/ui/components/sidebar/toc/entries_calculator_spec.rb[1:2]","description":"keeps matching entry ancestors when filter is active","full_description":"Shoko::Adapters::Ui::Components::Sidebar::EntriesCalculator keeps matching entry ancestors when filter is active","status":"passed","file_path":"./spec/adapters/ui/components/sidebar/toc/entries_calculator_spec.rb","line_number":109,"run_time":0.000320932,"pending_message":null},{"id":"./spec/adapters/ui/components/sidebar/toc/entries_calculator_spec.rb[1:4]","description":"clamps selected index and maps visible index safely","full_description":"Shoko::Adapters::Ui::Components::Sidebar::EntriesCalculator clamps selected index and maps visible index safely","status":"passed","file_path":"./spec/adapters/ui/components/sidebar/toc/entries_calculator_spec.rb","line_number":139,"run_time":0.000195176,"pending_message":null},{"id":"./spec/adapters/ui/components/sidebar/toc/entries_calculator_spec.rb[1:1]","description":"builds fallback entries from chapters when TOC is empty","full_description":"Shoko::Adapters::Ui::Components::Sidebar::EntriesCalculator builds fallback entries from chapters when TOC is empty","status":"passed","file_path":"./spec/adapters/ui/components/sidebar/toc/entries_calculator_spec.rb","line_number":97,"run_time":0.000205816,"pending_message":null},{"id":"./spec/adapters/ui/components/sidebar/toc/entries_calculator_spec.rb[1:3]","description":"does not apply collapse filtering when filter is active","full_description":"Shoko::Adapters::Ui::Components::Sidebar::EntriesCalculator does not apply collapse filtering when filter is active","status":"passed","file_path":"./spec/adapters/ui/components/sidebar/toc/entries_calculator_spec.rb","line_number":125,"run_time":0.000189526,"pending_message":null},{"id":"./spec/core/services/page_calculator_service_spec.rb[1:2]","description":"maps current line offset to a valid page in the switched sidebar variant","full_description":"Shoko::Core::Services::PageCalculatorService maps current line offset to a valid page in the switched sidebar variant","status":"passed","file_path":"./spec/core/services/page_calculator_service_spec.rb","line_number":109,"run_time":0.00225049,"pending_message":null},{"id":"./spec/core/services/page_calculator_service_spec.rb[1:1]","description":"precomputes sidebar variant and switches without rebuilding wrapped lines","full_description":"Shoko::Core::Services::PageCalculatorService precomputes sidebar variant and switches without rebuilding wrapped lines","status":"passed","file_path":"./spec/core/services/page_calculator_service_spec.rb","line_number":80,"run_time":0.000488546,"pending_message":null},{"id":"./spec/adapters/output/terminal/input/decoder_spec.rb[1:2]","description":"waits for the full X10 mouse sequence before emitting a token","full_description":"Shoko::Adapters::Output::Terminal::TerminalInput::Decoder waits for the full X10 mouse sequence before emitting a token","status":"passed","file_path":"./spec/adapters/output/terminal/input/decoder_spec.rb","line_number":19,"run_time":0.000127469,"pending_message":null},{"id":"./spec/adapters/output/terminal/input/decoder_spec.rb[1:1]","description":"returns a full X10 mouse sequence as a single token","full_description":"Shoko::Adapters::Output::Terminal::TerminalInput::Decoder returns a full X10 mouse sequence as a single token","status":"passed","file_path":"./spec/adapters/output/terminal/input/decoder_spec.rb","line_number":6,"run_time":0.000079889,"pending_message":null},{"id":"./spec/adapters/output/terminal/input/decoder_spec.rb[1:3]","description":"normalizes 8-bit CSI X10 mouse sequences to ESC-prefixed tokens","full_description":"Shoko::Adapters::Output::Terminal::TerminalInput::Decoder normalizes 8-bit CSI X10 mouse sequences to ESC-prefixed tokens","status":"passed","file_path":"./spec/adapters/output/terminal/input/decoder_spec.rb","line_number":31,"run_time":0.000079048,"pending_message":null},{"id":"./spec/core/book_formats/kindle/pdb_header_parser_spec.rb[1:2]","description":"parses the correct number of records","full_description":"Shoko::Core::BookFormats::Kindle::PdbHeaderParser parses the correct number of records","status":"passed","file_path":"./spec/core/book_formats/kindle/pdb_header_parser_spec.rb","line_number":52,"run_time":0.000089818,"pending_message":null},{"id":"./spec/core/book_formats/kindle/pdb_header_parser_spec.rb[1:4]","description":"reports correct record sizes","full_description":"Shoko::Core::BookFormats::Kindle::PdbHeaderParser reports correct record sizes","status":"passed","file_path":"./spec/core/book_formats/kindle/pdb_header_parser_spec.rb","line_number":69,"run_time":0.000079779,"pending_message":null},{"id":"./spec/core/book_formats/kindle/pdb_header_parser_spec.rb[1:3]","description":"extracts record data by index","full_description":"Shoko::Core::BookFormats::Kindle::PdbHeaderParser extracts record data by index","status":"passed","file_path":"./spec/core/book_formats/kindle/pdb_header_parser_spec.rb","line_number":59,"run_time":0.000086182,"pending_message":null},{"id":"./spec/core/book_formats/kindle/pdb_header_parser_spec.rb[1:1]","description":"parses PDB header name, type, and creator","full_description":"Shoko::Core::BookFormats::Kindle::PdbHeaderParser parses PDB header name, type, and creator","status":"passed","file_path":"./spec/core/book_formats/kindle/pdb_header_parser_spec.rb","line_number":43,"run_time":0.000143028,"pending_message":null},{"id":"./spec/core/book_formats/kindle/pdb_header_parser_spec.rb[1:6]","description":"raises on truncated file","full_description":"Shoko::Core::BookFormats::Kindle::PdbHeaderParser raises on truncated file","status":"passed","file_path":"./spec/core/book_formats/kindle/pdb_header_parser_spec.rb","line_number":86,"run_time":0.000102432,"pending_message":null},{"id":"./spec/core/book_formats/kindle/pdb_header_parser_spec.rb[1:5]","description":"raises on out-of-range record index","full_description":"Shoko::Core::BookFormats::Kindle::PdbHeaderParser raises on out-of-range record index","status":"passed","file_path":"./spec/core/book_formats/kindle/pdb_header_parser_spec.rb","line_number":79,"run_time":0.00009084,"pending_message":null},{"id":"./spec/core/book_formats/fb2/fb2_content_parser_spec.rb[1:2]","description":"centers subtitles","full_description":"Shoko::Core::BookFormats::Fb2::Fb2ContentParser centers subtitles","status":"passed","file_path":"./spec/core/book_formats/fb2/fb2_content_parser_spec.rb","line_number":41,"run_time":0.00028279,"pending_message":null},{"id":"./spec/core/book_formats/fb2/fb2_content_parser_spec.rb[1:1]","description":"maps title, epigraph, and attribution to aligned semantic blocks","full_description":"Shoko::Core::BookFormats::Fb2::Fb2ContentParser maps title, epigraph, and attribution to aligned semantic blocks","status":"passed","file_path":"./spec/core/book_formats/fb2/fb2_content_parser_spec.rb","line_number":6,"run_time":0.000430257,"pending_message":null},{"id":"./spec/core/book_formats/rtf/metadata_parser_spec.rb[1:1:1]","description":"extracts canonical metadata from info and content heuristics","full_description":"Shoko::Core::BookFormats::Rtf::MetadataParser.parse extracts canonical metadata from info and content heuristics","status":"passed","file_path":"./spec/core/book_formats/rtf/metadata_parser_spec.rb","line_number":12,"run_time":0.00012249,"pending_message":null},{"id":"./spec/core/book_formats/rtf/metadata_parser_spec.rb[1:2:2]","description":"is used by RtfImporter metadata extraction and preserves author_str","full_description":"Shoko::Core::BookFormats::Rtf::MetadataParser delegation is used by RtfImporter metadata extraction and preserves author_str","status":"passed","file_path":"./spec/core/book_formats/rtf/metadata_parser_spec.rb","line_number":83,"run_time":0.000323617,"pending_message":null},{"id":"./spec/core/book_formats/rtf/metadata_parser_spec.rb[1:2:1]","description":"is used by RtfMetadataExtractor and preserves author_str","full_description":"Shoko::Core::BookFormats::Rtf::MetadataParser delegation is used by RtfMetadataExtractor and preserves author_str","status":"passed","file_path":"./spec/core/book_formats/rtf/metadata_parser_spec.rb","line_number":38,"run_time":0.000539682,"pending_message":null},{"id":"./spec/core/ports/outbound/zero_fallback_ports_spec.rb[1:2]","description":"defines BackgroundWorkerBuilder contract method","full_description":"Zero fallback outbound port contracts defines BackgroundWorkerBuilder contract method","status":"passed","file_path":"./spec/core/ports/outbound/zero_fallback_ports_spec.rb","line_number":20,"run_time":0.000092313,"pending_message":null},{"id":"./spec/core/ports/outbound/zero_fallback_ports_spec.rb[1:3]","description":"defines ProgressRepository contract methods","full_description":"Zero fallback outbound port contracts defines ProgressRepository contract methods","status":"passed","file_path":"./spec/core/ports/outbound/zero_fallback_ports_spec.rb","line_number":28,"run_time":0.000124894,"pending_message":null},{"id":"./spec/core/ports/outbound/zero_fallback_ports_spec.rb[1:1]","description":"defines DocumentLoader contract method","full_description":"Zero fallback outbound port contracts defines DocumentLoader contract method","status":"passed","file_path":"./spec/core/ports/outbound/zero_fallback_ports_spec.rb","line_number":12,"run_time":0.000070022,"pending_message":null},{"id":"./spec/adapters/book_sources/book_document_cleanup_spec.rb[1:1]","description":"removes dead private helper APIs no longer used by render/import paths","full_description":"Shoko::Adapters::BookSources::BookDocument removes dead private helper APIs no longer used by render/import paths","status":"passed","file_path":"./spec/adapters/book_sources/book_document_cleanup_spec.rb","line_number":8,"run_time":0.000216356,"pending_message":null},{"id":"./spec/adapters/book_sources/book_document_cleanup_spec.rb[1:2]","description":"still formats chapters through active formatting path","full_description":"Shoko::Adapters::BookSources::BookDocument still formats chapters through active formatting path","status":"passed","file_path":"./spec/adapters/book_sources/book_document_cleanup_spec.rb","line_number":16,"run_time":0.000353893,"pending_message":null},{"id":"./spec/adapters/book_sources/book_document_cleanup_spec.rb[1:3]","description":"allows image-only or blank chapters that produce zero lines after formatting","full_description":"Shoko::Adapters::BookSources::BookDocument allows image-only or blank chapters that produce zero lines after formatting","status":"passed","file_path":"./spec/adapters/book_sources/book_document_cleanup_spec.rb","line_number":69,"run_time":0.000307546,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_entry_formatter_spec.rb[1:2:1]","description":"formats fuzzy matches","full_description":"Shoko::Adapters::Ui::Components::Dictionary::EntryFormatter#format_fuzzy_results formats fuzzy matches","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_entry_formatter_spec.rb","line_number":85,"run_time":0.000117521,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_entry_formatter_spec.rb[1:2:2]","description":"falls back to not found when no matches","full_description":"Shoko::Adapters::Ui::Components::Dictionary::EntryFormatter#format_fuzzy_results falls back to not found when no matches","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_entry_formatter_spec.rb","line_number":95,"run_time":0.000068428,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_entry_formatter_spec.rb[1:1:4]","description":"formats unavailable results","full_description":"Shoko::Adapters::Ui::Components::Dictionary::EntryFormatter#format_result formats unavailable results","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_entry_formatter_spec.rb","line_number":61,"run_time":0.000078818,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_entry_formatter_spec.rb[1:1:3]","description":"formats not found results","full_description":"Shoko::Adapters::Ui::Components::Dictionary::EntryFormatter#format_result formats not found results","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_entry_formatter_spec.rb","line_number":55,"run_time":0.000063148,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_entry_formatter_spec.rb[1:1:5]","description":"formats error results","full_description":"Shoko::Adapters::Ui::Components::Dictionary::EntryFormatter#format_result formats error results","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_entry_formatter_spec.rb","line_number":73,"run_time":0.00006355,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_entry_formatter_spec.rb[1:1:2]","description":"includes result position when entry_index is provided","full_description":"Shoko::Adapters::Ui::Components::Dictionary::EntryFormatter#format_result includes result position when entry_index is provided","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_entry_formatter_spec.rb","line_number":41,"run_time":0.000108273,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_entry_formatter_spec.rb[1:1:1]","description":"formats entries with header and footer","full_description":"Shoko::Adapters::Ui::Components::Dictionary::EntryFormatter#format_result formats entries with header and footer","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_entry_formatter_spec.rb","line_number":30,"run_time":0.000092664,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/state_controller_spec.rb[1:2]","description":"delegates workflow actions to composed workflows","full_description":"Shoko::Adapters::Input::Controllers::Menu::StateController delegates workflow actions to composed workflows","status":"passed","file_path":"./spec/adapters/input/controllers/menu/state_controller_spec.rb","line_number":68,"run_time":0.000571372,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/state_controller_spec.rb[1:1]","description":"delegates reader actions to reader launch service","full_description":"Shoko::Adapters::Input::Controllers::Menu::StateController delegates reader actions to reader launch service","status":"passed","file_path":"./spec/adapters/input/controllers/menu/state_controller_spec.rb","line_number":48,"run_time":0.000464682,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/state_controller_spec.rb[1:3]","description":"refreshes catalog scan through catalog service","full_description":"Shoko::Adapters::Input::Controllers::Menu::StateController refreshes catalog scan through catalog service","status":"passed","file_path":"./spec/adapters/input/controllers/menu/state_controller_spec.rb","line_number":88,"run_time":0.000466915,"pending_message":null},{"id":"./spec/core/book_formats/fb2/fb2_importer_spec.rb[1:1]","description":"does not extract binary resources by default","full_description":"Shoko::Adapters::BookSources::Fb2::Fb2Importer does not extract binary resources by default","status":"passed","file_path":"./spec/core/book_formats/fb2/fb2_importer_spec.rb","line_number":36,"run_time":0.001925991,"pending_message":null},{"id":"./spec/core/book_formats/fb2/fb2_importer_spec.rb[1:2]","description":"extracts binary resources when extract_resources is enabled","full_description":"Shoko::Adapters::BookSources::Fb2::Fb2Importer extracts binary resources when extract_resources is enabled","status":"passed","file_path":"./spec/core/book_formats/fb2/fb2_importer_spec.rb","line_number":45,"run_time":0.001491256,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/render_state_writer_adapter_spec.rb[1:3:1]","description":"includes RenderStateWriter port","full_description":"Shoko::Adapters::Runtime::SessionState::RenderStateWriterAdapter port compliance includes RenderStateWriter port","status":"passed","file_path":"./spec/adapters/runtime/session_state/render_state_writer_adapter_spec.rb","line_number":61,"run_time":0.000187712,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/render_state_writer_adapter_spec.rb[1:1:1]","description":"dispatches ClearRenderedLinesAction","full_description":"Shoko::Adapters::Runtime::SessionState::RenderStateWriterAdapter#clear_rendered_lines dispatches ClearRenderedLinesAction","status":"passed","file_path":"./spec/adapters/runtime/session_state/render_state_writer_adapter_spec.rb","line_number":15,"run_time":0.00022386,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/render_state_writer_adapter_spec.rb[1:1:2:1]","description":"logs and re-raises the error","full_description":"Shoko::Adapters::Runtime::SessionState::RenderStateWriterAdapter#clear_rendered_lines when dispatch raises an error logs and re-raises the error","status":"passed","file_path":"./spec/adapters/runtime/session_state/render_state_writer_adapter_spec.rb","line_number":26,"run_time":0.000562234,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/render_state_writer_adapter_spec.rb[1:2:1]","description":"dispatches UpdateRenderedLinesAction with the lines","full_description":"Shoko::Adapters::Runtime::SessionState::RenderStateWriterAdapter#update_rendered_lines dispatches UpdateRenderedLinesAction with the lines","status":"passed","file_path":"./spec/adapters/runtime/session_state/render_state_writer_adapter_spec.rb","line_number":39,"run_time":0.000192221,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/render_state_writer_adapter_spec.rb[1:2:2:1]","description":"logs and re-raises the error","full_description":"Shoko::Adapters::Runtime::SessionState::RenderStateWriterAdapter#update_rendered_lines when dispatch raises an error logs and re-raises the error","status":"passed","file_path":"./spec/adapters/runtime/session_state/render_state_writer_adapter_spec.rb","line_number":50,"run_time":0.000425137,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/menu_workflow_bridges_spec.rb[3:1]","description":"delegates annotation view refresh to the menu workflow API","full_description":"Shoko::Adapters::Input::Controllers::Menu::AnnotationViewRefreshBridge delegates annotation view refresh to the menu workflow API","status":"passed","file_path":"./spec/adapters/input/controllers/menu/menu_workflow_bridges_spec.rb","line_number":54,"run_time":0.000137277,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb[1:5]","description":"keeps state store orchestration free from direct JSON/file persistence logic","full_description":"Hexagonal hardening guardrails keeps state store orchestration free from direct JSON/file persistence logic","status":"passed","file_path":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb","line_number":68,"run_time":0.000210645,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb[1:6]","description":"forbids initialize(**deps) constructors in menu controllers and workflows","full_description":"Hexagonal hardening guardrails forbids initialize(**deps) constructors in menu controllers and workflows","status":"passed","file_path":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb","line_number":84,"run_time":0.001452433,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb[1:1]","description":"forbids deprecated UI-shaped core menu ports in application layer","full_description":"Hexagonal hardening guardrails forbids deprecated UI-shaped core menu ports in application layer","status":"passed","file_path":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb","line_number":21,"run_time":0.006895681,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb[1:10]","description":"forbids Rouge references in runtime source until highlighting port decision is approved","full_description":"Hexagonal hardening guardrails forbids Rouge references in runtime source until highlighting port decision is approved","status":"passed","file_path":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb","line_number":152,"run_time":0.037644361,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb[1:9]","description":"contains hardcoded keyword highlighting to approved rendering files only","full_description":"Hexagonal hardening guardrails contains hardcoded keyword highlighting to approved rendering files only","status":"passed","file_path":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb","line_number":133,"run_time":0.032328342,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb[1:2]","description":"forbids private helper dispatch via menu.send in bootstrap menu composition","full_description":"Hexagonal hardening guardrails forbids private helper dispatch via menu.send in bootstrap menu composition","status":"passed","file_path":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb","line_number":43,"run_time":0.00025596,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb[1:4]","description":"forbids respond_to? collaborator validation in ReaderLaunchService dependencies","full_description":"Hexagonal hardening guardrails forbids respond_to? collaborator validation in ReaderLaunchService dependencies","status":"passed","file_path":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb","line_number":60,"run_time":0.000155021,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb[1:8]","description":"requires explicit resilient-boundary annotation for broad rescues in hardening scope","full_description":"Hexagonal hardening guardrails requires explicit resilient-boundary annotation for broad rescues in hardening scope","status":"passed","file_path":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb","line_number":111,"run_time":0.002521518,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb[1:7]","description":"forbids direct File/Process usage in application layer","full_description":"Hexagonal hardening guardrails forbids direct File/Process usage in application layer","status":"passed","file_path":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb","line_number":92,"run_time":0.002626956,"pending_message":null},{"id":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb[1:3]","description":"forbids respond_to? capability checks in application command use-cases","full_description":"Hexagonal hardening guardrails forbids respond_to? capability checks in application command use-cases","status":"passed","file_path":"./spec/core/architecture/hexagonal_hardening_guardrails_spec.rb","line_number":51,"run_time":0.000465833,"pending_message":null},{"id":"./spec/adapters/book_sources/source_fingerprint_spec.rb[1:4]","description":"falls back to default chunk size when chunk_bytes is invalid","full_description":"Shoko::Shared::SourceFingerprint falls back to default chunk size when chunk_bytes is invalid","status":"passed","file_path":"./spec/adapters/book_sources/source_fingerprint_spec.rb","line_number":48,"run_time":0.000598011,"pending_message":null},{"id":"./spec/adapters/book_sources/source_fingerprint_spec.rb[1:2]","description":"returns nil when the source file is not present","full_description":"Shoko::Shared::SourceFingerprint returns nil when the source file is not present","status":"passed","file_path":"./spec/adapters/book_sources/source_fingerprint_spec.rb","line_number":31,"run_time":0.000162625,"pending_message":null},{"id":"./spec/adapters/book_sources/source_fingerprint_spec.rb[1:3]","description":"changes when head or tail content changes","full_description":"Shoko::Shared::SourceFingerprint changes when head or tail content changes","status":"passed","file_path":"./spec/adapters/book_sources/source_fingerprint_spec.rb","line_number":37,"run_time":0.002761068,"pending_message":null},{"id":"./spec/adapters/book_sources/source_fingerprint_spec.rb[1:1]","description":"returns deterministic fingerprints for the same file","full_description":"Shoko::Shared::SourceFingerprint returns deterministic fingerprints for the same file","status":"passed","file_path":"./spec/adapters/book_sources/source_fingerprint_spec.rb","line_number":21,"run_time":0.001473162,"pending_message":null},{"id":"./spec/adapters/input/controllers/ui_controller_spec.rb[1:1]","description":"allows close_dictionary to be called with a key argument","full_description":"Shoko::Adapters::Input::Controllers::UIController allows close_dictionary to be called with a key argument","status":"passed","file_path":"./spec/adapters/input/controllers/ui_controller_spec.rb","line_number":67,"run_time":0.000647754,"pending_message":null},{"id":"./spec/core/architecture/no_noop_reraise_rescue_spec.rb[1:1]","description":"forbids rescue branches that only re-raise without translation or context","full_description":"No no-op re-raise rescues forbids rescue branches that only re-raise without translation or context","status":"passed","file_path":"./spec/core/architecture/no_noop_reraise_rescue_spec.rb","line_number":16,"run_time":0.056218241,"pending_message":null},{"id":"./spec/core/book_formats/kindle/metadata_parser_spec.rb[1:2:2]","description":"is used by KindleImporter metadata extraction and preserves author_str","full_description":"Shoko::Core::BookFormats::Kindle::MetadataParser delegation is used by KindleImporter metadata extraction and preserves author_str","status":"passed","file_path":"./spec/core/book_formats/kindle/metadata_parser_spec.rb","line_number":84,"run_time":0.000723056,"pending_message":null},{"id":"./spec/core/book_formats/kindle/metadata_parser_spec.rb[1:2:1]","description":"is used by KindleMetadataExtractor and preserves author_str output","full_description":"Shoko::Core::BookFormats::Kindle::MetadataParser delegation is used by KindleMetadataExtractor and preserves author_str output","status":"passed","file_path":"./spec/core/book_formats/kindle/metadata_parser_spec.rb","line_number":29,"run_time":0.000548048,"pending_message":null},{"id":"./spec/core/book_formats/kindle/metadata_parser_spec.rb[1:1:1]","description":"extracts canonical metadata from MOBI and EXTH values","full_description":"Shoko::Core::BookFormats::Kindle::MetadataParser.parse extracts canonical metadata from MOBI and EXTH values","status":"passed","file_path":"./spec/core/book_formats/kindle/metadata_parser_spec.rb","line_number":7,"run_time":0.000171331,"pending_message":null},{"id":"./spec/adapters/book_sources/folder_scanner_spec.rb[1:4]","description":"detects compound extensions and maps format groups","full_description":"Shoko::Adapters::BookSources::FolderScanner detects compound extensions and maps format groups","status":"passed","file_path":"./spec/adapters/book_sources/folder_scanner_spec.rb","line_number":54,"run_time":0.000467006,"pending_message":null},{"id":"./spec/adapters/book_sources/folder_scanner_spec.rb[1:3]","description":"includes hidden entries when skip_hidden is false","full_description":"Shoko::Adapters::BookSources::FolderScanner includes hidden entries when skip_hidden is false","status":"passed","file_path":"./spec/adapters/book_sources/folder_scanner_spec.rb","line_number":42,"run_time":0.0002454,"pending_message":null},{"id":"./spec/adapters/book_sources/folder_scanner_spec.rb[1:1]","description":"scans recursively for supported book files","full_description":"Shoko::Adapters::BookSources::FolderScanner scans recursively for supported book files","status":"passed","file_path":"./spec/adapters/book_sources/folder_scanner_spec.rb","line_number":12,"run_time":0.000503384,"pending_message":null},{"id":"./spec/adapters/book_sources/folder_scanner_spec.rb[1:2]","description":"does not descend into hidden files and folders when skip_hidden is true","full_description":"Shoko::Adapters::BookSources::FolderScanner does not descend into hidden files and folders when skip_hidden is true","status":"passed","file_path":"./spec/adapters/book_sources/folder_scanner_spec.rb","line_number":26,"run_time":0.000344016,"pending_message":null},{"id":"./spec/core/models/dictionary_entry_spec.rb[1:2:1]","description":"serializes to a hash of attributes","full_description":"Shoko::Core::Models::DictionaryEntry#to_h serializes to a hash of attributes","status":"passed","file_path":"./spec/core/models/dictionary_entry_spec.rb","line_number":41,"run_time":0.000106079,"pending_message":null},{"id":"./spec/core/models/dictionary_entry_spec.rb[1:4:1]","description":"groups senses by inferred part of speech","full_description":"Shoko::Core::Models::DictionaryEntry#senses_grouped groups senses by inferred part of speech","status":"passed","file_path":"./spec/core/models/dictionary_entry_spec.rb","line_number":60,"run_time":0.001073733,"pending_message":null},{"id":"./spec/core/models/dictionary_entry_spec.rb[1:3:1]","description":"returns true when there are no senses or translations","full_description":"Shoko::Core::Models::DictionaryEntry#empty? returns true when there are no senses or translations","status":"passed","file_path":"./spec/core/models/dictionary_entry_spec.rb","line_number":48,"run_time":0.000096301,"pending_message":null},{"id":"./spec/core/models/dictionary_entry_spec.rb[1:3:2]","description":"returns false when senses exist","full_description":"Shoko::Core::Models::DictionaryEntry#empty? returns false when senses exist","status":"passed","file_path":"./spec/core/models/dictionary_entry_spec.rb","line_number":53,"run_time":0.000069851,"pending_message":null},{"id":"./spec/core/models/dictionary_entry_spec.rb[1:1:1]","description":"builds an entry from hash values","full_description":"Shoko::Core::Models::DictionaryEntry.from_hash builds an entry from hash values","status":"passed","file_path":"./spec/core/models/dictionary_entry_spec.rb","line_number":7,"run_time":0.000088846,"pending_message":null},{"id":"./spec/core/models/dictionary_entry_spec.rb[1:1:2]","description":"falls back to word key and handles arrays","full_description":"Shoko::Core::Models::DictionaryEntry.from_hash falls back to word key and handles arrays","status":"passed","file_path":"./spec/core/models/dictionary_entry_spec.rb","line_number":27,"run_time":0.000065443,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_content_parser_spec.rb[1:1]","description":"parses HTML paragraphs into content blocks","full_description":"Shoko::Core::BookFormats::Rtf::RtfContentParser parses HTML paragraphs into content blocks","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_content_parser_spec.rb","line_number":6,"run_time":0.000471484,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_content_parser_spec.rb[1:3]","description":"parses bold and italic styles","full_description":"Shoko::Core::BookFormats::Rtf::RtfContentParser parses bold and italic styles","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_content_parser_spec.rb","line_number":26,"run_time":0.000670668,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_content_parser_spec.rb[1:4]","description":"preserves underline, strike, superscript, and subscript styles from HTML","full_description":"Shoko::Core::BookFormats::Rtf::RtfContentParser preserves underline, strike, superscript, and subscript styles from HTML","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_content_parser_spec.rb","line_number":38,"run_time":0.000479018,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_content_parser_spec.rb[1:2]","description":"parses headings","full_description":"Shoko::Core::BookFormats::Rtf::RtfContentParser parses headings","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_content_parser_spec.rb","line_number":17,"run_time":0.000345247,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_content_parser_spec.rb[1:5]","description":"returns empty array for blank input","full_description":"Shoko::Core::BookFormats::Rtf::RtfContentParser returns empty array for blank input","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_content_parser_spec.rb","line_number":50,"run_time":0.000062587,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_content_parser_spec.rb[1:6]","description":"handles nil-like input gracefully","full_description":"Shoko::Core::BookFormats::Rtf::RtfContentParser handles nil-like input gracefully","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_content_parser_spec.rb","line_number":55,"run_time":0.000064771,"pending_message":null},{"id":"./spec/core/architecture/no_rescue_exception_spec.rb[1:1]","description":"forbids rescue Exception in lib/shoko runtime sources","full_description":"No Exception rescues in runtime code forbids rescue Exception in lib/shoko runtime sources","status":"passed","file_path":"./spec/core/architecture/no_rescue_exception_spec.rb","line_number":9,"run_time":0.026926974,"pending_message":null},{"id":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb[1:3:2]","description":"enables extract_resources only when explicitly true","full_description":"Importer extract_resources flag Shoko::Adapters::BookSources::Pdf::PdfImporter enables extract_resources only when explicitly true","status":"passed","file_path":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb","line_number":21,"run_time":0.00010144,"pending_message":null},{"id":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb[1:3:1]","description":"keeps extract_resources disabled by default","full_description":"Importer extract_resources flag Shoko::Adapters::BookSources::Pdf::PdfImporter keeps extract_resources disabled by default","status":"passed","file_path":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb","line_number":16,"run_time":0.000086242,"pending_message":null},{"id":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb[1:1:2]","description":"enables extract_resources only when explicitly true","full_description":"Importer extract_resources flag Shoko::Adapters::BookSources::Epub::EpubImporter enables extract_resources only when explicitly true","status":"passed","file_path":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb","line_number":21,"run_time":0.000081894,"pending_message":null},{"id":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb[1:1:1]","description":"keeps extract_resources disabled by default","full_description":"Importer extract_resources flag Shoko::Adapters::BookSources::Epub::EpubImporter keeps extract_resources disabled by default","status":"passed","file_path":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb","line_number":16,"run_time":0.000055564,"pending_message":null},{"id":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb[1:4:1]","description":"keeps extract_resources disabled by default","full_description":"Importer extract_resources flag Shoko::Adapters::BookSources::Kindle::KindleImporter keeps extract_resources disabled by default","status":"passed","file_path":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb","line_number":16,"run_time":0.000088957,"pending_message":null},{"id":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb[1:4:2]","description":"enables extract_resources only when explicitly true","full_description":"Importer extract_resources flag Shoko::Adapters::BookSources::Kindle::KindleImporter enables extract_resources only when explicitly true","status":"passed","file_path":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb","line_number":21,"run_time":0.000055364,"pending_message":null},{"id":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb[1:5:2]","description":"enables extract_resources only when explicitly true","full_description":"Importer extract_resources flag Shoko::Adapters::BookSources::Rtf::RtfImporter enables extract_resources only when explicitly true","status":"passed","file_path":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb","line_number":21,"run_time":0.000120155,"pending_message":null},{"id":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb[1:5:1]","description":"keeps extract_resources disabled by default","full_description":"Importer extract_resources flag Shoko::Adapters::BookSources::Rtf::RtfImporter keeps extract_resources disabled by default","status":"passed","file_path":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb","line_number":16,"run_time":0.00007503,"pending_message":null},{"id":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb[1:2:2]","description":"enables extract_resources only when explicitly true","full_description":"Importer extract_resources flag Shoko::Adapters::BookSources::Fb2::Fb2Importer enables extract_resources only when explicitly true","status":"passed","file_path":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb","line_number":21,"run_time":0.000064962,"pending_message":null},{"id":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb[1:2:1]","description":"keeps extract_resources disabled by default","full_description":"Importer extract_resources flag Shoko::Adapters::BookSources::Fb2::Fb2Importer keeps extract_resources disabled by default","status":"passed","file_path":"./spec/adapters/book_sources/importer_extract_resources_flag_spec.rb","line_number":16,"run_time":0.000051958,"pending_message":null},{"id":"./spec/core/architecture/adapter_boundary_spec.rb[1:1]","description":"uses a single core ports root split by inbound/outbound","full_description":"Hexagonal architecture boundaries uses a single core ports root split by inbound/outbound","status":"passed","file_path":"./spec/core/architecture/adapter_boundary_spec.rb","line_number":46,"run_time":0.000206236,"pending_message":null},{"id":"./spec/core/architecture/adapter_boundary_spec.rb[1:2]","description":"forbids adapter constants in core sources","full_description":"Hexagonal architecture boundaries forbids adapter constants in core sources","status":"passed","file_path":"./spec/core/architecture/adapter_boundary_spec.rb","line_number":63,"run_time":0.006334488,"pending_message":null},{"id":"./spec/core/architecture/adapter_boundary_spec.rb[1:6]","description":"restricts container mutation to composition roots","full_description":"Hexagonal architecture boundaries restricts container mutation to composition roots","status":"passed","file_path":"./spec/core/architecture/adapter_boundary_spec.rb","line_number":104,"run_time":0.046573064,"pending_message":null},{"id":"./spec/core/architecture/adapter_boundary_spec.rb[1:5]","description":"restricts container resolution to composition roots","full_description":"Hexagonal architecture boundaries restricts container resolution to composition roots","status":"passed","file_path":"./spec/core/architecture/adapter_boundary_spec.rb","line_number":91,"run_time":0.033153039,"pending_message":null},{"id":"./spec/core/architecture/adapter_boundary_spec.rb[1:4]","description":"forbids ui adapter dependencies on sibling adapters","full_description":"Hexagonal architecture boundaries forbids ui adapter dependencies on sibling adapters","status":"passed","file_path":"./spec/core/architecture/adapter_boundary_spec.rb","line_number":77,"run_time":0.008037001,"pending_message":null},{"id":"./spec/core/architecture/adapter_boundary_spec.rb[1:3]","description":"forbids adapter constants in application sources","full_description":"Hexagonal architecture boundaries forbids adapter constants in application sources","status":"passed","file_path":"./spec/core/architecture/adapter_boundary_spec.rb","line_number":70,"run_time":0.002842611,"pending_message":null},{"id":"./spec/application/use_cases/settings_service_spec.rb[1:1:1]","description":"toggles dictionary backend between :sqlite and :disabled","full_description":"Shoko::Application::UseCases::SettingsService#toggle_dictionary_backend toggles dictionary backend between :sqlite and :disabled","status":"passed","file_path":"./spec/application/use_cases/settings_service_spec.rb","line_number":77,"run_time":0.000733907,"pending_message":null},{"id":"./spec/application/use_cases/settings_service_spec.rb[1:2:2]","description":"removes downloaded books when downloads option selected","full_description":"Shoko::Application::UseCases::SettingsService#wipe_cache removes downloaded books when downloads option selected","status":"passed","file_path":"./spec/application/use_cases/settings_service_spec.rb","line_number":117,"run_time":0.001067362,"pending_message":null},{"id":"./spec/application/use_cases/settings_service_spec.rb[1:2:1]","description":"removes cached data when cached option selected","full_description":"Shoko::Application::UseCases::SettingsService#wipe_cache removes cached data when cached option selected","status":"passed","file_path":"./spec/application/use_cases/settings_service_spec.rb","line_number":104,"run_time":0.000992852,"pending_message":null},{"id":"./spec/application/use_cases/settings_service_spec.rb[1:2:4]","description":"nukes caches, downloads, and dictionaries when nuke option selected","full_description":"Shoko::Application::UseCases::SettingsService#wipe_cache nukes caches, downloads, and dictionaries when nuke option selected","status":"passed","file_path":"./spec/application/use_cases/settings_service_spec.rb","line_number":151,"run_time":0.001100403,"pending_message":null},{"id":"./spec/application/use_cases/settings_service_spec.rb[1:2:3]","description":"removes selected user data files when options are enabled","full_description":"Shoko::Application::UseCases::SettingsService#wipe_cache removes selected user data files when options are enabled","status":"passed","file_path":"./spec/application/use_cases/settings_service_spec.rb","line_number":134,"run_time":0.00081082,"pending_message":null},{"id":"./spec/core/services/toc_tree_service_spec.rb[1:1]","description":"builds fallback entries from chapters when toc is empty","full_description":"Shoko::Core::Services::TocTreeService builds fallback entries from chapters when toc is empty","status":"passed","file_path":"./spec/core/services/toc_tree_service_spec.rb","line_number":8,"run_time":0.000142648,"pending_message":null},{"id":"./spec/core/services/toc_tree_service_spec.rb[1:4]","description":"re-targets hidden selection to a visible entry","full_description":"Shoko::Core::Services::TocTreeService re-targets hidden selection to a visible entry","status":"passed","file_path":"./spec/core/services/toc_tree_service_spec.rb","line_number":91,"run_time":0.000779391,"pending_message":null},{"id":"./spec/core/services/toc_tree_service_spec.rb[1:2]","description":"returns filtered entries with ancestors and ignores collapse when filter is active","full_description":"Shoko::Core::Services::TocTreeService returns filtered entries with ancestors and ignores collapse when filter is active","status":"passed","file_path":"./spec/core/services/toc_tree_service_spec.rb","line_number":65,"run_time":0.000132148,"pending_message":null},{"id":"./spec/core/services/toc_tree_service_spec.rb[1:3]","description":"applies collapse when filter is inactive","full_description":"Shoko::Core::Services::TocTreeService applies collapse when filter is inactive","status":"passed","file_path":"./spec/core/services/toc_tree_service_spec.rb","line_number":78,"run_time":0.000095419,"pending_message":null},{"id":"./spec/core/architecture/dependency_constructor_guardrails_spec.rb[1:1]","description":"forbids initialize(**deps) on critical controller/workflow classes","full_description":"Dependency constructor guardrails forbids initialize(**deps) on critical controller/workflow classes","status":"passed","file_path":"./spec/core/architecture/dependency_constructor_guardrails_spec.rb","line_number":8,"run_time":0.000258525,"pending_message":null},{"id":"./spec/bootstrap/runtime_bootstrap_spec.rb[1:1:2]","description":"excludes runtime bootstrap and test support files","full_description":"Shoko::Bootstrap::RuntimeBootstrap.manifest_features excludes runtime bootstrap and test support files","status":"passed","file_path":"./spec/bootstrap/runtime_bootstrap_spec.rb","line_number":15,"run_time":0.000364844,"pending_message":null},{"id":"./spec/bootstrap/runtime_bootstrap_spec.rb[1:1:1]","description":"is deterministic without synthetic namespace preload entries","full_description":"Shoko::Bootstrap::RuntimeBootstrap.manifest_features is deterministic without synthetic namespace preload entries","status":"passed","file_path":"./spec/bootstrap/runtime_bootstrap_spec.rb","line_number":7,"run_time":0.00025569,"pending_message":null},{"id":"./spec/bootstrap/runtime_bootstrap_spec.rb[1:1:3]","description":"contains runtime format files needed by non-fixture specs","full_description":"Shoko::Bootstrap::RuntimeBootstrap.manifest_features contains runtime format files needed by non-fixture specs","status":"passed","file_path":"./spec/bootstrap/runtime_bootstrap_spec.rb","line_number":22,"run_time":0.000074229,"pending_message":null},{"id":"./spec/bootstrap/runtime_bootstrap_spec.rb[1:2:2]","description":"loads key format constants referenced by required non-fixture specs","full_description":"Shoko::Bootstrap::RuntimeBootstrap.boot! loads key format constants referenced by required non-fixture specs","status":"passed","file_path":"./spec/bootstrap/runtime_bootstrap_spec.rb","line_number":62,"run_time":0.025409909,"pending_message":null},{"id":"./spec/bootstrap/runtime_bootstrap_spec.rb[1:2:1]","description":"boots idempotently","full_description":"Shoko::Bootstrap::RuntimeBootstrap.boot! boots idempotently","status":"passed","file_path":"./spec/bootstrap/runtime_bootstrap_spec.rb","line_number":52,"run_time":0.017942265,"pending_message":null},{"id":"./spec/adapters/output/kitty/kitty_image_renderer_spec.rb[1:1:1]","description":"returns a non-zero 24-bit id","full_description":"Shoko::Adapters::Output::Kitty::KittyImageRenderer#hashed_id returns a non-zero 24-bit id","status":"passed","file_path":"./spec/adapters/output/kitty/kitty_image_renderer_spec.rb","line_number":7,"run_time":0.000754755,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_content_parser_spec.rb[1:3]","description":"parses bold and italic inline styles","full_description":"Shoko::Core::BookFormats::Kindle::KindleContentParser parses bold and italic inline styles","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_content_parser_spec.rb","line_number":26,"run_time":0.000947076,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_content_parser_spec.rb[1:1]","description":"parses simple HTML paragraphs into content blocks","full_description":"Shoko::Core::BookFormats::Kindle::KindleContentParser parses simple HTML paragraphs into content blocks","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_content_parser_spec.rb","line_number":6,"run_time":0.00034148,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_content_parser_spec.rb[1:8]","description":"handles nil-like input gracefully","full_description":"Shoko::Core::BookFormats::Kindle::KindleContentParser handles nil-like input gracefully","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_content_parser_spec.rb","line_number":82,"run_time":0.000058429,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_content_parser_spec.rb[1:4]","description":"preserves underline, strike, superscript, and subscript inline styles","full_description":"Shoko::Core::BookFormats::Kindle::KindleContentParser preserves underline, strike, superscript, and subscript inline styles","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_content_parser_spec.rb","line_number":40,"run_time":0.000500369,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_content_parser_spec.rb[1:2]","description":"parses headings in a body context","full_description":"Shoko::Core::BookFormats::Kindle::KindleContentParser parses headings in a body context","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_content_parser_spec.rb","line_number":17,"run_time":0.000413084,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_content_parser_spec.rb[1:7]","description":"returns empty array for blank input","full_description":"Shoko::Core::BookFormats::Kindle::KindleContentParser returns empty array for blank input","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_content_parser_spec.rb","line_number":77,"run_time":0.000062166,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_content_parser_spec.rb[1:5]","description":"handles MOBI-style HTML with font tags","full_description":"Shoko::Core::BookFormats::Kindle::KindleContentParser handles MOBI-style HTML with font tags","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_content_parser_spec.rb","line_number":52,"run_time":0.000333345,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_content_parser_spec.rb[1:6]","description":"handles AZW3/KF8 XHTML with namespace","full_description":"Shoko::Core::BookFormats::Kindle::KindleContentParser handles AZW3/KF8 XHTML with namespace","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_content_parser_spec.rb","line_number":61,"run_time":0.000424456,"pending_message":null},{"id":"./spec/adapters/book_sources/metadata_reader_adapter_fb2_zip_spec.rb[1:1]","description":"extracts metadata from .fb2.zip through format registry dispatch","full_description":"Shoko::Adapters::BookSources::MetadataReaderAdapter extracts metadata from .fb2.zip through format registry dispatch","status":"passed","file_path":"./spec/adapters/book_sources/metadata_reader_adapter_fb2_zip_spec.rb","line_number":6,"run_time":0.001061451,"pending_message":null},{"id":"./spec/adapters/storage/book_cache_pipeline_spec.rb[1:1]","description":"returns an in-memory payload when cache write fails","full_description":"Shoko::Adapters::Storage::BookCachePipeline returns an in-memory payload when cache write fails","status":"passed","file_path":"./spec/adapters/storage/book_cache_pipeline_spec.rb","line_number":94,"run_time":0.000329748,"pending_message":null},{"id":"./spec/adapters/storage/book_cache_pipeline_spec.rb[1:2]","description":"loads from cache on subsequent source and pointer loads","full_description":"Shoko::Adapters::Storage::BookCachePipeline loads from cache on subsequent source and pointer loads","status":"passed","file_path":"./spec/adapters/storage/book_cache_pipeline_spec.rb","line_number":115,"run_time":0.00186627,"pending_message":null},{"id":"./spec/adapters/input/command_binding_completeness_spec.rb[1:1]","description":"ensures reader input symbol bindings map only to registered bus commands","full_description":"Input command binding completeness ensures reader input symbol bindings map only to registered bus commands","status":"passed","file_path":"./spec/adapters/input/command_binding_completeness_spec.rb","line_number":13,"run_time":0.000318007,"pending_message":null},{"id":"./spec/adapters/input/command_binding_completeness_spec.rb[1:2]","description":"ensures menu input symbol bindings map only to registered bus commands","full_description":"Input command binding completeness ensures menu input symbol bindings map only to registered bus commands","status":"passed","file_path":"./spec/adapters/input/command_binding_completeness_spec.rb","line_number":37,"run_time":0.000292218,"pending_message":null},{"id":"./spec/adapters/storage/dictionary_storage_adapter_spec.rb[1:4:1]","description":"removes the resolved dictionary directory","full_description":"Shoko::Adapters::Storage::DictionaryStorageAdapter#remove_databases_path removes the resolved dictionary directory","status":"passed","file_path":"./spec/adapters/storage/dictionary_storage_adapter_spec.rb","line_number":44,"run_time":0.00033053,"pending_message":null},{"id":"./spec/adapters/storage/dictionary_storage_adapter_spec.rb[1:1:1]","description":"uses the config-root dictionary directory","full_description":"Shoko::Adapters::Storage::DictionaryStorageAdapter#default_databases_path uses the config-root dictionary directory","status":"passed","file_path":"./spec/adapters/storage/dictionary_storage_adapter_spec.rb","line_number":16,"run_time":0.000177503,"pending_message":null},{"id":"./spec/adapters/storage/dictionary_storage_adapter_spec.rb[1:3:1]","description":"returns true when sqlite3 files exist in the resolved path","full_description":"Shoko::Adapters::Storage::DictionaryStorageAdapter#databases_present? returns true when sqlite3 files exist in the resolved path","status":"passed","file_path":"./spec/adapters/storage/dictionary_storage_adapter_spec.rb","line_number":33,"run_time":0.000321172,"pending_message":null},{"id":"./spec/adapters/storage/dictionary_storage_adapter_spec.rb[1:2:1]","description":"creates and returns the configured dictionary path","full_description":"Shoko::Adapters::Storage::DictionaryStorageAdapter#ensure_databases_path creates and returns the configured dictionary path","status":"passed","file_path":"./spec/adapters/storage/dictionary_storage_adapter_spec.rb","line_number":22,"run_time":0.000269615,"pending_message":null},{"id":"./spec/adapters/input/controllers/state_controller_progress_actions_spec.rb[1:1:2]","description":"saves progress and then quits on success","full_description":"Shoko::Adapters::Input::Controllers::StateController#quit_to_menu saves progress and then quits on success","status":"passed","file_path":"./spec/adapters/input/controllers/state_controller_progress_actions_spec.rb","line_number":99,"run_time":0.00065611,"pending_message":null},{"id":"./spec/adapters/input/controllers/state_controller_progress_actions_spec.rb[1:1:1]","description":"raises when saving progress fails","full_description":"Shoko::Adapters::Input::Controllers::StateController#quit_to_menu raises when saving progress fails","status":"passed","file_path":"./spec/adapters/input/controllers/state_controller_progress_actions_spec.rb","line_number":92,"run_time":0.00044256,"pending_message":null},{"id":"./spec/core/models/dictionary_entry_spec.rb[3:1]","description":"classifies confidence based on similarity","full_description":"Shoko::Core::Models::FuzzyMatch classifies confidence based on similarity","status":"passed","file_path":"./spec/core/models/dictionary_entry_spec.rb","line_number":89,"run_time":0.000093295,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/ui_state_reader_adapter_spec.rb[1:1:1]","description":"reads from state","full_description":"Shoko::Adapters::Runtime::SessionState::UiStateReaderAdapter#terminal_width reads from state","status":"passed","file_path":"./spec/adapters/runtime/session_state/ui_state_reader_adapter_spec.rb","line_number":10,"run_time":0.000153728,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/ui_state_reader_adapter_spec.rb[1:1:2]","description":"returns nil when not set","full_description":"Shoko::Adapters::Runtime::SessionState::UiStateReaderAdapter#terminal_width returns nil when not set","status":"passed","file_path":"./spec/adapters/runtime/session_state/ui_state_reader_adapter_spec.rb","line_number":15,"run_time":0.000124193,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/ui_state_reader_adapter_spec.rb[1:3:1]","description":"includes Core::Ports::Outbound::UiStateReader","full_description":"Shoko::Adapters::Runtime::SessionState::UiStateReaderAdapter port compliance includes Core::Ports::Outbound::UiStateReader","status":"passed","file_path":"./spec/adapters/runtime/session_state/ui_state_reader_adapter_spec.rb","line_number":34,"run_time":0.000064752,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/ui_state_reader_adapter_spec.rb[1:2:2]","description":"returns nil when not set","full_description":"Shoko::Adapters::Runtime::SessionState::UiStateReaderAdapter#terminal_height returns nil when not set","status":"passed","file_path":"./spec/adapters/runtime/session_state/ui_state_reader_adapter_spec.rb","line_number":27,"run_time":0.000141626,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/ui_state_reader_adapter_spec.rb[1:2:1]","description":"reads from state","full_description":"Shoko::Adapters::Runtime::SessionState::UiStateReaderAdapter#terminal_height reads from state","status":"passed","file_path":"./spec/adapters/runtime/session_state/ui_state_reader_adapter_spec.rb","line_number":22,"run_time":0.000172704,"pending_message":null},{"id":"./spec/adapters/ui/sessions/dictionary_ui_session_adapter_spec.rb[1:5]","description":"logs and returns a failed outcome for component errors","full_description":"Shoko::Adapters::Ui::Sessions::DictionaryUiSessionAdapter logs and returns a failed outcome for component errors","status":"passed","file_path":"./spec/adapters/ui/sessions/dictionary_ui_session_adapter_spec.rb","line_number":92,"run_time":0.00050144,"pending_message":null},{"id":"./spec/adapters/ui/sessions/dictionary_ui_session_adapter_spec.rb[1:1]","description":"shows popup and updates reader state","full_description":"Shoko::Adapters::Ui::Sessions::DictionaryUiSessionAdapter shows popup and updates reader state","status":"passed","file_path":"./spec/adapters/ui/sessions/dictionary_ui_session_adapter_spec.rb","line_number":40,"run_time":0.000439885,"pending_message":null},{"id":"./spec/adapters/ui/sessions/dictionary_ui_session_adapter_spec.rb[1:3]","description":"returns payload outcomes for active component input intents","full_description":"Shoko::Adapters::Ui::Sessions::DictionaryUiSessionAdapter returns payload outcomes for active component input intents","status":"passed","file_path":"./spec/adapters/ui/sessions/dictionary_ui_session_adapter_spec.rb","line_number":71,"run_time":0.000437049,"pending_message":null},{"id":"./spec/adapters/ui/sessions/dictionary_ui_session_adapter_spec.rb[1:4]","description":"updates setup state through popup","full_description":"Shoko::Adapters::Ui::Sessions::DictionaryUiSessionAdapter updates setup state through popup","status":"passed","file_path":"./spec/adapters/ui/sessions/dictionary_ui_session_adapter_spec.rb","line_number":82,"run_time":0.000421601,"pending_message":null},{"id":"./spec/adapters/ui/sessions/dictionary_ui_session_adapter_spec.rb[1:2]","description":"closes active dictionary UI and clears state","full_description":"Shoko::Adapters::Ui::Sessions::DictionaryUiSessionAdapter closes active dictionary UI and clears state","status":"passed","file_path":"./spec/adapters/ui/sessions/dictionary_ui_session_adapter_spec.rb","line_number":56,"run_time":0.000396293,"pending_message":null},{"id":"./spec/core/architecture/application_workflow_guardrails_spec.rb[1:5]","description":"forbids frame coordinator coupling in application pagination orchestration","full_description":"Application workflow guardrails forbids frame coordinator coupling in application pagination orchestration","status":"passed","file_path":"./spec/core/architecture/application_workflow_guardrails_spec.rb","line_number":76,"run_time":0.000348743,"pending_message":null},{"id":"./spec/core/architecture/application_workflow_guardrails_spec.rb[1:4]","description":"forbids direct ui_controller coupling in PendingJumpHandler","full_description":"Application workflow guardrails forbids direct ui_controller coupling in PendingJumpHandler","status":"passed","file_path":"./spec/core/architecture/application_workflow_guardrails_spec.rb","line_number":63,"run_time":0.000121097,"pending_message":null},{"id":"./spec/core/architecture/application_workflow_guardrails_spec.rb[1:1]","description":"forbids respond_to?(:call) callback introspection in menu workflows","full_description":"Application workflow guardrails forbids respond_to?(:call) callback introspection in menu workflows","status":"passed","file_path":"./spec/core/architecture/application_workflow_guardrails_spec.rb","line_number":15,"run_time":0.000652784,"pending_message":null},{"id":"./spec/core/architecture/application_workflow_guardrails_spec.rb[1:2]","description":"forbids callback-style reader launch dependencies in application workflow wiring","full_description":"Application workflow guardrails forbids callback-style reader launch dependencies in application workflow wiring","status":"passed","file_path":"./spec/core/architecture/application_workflow_guardrails_spec.rb","line_number":24,"run_time":0.000185428,"pending_message":null},{"id":"./spec/core/architecture/application_workflow_guardrails_spec.rb[1:3]","description":"forbids callback-style redraw/scan dependencies in menu workflows","full_description":"Application workflow guardrails forbids callback-style redraw/scan dependencies in menu workflows","status":"passed","file_path":"./spec/core/architecture/application_workflow_guardrails_spec.rb","line_number":41,"run_time":0.000670176,"pending_message":null},{"id":"./spec/core/architecture/application_workflow_guardrails_spec.rb[1:6]","description":"forbids application layer dependencies on controller runtime APIs","full_description":"Application workflow guardrails forbids application layer dependencies on controller runtime APIs","status":"passed","file_path":"./spec/core/architecture/application_workflow_guardrails_spec.rb","line_number":87,"run_time":0.002952797,"pending_message":null},{"id":"./spec/core/architecture/application_workflow_guardrails_spec.rb[1:7]","description":"forbids terminal_service dependencies in application layer","full_description":"Application workflow guardrails forbids terminal_service dependencies in application layer","status":"passed","file_path":"./spec/core/architecture/application_workflow_guardrails_spec.rb","line_number":109,"run_time":0.003867362,"pending_message":null},{"id":"./spec/adapters/input/command_bus_only_bindings_spec.rb[1:1]","description":"forces reader bindings to use command bus symbols only","full_description":"Command-bus-only input bindings forces reader bindings to use command bus symbols only","status":"passed","file_path":"./spec/adapters/input/command_bus_only_bindings_spec.rb","line_number":33,"run_time":0.000280456,"pending_message":null},{"id":"./spec/adapters/input/command_bus_only_bindings_spec.rb[1:2]","description":"forces menu bindings to use command bus symbols only","full_description":"Command-bus-only input bindings forces menu bindings to use command bus symbols only","status":"passed","file_path":"./spec/adapters/input/command_bus_only_bindings_spec.rb","line_number":52,"run_time":0.000252393,"pending_message":null},{"id":"./spec/adapters/input/commands_spec.rb[1:1]","description":"routes symbol execution through typed InputCommandPayload","full_description":"Shoko::Adapters::Input::Commands routes symbol execution through typed InputCommandPayload","status":"passed","file_path":"./spec/adapters/input/commands_spec.rb","line_number":48,"run_time":0.00022951,"pending_message":null},{"id":"./spec/adapters/input/commands_spec.rb[1:3]","description":"returns :error and logs command.contract_mismatch for non-symbol commands","full_description":"Shoko::Adapters::Input::Commands returns :error and logs command.contract_mismatch for non-symbol commands","status":"passed","file_path":"./spec/adapters/input/commands_spec.rb","line_number":92,"run_time":0.000548999,"pending_message":null},{"id":"./spec/adapters/input/commands_spec.rb[1:2]","description":"returns :error and logs command.contract_mismatch when command bus is missing","full_description":"Shoko::Adapters::Input::Commands returns :error and logs command.contract_mismatch when command bus is missing","status":"passed","file_path":"./spec/adapters/input/commands_spec.rb","line_number":62,"run_time":0.000200255,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/library_screen_component_spec.rb[1:5]","description":"renders title-focused library layout in light mode at 120x40","full_description":"Shoko::Adapters::Ui::Components::Screens::LibraryScreenComponent renders title-focused library layout in light mode at 120x40","status":"passed","file_path":"./spec/adapters/ui/components/screens/library_screen_component_spec.rb","line_number":57,"run_time":0.002333786,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/library_screen_component_spec.rb[1:6]","description":"renders a details panel when metadata drawer is toggled open","full_description":"Shoko::Adapters::Ui::Components::Screens::LibraryScreenComponent renders a details panel when metadata drawer is toggled open","status":"passed","file_path":"./spec/adapters/ui/components/screens/library_screen_component_spec.rb","line_number":70,"run_time":0.004002997,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/library_screen_component_spec.rb[1:3]","description":"renders title-focused library layout in light mode at 80x24","full_description":"Shoko::Adapters::Ui::Components::Screens::LibraryScreenComponent renders title-focused library layout in light mode at 80x24","status":"passed","file_path":"./spec/adapters/ui/components/screens/library_screen_component_spec.rb","line_number":57,"run_time":0.000960902,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/library_screen_component_spec.rb[1:4]","description":"renders title-focused library layout in dark mode at 120x40","full_description":"Shoko::Adapters::Ui::Components::Screens::LibraryScreenComponent renders title-focused library layout in dark mode at 120x40","status":"passed","file_path":"./spec/adapters/ui/components/screens/library_screen_component_spec.rb","line_number":57,"run_time":0.001528256,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/library_screen_component_spec.rb[1:2]","description":"renders title-focused library layout in dark mode at 80x24","full_description":"Shoko::Adapters::Ui::Components::Screens::LibraryScreenComponent renders title-focused library layout in dark mode at 80x24","status":"passed","file_path":"./spec/adapters/ui/components/screens/library_screen_component_spec.rb","line_number":57,"run_time":0.000878568,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/library_screen_component_spec.rb[1:1:1]","description":"formats minute/hour/day/week ranges with non-zero values","full_description":"Shoko::Adapters::Ui::Components::Screens::LibraryScreenComponent relative access labels formats minute/hour/day/week ranges with non-zero values","status":"passed","file_path":"./spec/adapters/ui/components/screens/library_screen_component_spec.rb","line_number":36,"run_time":0.00025639,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/library_screen_component_spec.rb[1:1:2]","description":"converts ISO timestamps to relative labels","full_description":"Shoko::Adapters::Ui::Components::Screens::LibraryScreenComponent relative access labels converts ISO timestamps to relative labels","status":"passed","file_path":"./spec/adapters/ui/components/screens/library_screen_component_spec.rb","line_number":43,"run_time":0.000562896,"pending_message":null},{"id":"./spec/adapters/input/annotations/mouse_handler_spec.rb[1:4]","description":"parses X10 mouse events","full_description":"Shoko::Adapters::Input::Annotations::MouseHandler parses X10 mouse events","status":"passed","file_path":"./spec/adapters/input/annotations/mouse_handler_spec.rb","line_number":30,"run_time":0.000122049,"pending_message":null},{"id":"./spec/adapters/input/annotations/mouse_handler_spec.rb[1:3]","description":"parses SGR mouse events","full_description":"Shoko::Adapters::Input::Annotations::MouseHandler parses SGR mouse events","status":"passed","file_path":"./spec/adapters/input/annotations/mouse_handler_spec.rb","line_number":24,"run_time":0.000099938,"pending_message":null},{"id":"./spec/adapters/input/annotations/mouse_handler_spec.rb[1:1]","description":"detects SGR and X10 mouse sequences","full_description":"Shoko::Adapters::Input::Annotations::MouseHandler detects SGR and X10 mouse sequences","status":"passed","file_path":"./spec/adapters/input/annotations/mouse_handler_spec.rb","line_number":8,"run_time":0.000079369,"pending_message":null},{"id":"./spec/adapters/input/annotations/mouse_handler_spec.rb[1:2]","description":"recognizes mouse prefixes for buffering","full_description":"Shoko::Adapters::Input::Annotations::MouseHandler recognizes mouse prefixes for buffering","status":"passed","file_path":"./spec/adapters/input/annotations/mouse_handler_spec.rb","line_number":17,"run_time":0.000066846,"pending_message":null},{"id":"./spec/core/services/coordinate_service_spec.rb[1:1]","description":"converts between mouse and terminal coordinates","full_description":"Shoko::Core::Services::CoordinateService converts between mouse and terminal coordinates","status":"passed","file_path":"./spec/core/services/coordinate_service_spec.rb","line_number":8,"run_time":0.000078658,"pending_message":null},{"id":"./spec/core/services/coordinate_service_spec.rb[1:3]","description":"creates anchors from rendered geometry","full_description":"Shoko::Core::Services::CoordinateService creates anchors from rendered geometry","status":"passed","file_path":"./spec/core/services/coordinate_service_spec.rb","line_number":24,"run_time":0.000153007,"pending_message":null},{"id":"./spec/core/services/coordinate_service_spec.rb[1:2]","description":"normalizes selection ranges so start precedes end","full_description":"Shoko::Core::Services::CoordinateService normalizes selection ranges so start precedes end","status":"passed","file_path":"./spec/core/services/coordinate_service_spec.rb","line_number":13,"run_time":0.00008008,"pending_message":null},{"id":"./spec/zip/name_normalizer_spec.rb[1:1]","description":"normalizes backslashes and leading dot slashes","full_description":"Zip::NameNormalizer normalizes backslashes and leading dot slashes","status":"passed","file_path":"./spec/zip/name_normalizer_spec.rb","line_number":6,"run_time":0.000196057,"pending_message":null},{"id":"./spec/adapters/output/formatting/wrapping_service_spec.rb[1:2]","description":"reuses cached windows for identical line sets","full_description":"Shoko::Adapters::Output::Formatting::WrappingService reuses cached windows for identical line sets","status":"passed","file_path":"./spec/adapters/output/formatting/wrapping_service_spec.rb","line_number":42,"run_time":0.000183344,"pending_message":null},{"id":"./spec/adapters/output/formatting/wrapping_service_spec.rb[1:5]","description":"uses the shared core chapter cache implementation","full_description":"Shoko::Adapters::Output::Formatting::WrappingService uses the shared core chapter cache implementation","status":"passed","file_path":"./spec/adapters/output/formatting/wrapping_service_spec.rb","line_number":101,"run_time":0.000081563,"pending_message":null},{"id":"./spec/adapters/output/formatting/wrapping_service_spec.rb[1:1]","description":"does not reuse window cache across different line sets","full_description":"Shoko::Adapters::Output::Formatting::WrappingService does not reuse window cache across different line sets","status":"passed","file_path":"./spec/adapters/output/formatting/wrapping_service_spec.rb","line_number":29,"run_time":0.000093956,"pending_message":null},{"id":"./spec/adapters/output/formatting/wrapping_service_spec.rb[1:3]","description":"reuses covered ranges from prefetched windows without rewrapping","full_description":"Shoko::Adapters::Output::Formatting::WrappingService reuses covered ranges from prefetched windows without rewrapping","status":"passed","file_path":"./spec/adapters/output/formatting/wrapping_service_spec.rb","line_number":52,"run_time":0.000132228,"pending_message":null},{"id":"./spec/adapters/output/formatting/wrapping_service_spec.rb[1:4]","description":"uses explicitly provided document for formatted wrapping when container has no document","full_description":"Shoko::Adapters::Output::Formatting::WrappingService uses explicitly provided document for formatted wrapping when container has no document","status":"passed","file_path":"./spec/adapters/output/formatting/wrapping_service_spec.rb","line_number":81,"run_time":0.000093045,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_spec.rb[1:3]","description":"persists config to disk","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore persists config to disk","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_spec.rb","line_number":61,"run_time":0.00086913,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_spec.rb[1:4]","description":"allows event subscribers to read state during callbacks without deadlocking","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore allows event subscribers to read state during callbacks without deadlocking","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_spec.rb","line_number":69,"run_time":0.000523962,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_spec.rb[1:2]","description":"validates update values","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore validates update values","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_spec.rb","line_number":55,"run_time":0.0002559,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/state_store_spec.rb[1:1]","description":"emits state change events when updates occur","full_description":"Shoko::Adapters::Runtime::SessionState::StateStore emits state change events when updates occur","status":"passed","file_path":"./spec/adapters/runtime/session_state/state_store_spec.rb","line_number":34,"run_time":0.000278042,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/dictionary_settings_screen_component_spec.rb[1:1:2]","description":"shows needs sqlite3 when backend is sqlite but gem is missing","full_description":"Shoko::Adapters::Ui::Components::Screens::DictionarySettingsScreenComponent#lookup_value shows needs sqlite3 when backend is sqlite but gem is missing","status":"passed","file_path":"./spec/adapters/ui/components/screens/dictionary_settings_screen_component_spec.rb","line_number":40,"run_time":0.000616797,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/dictionary_settings_screen_component_spec.rb[1:1:3]","description":"shows disabled when backend is nil","full_description":"Shoko::Adapters::Ui::Components::Screens::DictionarySettingsScreenComponent#lookup_value shows disabled when backend is nil","status":"passed","file_path":"./spec/adapters/ui/components/screens/dictionary_settings_screen_component_spec.rb","line_number":47,"run_time":0.000509626,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/dictionary_settings_screen_component_spec.rb[1:1:4]","description":"shows enabled when backend is auto and databases are present","full_description":"Shoko::Adapters::Ui::Components::Screens::DictionarySettingsScreenComponent#lookup_value shows enabled when backend is auto and databases are present","status":"passed","file_path":"./spec/adapters/ui/components/screens/dictionary_settings_screen_component_spec.rb","line_number":54,"run_time":0.000753002,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/dictionary_settings_screen_component_spec.rb[1:1:1]","description":"shows enabled when backend is sqlite and sqlite3 is available","full_description":"Shoko::Adapters::Ui::Components::Screens::DictionarySettingsScreenComponent#lookup_value shows enabled when backend is sqlite and sqlite3 is available","status":"passed","file_path":"./spec/adapters/ui/components/screens/dictionary_settings_screen_component_spec.rb","line_number":33,"run_time":0.000505789,"pending_message":null},{"id":"./spec/adapters/book_sources/book_finder/directory_scanner_spec.rb[1:2]","description":"allows explicit scan roots from SHOKO_BOOK_SCAN_DIRS","full_description":"Shoko::Adapters::BookSources::BookFinder::DirectoryScanner allows explicit scan roots from SHOKO_BOOK_SCAN_DIRS","status":"passed","file_path":"./spec/adapters/book_sources/book_finder/directory_scanner_spec.rb","line_number":34,"run_time":0.000342973,"pending_message":null},{"id":"./spec/adapters/book_sources/book_finder/directory_scanner_spec.rb[1:1]","description":"limits default scan roots to book-specific directories","full_description":"Shoko::Adapters::BookSources::BookFinder::DirectoryScanner limits default scan roots to book-specific directories","status":"passed","file_path":"./spec/adapters/book_sources/book_finder/directory_scanner_spec.rb","line_number":16,"run_time":0.000495339,"pending_message":null},{"id":"./spec/application/use_cases/menu_intent_handler_spec.rb[1:1]","description":"delegates supported intents to the executor","full_description":"Shoko::Application::UseCases::Intents::MenuIntentHandler delegates supported intents to the executor","status":"passed","file_path":"./spec/application/use_cases/menu_intent_handler_spec.rb","line_number":30,"run_time":0.00011198,"pending_message":null},{"id":"./spec/application/use_cases/menu_intent_handler_spec.rb[1:3]","description":"enforces typed executor dependency","full_description":"Shoko::Application::UseCases::Intents::MenuIntentHandler enforces typed executor dependency","status":"passed","file_path":"./spec/application/use_cases/menu_intent_handler_spec.rb","line_number":42,"run_time":0.000119824,"pending_message":null},{"id":"./spec/application/use_cases/menu_intent_handler_spec.rb[1:2]","description":"raises for unsupported intents","full_description":"Shoko::Application::UseCases::Intents::MenuIntentHandler raises for unsupported intents","status":"passed","file_path":"./spec/application/use_cases/menu_intent_handler_spec.rb","line_number":38,"run_time":0.00009036,"pending_message":null},{"id":"./spec/adapters/runtime/uuid_generator_adapter_spec.rb[1:1]","description":"returns UUID strings","full_description":"Shoko::Adapters::Runtime::UuidGeneratorAdapter returns UUID strings","status":"passed","file_path":"./spec/adapters/runtime/uuid_generator_adapter_spec.rb","line_number":6,"run_time":0.00007956,"pending_message":null},{"id":"./spec/adapters/output/terminal/terminal_sanitizer_spec.rb[1:1:1]","description":"removes ANSI and control characters","full_description":"Shoko::Shared::TextSanitizer.sanitize removes ANSI and control characters","status":"passed","file_path":"./spec/adapters/output/terminal/terminal_sanitizer_spec.rb","line_number":7,"run_time":0.000114185,"pending_message":null},{"id":"./spec/adapters/output/terminal/terminal_sanitizer_spec.rb[1:1:2]","description":"preserves newlines when requested","full_description":"Shoko::Shared::TextSanitizer.sanitize preserves newlines when requested","status":"passed","file_path":"./spec/adapters/output/terminal/terminal_sanitizer_spec.rb","line_number":12,"run_time":0.000056937,"pending_message":null},{"id":"./spec/adapters/output/terminal/terminal_sanitizer_spec.rb[1:3:2]","description":"accepts printable characters","full_description":"Shoko::Shared::TextSanitizer.printable_char? accepts printable characters","status":"passed","file_path":"./spec/adapters/output/terminal/terminal_sanitizer_spec.rb","line_number":30,"run_time":0.000184756,"pending_message":null},{"id":"./spec/adapters/output/terminal/terminal_sanitizer_spec.rb[1:3:1]","description":"rejects control characters","full_description":"Shoko::Shared::TextSanitizer.printable_char? rejects control characters","status":"passed","file_path":"./spec/adapters/output/terminal/terminal_sanitizer_spec.rb","line_number":26,"run_time":0.000053069,"pending_message":null},{"id":"./spec/adapters/output/terminal/terminal_sanitizer_spec.rb[1:2:1]","description":"decodes numeric control references before sanitizing","full_description":"Shoko::Shared::TextSanitizer.sanitize_xml_source decodes numeric control references before sanitizing","status":"passed","file_path":"./spec/adapters/output/terminal/terminal_sanitizer_spec.rb","line_number":19,"run_time":0.000072977,"pending_message":null},{"id":"./spec/adapters/storage/dictionary_catalog_service_spec.rb[1:2:1]","description":"follows redirects, writes file, and reports progress","full_description":"Shoko::Adapters::Storage::DictionaryCatalogService#download follows redirects, writes file, and reports progress","status":"passed","file_path":"./spec/adapters/storage/dictionary_catalog_service_spec.rb","line_number":46,"run_time":0.009821166,"pending_message":null},{"id":"./spec/adapters/storage/dictionary_catalog_service_spec.rb[1:2:2]","description":"returns existing when file already exists and skips network download","full_description":"Shoko::Adapters::Storage::DictionaryCatalogService#download returns existing when file already exists and skips network download","status":"passed","file_path":"./spec/adapters/storage/dictionary_catalog_service_spec.rb","line_number":68,"run_time":0.000262241,"pending_message":null},{"id":"./spec/adapters/storage/dictionary_catalog_service_spec.rb[1:1:2]","description":"raises CatalogError on request failures","full_description":"Shoko::Adapters::Storage::DictionaryCatalogService#list_remote raises CatalogError on request failures","status":"passed","file_path":"./spec/adapters/storage/dictionary_catalog_service_spec.rb","line_number":38,"run_time":0.000578144,"pending_message":null},{"id":"./spec/adapters/storage/dictionary_catalog_service_spec.rb[1:1:1]","description":"parses dictionary index rows into catalog entries","full_description":"Shoko::Adapters::Storage::DictionaryCatalogService#list_remote parses dictionary index rows into catalog entries","status":"passed","file_path":"./spec/adapters/storage/dictionary_catalog_service_spec.rb","line_number":20,"run_time":0.000502302,"pending_message":null},{"id":"./spec/adapters/ui/components/in_book_search_popup_component_spec.rb[1:3:1]","description":"respects minimum dimensions","full_description":"Shoko::Adapters::Ui::Components::InBookSearchPopupComponent overlay sizing respects minimum dimensions","status":"passed","file_path":"./spec/adapters/ui/components/in_book_search_popup_component_spec.rb","line_number":82,"run_time":0.000110477,"pending_message":null},{"id":"./spec/adapters/ui/components/in_book_search_popup_component_spec.rb[1:1:1]","description":"tracks visibility and payload","full_description":"Shoko::Adapters::Ui::Components::InBookSearchPopupComponent#show and #hide tracks visibility and payload","status":"passed","file_path":"./spec/adapters/ui/components/in_book_search_popup_component_spec.rb","line_number":17,"run_time":0.000117641,"pending_message":null},{"id":"./spec/adapters/ui/components/in_book_search_popup_component_spec.rb[1:2:1]","description":"emits query change for printable input and backspace","full_description":"Shoko::Adapters::Ui::Components::InBookSearchPopupComponent#handle_key emits query change for printable input and backspace","status":"passed","file_path":"./spec/adapters/ui/components/in_book_search_popup_component_spec.rb","line_number":35,"run_time":0.000139251,"pending_message":null},{"id":"./spec/adapters/ui/components/in_book_search_popup_component_spec.rb[1:2:5]","description":"submits query on enter only when query changed since last search","full_description":"Shoko::Adapters::Ui::Components::InBookSearchPopupComponent#handle_key submits query on enter only when query changed since last search","status":"passed","file_path":"./spec/adapters/ui/components/in_book_search_popup_component_spec.rb","line_number":66,"run_time":0.000087254,"pending_message":null},{"id":"./spec/adapters/ui/components/in_book_search_popup_component_spec.rb[1:2:3]","description":"treats q as query input instead of closing the popup","full_description":"Shoko::Adapters::Ui::Components::InBookSearchPopupComponent#handle_key treats q as query input instead of closing the popup","status":"passed","file_path":"./spec/adapters/ui/components/in_book_search_popup_component_spec.rb","line_number":46,"run_time":0.000075501,"pending_message":null},{"id":"./spec/adapters/ui/components/in_book_search_popup_component_spec.rb[1:2:2]","description":"emits close for cancel key","full_description":"Shoko::Adapters::Ui::Components::InBookSearchPopupComponent#handle_key emits close for cancel key","status":"passed","file_path":"./spec/adapters/ui/components/in_book_search_popup_component_spec.rb","line_number":41,"run_time":0.000062347,"pending_message":null},{"id":"./spec/adapters/ui/components/in_book_search_popup_component_spec.rb[1:2:6]","description":"opens selected result on enter when query is already searched","full_description":"Shoko::Adapters::Ui::Components::InBookSearchPopupComponent#handle_key opens selected result on enter when query is already searched","status":"passed","file_path":"./spec/adapters/ui/components/in_book_search_popup_component_spec.rb","line_number":72,"run_time":0.000077846,"pending_message":null},{"id":"./spec/adapters/ui/components/in_book_search_popup_component_spec.rb[1:2:4]","description":"moves selection on navigation keys","full_description":"Shoko::Adapters::Ui::Components::InBookSearchPopupComponent#handle_key moves selection on navigation keys","status":"passed","file_path":"./spec/adapters/ui/components/in_book_search_popup_component_spec.rb","line_number":51,"run_time":0.000083537,"pending_message":null},{"id":"./spec/core/architecture/namespace_guardrails_spec.rb[1:2]","description":"forbids synthetic namespace preload files","full_description":"Namespace guardrails forbids synthetic namespace preload files","status":"passed","file_path":"./spec/core/architecture/namespace_guardrails_spec.rb","line_number":25,"run_time":0.000081132,"pending_message":null},{"id":"./spec/core/architecture/namespace_guardrails_spec.rb[1:3]","description":"forbids runtime bootstrap manifest from injecting namespace preload entries","full_description":"Namespace guardrails forbids runtime bootstrap manifest from injecting namespace preload entries","status":"passed","file_path":"./spec/core/architecture/namespace_guardrails_spec.rb","line_number":32,"run_time":0.000098374,"pending_message":null},{"id":"./spec/core/architecture/namespace_guardrails_spec.rb[1:1]","description":"forbids shorthand module declarations in runtime code","full_description":"Namespace guardrails forbids shorthand module declarations in runtime code","status":"passed","file_path":"./spec/core/architecture/namespace_guardrails_spec.rb","line_number":13,"run_time":0.033461918,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/menu_workflow_bridges_spec.rb[1:1]","description":"delegates draw_screen to menu controller","full_description":"Shoko::Adapters::Input::Controllers::Menu::MenuWorkflowRuntimeBridge delegates draw_screen to menu controller","status":"passed","file_path":"./spec/adapters/input/controllers/menu/menu_workflow_bridges_spec.rb","line_number":16,"run_time":0.000342552,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/menu_workflow_bridges_spec.rb[1:2]","description":"delegates refresh_scan to catalog scanner","full_description":"Shoko::Adapters::Input::Controllers::Menu::MenuWorkflowRuntimeBridge delegates refresh_scan to catalog scanner","status":"passed","file_path":"./spec/adapters/input/controllers/menu/menu_workflow_bridges_spec.rb","line_number":22,"run_time":0.000172653,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/browse_screen_component_spec.rb[1:6]","description":"renders binary-encoded titles without raising encoding errors","full_description":"Shoko::Adapters::Ui::Components::Screens::BrowseScreenComponent renders binary-encoded titles without raising encoding errors","status":"passed","file_path":"./spec/adapters/ui/components/screens/browse_screen_component_spec.rb","line_number":89,"run_time":0.002025068,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/browse_screen_component_spec.rb[1:5]","description":"keeps status and footer aligned to the centered content area on wide terminals","full_description":"Shoko::Adapters::Ui::Components::Screens::BrowseScreenComponent keeps status and footer aligned to the centered content area on wide terminals","status":"passed","file_path":"./spec/adapters/ui/components/screens/browse_screen_component_spec.rb","line_number":63,"run_time":0.001927534,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/browse_screen_component_spec.rb[1:3]","description":"renders coherent browse layout in dark mode at 120x40","full_description":"Shoko::Adapters::Ui::Components::Screens::BrowseScreenComponent renders coherent browse layout in dark mode at 120x40","status":"passed","file_path":"./spec/adapters/ui/components/screens/browse_screen_component_spec.rb","line_number":51,"run_time":0.001142523,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/browse_screen_component_spec.rb[1:1]","description":"renders coherent browse layout in dark mode at 80x24","full_description":"Shoko::Adapters::Ui::Components::Screens::BrowseScreenComponent renders coherent browse layout in dark mode at 80x24","status":"passed","file_path":"./spec/adapters/ui/components/screens/browse_screen_component_spec.rb","line_number":51,"run_time":0.000507792,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/browse_screen_component_spec.rb[1:4]","description":"renders coherent browse layout in light mode at 120x40","full_description":"Shoko::Adapters::Ui::Components::Screens::BrowseScreenComponent renders coherent browse layout in light mode at 120x40","status":"passed","file_path":"./spec/adapters/ui/components/screens/browse_screen_component_spec.rb","line_number":51,"run_time":0.001190433,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/browse_screen_component_spec.rb[1:2]","description":"renders coherent browse layout in light mode at 80x24","full_description":"Shoko::Adapters::Ui::Components::Screens::BrowseScreenComponent renders coherent browse layout in light mode at 80x24","status":"passed","file_path":"./spec/adapters/ui/components/screens/browse_screen_component_spec.rb","line_number":51,"run_time":0.000460774,"pending_message":null},{"id":"./spec/core/architecture/layer_policy_consistency_spec.rb[1:1]","description":"keeps adapters isolated from application dependencies","full_description":"Layer policy consistency keeps adapters isolated from application dependencies","status":"passed","file_path":"./spec/core/architecture/layer_policy_consistency_spec.rb","line_number":6,"run_time":0.000075041,"pending_message":null},{"id":"./spec/core/architecture/layer_policy_consistency_spec.rb[1:2]","description":"forces architecture specs to use the shared layer policy helper","full_description":"Layer policy consistency forces architecture specs to use the shared layer policy helper","status":"passed","file_path":"./spec/core/architecture/layer_policy_consistency_spec.rb","line_number":11,"run_time":0.000129643,"pending_message":null},{"id":"./spec/core/book_formats/pdf/pdf_reader_spec.rb[1:2]","description":"resolves indirect Length references when reading stream bytes","full_description":"Shoko::Core::BookFormats::Pdf::PdfReader resolves indirect Length references when reading stream bytes","status":"passed","file_path":"./spec/core/book_formats/pdf/pdf_reader_spec.rb","line_number":28,"run_time":0.000110988,"pending_message":null},{"id":"./spec/core/book_formats/pdf/pdf_reader_spec.rb[1:1]","description":"reads raw streams by declared Length without trimming valid trailing newlines","full_description":"Shoko::Core::BookFormats::Pdf::PdfReader reads raw streams by declared Length without trimming valid trailing newlines","status":"passed","file_path":"./spec/core/book_formats/pdf/pdf_reader_spec.rb","line_number":16,"run_time":0.000102833,"pending_message":null},{"id":"./spec/zip/limit_resolver_spec.rb[1:1]","description":"uses the provided value when valid","full_description":"Zip::LimitResolver uses the provided value when valid","status":"passed","file_path":"./spec/zip/limit_resolver_spec.rb","line_number":6,"run_time":0.000059631,"pending_message":null},{"id":"./spec/zip/limit_resolver_spec.rb[1:2]","description":"falls back to default when value is nil","full_description":"Zip::LimitResolver falls back to default when value is nil","status":"passed","file_path":"./spec/zip/limit_resolver_spec.rb","line_number":10,"run_time":0.000049583,"pending_message":null},{"id":"./spec/zip/limit_resolver_spec.rb[1:3]","description":"raises for invalid values","full_description":"Zip::LimitResolver raises for invalid values","status":"passed","file_path":"./spec/zip/limit_resolver_spec.rb","line_number":14,"run_time":0.0000961,"pending_message":null},{"id":"./spec/adapters/input/controllers/reader/render_requester_bridge_spec.rb[1:1]","description":"requests redraw through the controller boundary","full_description":"Shoko::Adapters::Input::Controllers::Reader::RenderRequesterBridge requests redraw through the controller boundary","status":"passed","file_path":"./spec/adapters/input/controllers/reader/render_requester_bridge_spec.rb","line_number":9,"run_time":0.000262432,"pending_message":null},{"id":"./spec/adapters/input/controllers/reader/render_requester_bridge_spec.rb[1:2]","description":"raises typed render request errors when controller redraw fails","full_description":"Shoko::Adapters::Input::Controllers::Reader::RenderRequesterBridge raises typed render request errors when controller redraw fails","status":"passed","file_path":"./spec/adapters/input/controllers/reader/render_requester_bridge_spec.rb","line_number":18,"run_time":0.000312375,"pending_message":null},{"id":"./spec/core/architecture/no_legacy_artifacts_spec.rb[1:1]","description":"forbids legacy architecture directories","full_description":"No legacy runtime artifacts forbids legacy architecture directories","status":"passed","file_path":"./spec/core/architecture/no_legacy_artifacts_spec.rb","line_number":27,"run_time":0.000128421,"pending_message":null},{"id":"./spec/core/architecture/no_legacy_artifacts_spec.rb[1:9]","description":"forbids removed gateway and reader runtime bootstrap artifacts from reappearing","full_description":"No legacy runtime artifacts forbids removed gateway and reader runtime bootstrap artifacts from reappearing","status":"passed","file_path":"./spec/core/architecture/no_legacy_artifacts_spec.rb","line_number":188,"run_time":0.152252495,"pending_message":null},{"id":"./spec/core/architecture/no_legacy_artifacts_spec.rb[1:2]","description":"forbids legacy namespace and path references across runtime/docs","full_description":"No legacy runtime artifacts forbids legacy namespace and path references across runtime/docs","status":"passed","file_path":"./spec/core/architecture/no_legacy_artifacts_spec.rb","line_number":42,"run_time":0.091734972,"pending_message":null},{"id":"./spec/core/architecture/no_legacy_artifacts_spec.rb[1:3]","description":"forbids removed command-port artifacts and references","full_description":"No legacy runtime artifacts forbids removed command-port artifacts and references","status":"passed","file_path":"./spec/core/architecture/no_legacy_artifacts_spec.rb","line_number":68,"run_time":0.062892907,"pending_message":null},{"id":"./spec/core/architecture/no_legacy_artifacts_spec.rb[1:4]","description":"forbids core/ports artifacts outside inbound/outbound trees","full_description":"No legacy runtime artifacts forbids core/ports artifacts outside inbound/outbound trees","status":"passed","file_path":"./spec/core/architecture/no_legacy_artifacts_spec.rb","line_number":91,"run_time":0.000274364,"pending_message":null},{"id":"./spec/core/architecture/no_legacy_artifacts_spec.rb[1:6]","description":"forbids adapter-coupled application command artifacts from reappearing","full_description":"No legacy runtime artifacts forbids adapter-coupled application command artifacts from reappearing","status":"passed","file_path":"./spec/core/architecture/no_legacy_artifacts_spec.rb","line_number":120,"run_time":0.000197961,"pending_message":null},{"id":"./spec/core/architecture/no_legacy_artifacts_spec.rb[1:5]","description":"forbids removed adapter-local contracts from reappearing under core/ports/outbound","full_description":"No legacy runtime artifacts forbids removed adapter-local contracts from reappearing under core/ports/outbound","status":"passed","file_path":"./spec/core/architecture/no_legacy_artifacts_spec.rb","line_number":103,"run_time":0.000144491,"pending_message":null},{"id":"./spec/core/architecture/no_legacy_artifacts_spec.rb[1:8]","description":"forbids deleted runtime orchestration and deprecated port tombstones from reappearing","full_description":"No legacy runtime artifacts forbids deleted runtime orchestration and deprecated port tombstones from reappearing","status":"passed","file_path":"./spec/core/architecture/no_legacy_artifacts_spec.rb","line_number":153,"run_time":0.092686006,"pending_message":null},{"id":"./spec/core/architecture/no_legacy_artifacts_spec.rb[1:7]","description":"forbids explicit legacy path mentions for removed trees","full_description":"No legacy runtime artifacts forbids explicit legacy path mentions for removed trees","status":"passed","file_path":"./spec/core/architecture/no_legacy_artifacts_spec.rb","line_number":136,"run_time":0.046946724,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/line_content_composer_spec.rb[1:6]","description":"returns the same output with compose cache enabled and disabled","full_description":"Shoko::Adapters::Ui::Components::Reading::LineContentComposer returns the same output with compose cache enabled and disabled","status":"passed","file_path":"./spec/adapters/ui/components/reading/line_content_composer_spec.rb","line_number":79,"run_time":0.000440677,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/line_content_composer_spec.rb[1:5]","description":"adds accent styling for keywords in display lines","full_description":"Shoko::Adapters::Ui::Components::Reading::LineContentComposer adds accent styling for keywords in display lines","status":"passed","file_path":"./spec/adapters/ui/components/reading/line_content_composer_spec.rb","line_number":66,"run_time":0.00019184,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/line_content_composer_spec.rb[1:2]","description":"highlights quotes in plain lines when enabled","full_description":"Shoko::Adapters::Ui::Components::Reading::LineContentComposer highlights quotes in plain lines when enabled","status":"passed","file_path":"./spec/adapters/ui/components/reading/line_content_composer_spec.rb","line_number":29,"run_time":0.000176932,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/line_content_composer_spec.rb[1:3]","description":"uses primary color for quote blocks when highlighting is disabled","full_description":"Shoko::Adapters::Ui::Components::Reading::LineContentComposer uses primary color for quote blocks when highlighting is disabled","status":"passed","file_path":"./spec/adapters/ui/components/reading/line_content_composer_spec.rb","line_number":39,"run_time":0.000137668,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/line_content_composer_spec.rb[1:4]","description":"treats legacy blockquote display lines as quote blocks","full_description":"Shoko::Adapters::Ui::Components::Reading::LineContentComposer treats legacy blockquote display lines as quote blocks","status":"passed","file_path":"./spec/adapters/ui/components/reading/line_content_composer_spec.rb","line_number":53,"run_time":0.000137798,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/line_content_composer_spec.rb[1:1]","description":"highlights keywords in plain lines when enabled","full_description":"Shoko::Adapters::Ui::Components::Reading::LineContentComposer highlights keywords in plain lines when enabled","status":"passed","file_path":"./spec/adapters/ui/components/reading/line_content_composer_spec.rb","line_number":20,"run_time":0.000121508,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/line_content_composer_spec.rb[1:7]","description":"reuses cached compose result objects when cache is enabled","full_description":"Shoko::Adapters::Ui::Components::Reading::LineContentComposer reuses cached compose result objects when cache is enabled","status":"passed","file_path":"./spec/adapters/ui/components/reading/line_content_composer_spec.rb","line_number":99,"run_time":0.000122289,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_importer_spec.rb[1:1:3:2]","description":"reports .rtf as supported","full_description":"Shoko::Adapters::BookSources::Rtf::RtfImporter#import FormatRegistry integration reports .rtf as supported","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_importer_spec.rb","line_number":112,"run_time":0.000103654,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_importer_spec.rb[1:1:3:1]","description":"is registered for .rtf","full_description":"Shoko::Adapters::BookSources::Rtf::RtfImporter#import FormatRegistry integration is registered for .rtf","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_importer_spec.rb","line_number":107,"run_time":0.0000905,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_importer_spec.rb[1:1:2:1]","description":"raises FileNotFoundError for missing file","full_description":"Shoko::Adapters::BookSources::Rtf::RtfImporter#import error handling raises FileNotFoundError for missing file","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_importer_spec.rb","line_number":87,"run_time":0.000199945,"pending_message":null},{"id":"./spec/core/book_formats/rtf/rtf_importer_spec.rb[1:1:2:2]","description":"raises BookParseError for invalid file content","full_description":"Shoko::Adapters::BookSources::Rtf::RtfImporter#import error handling raises BookParseError for invalid file content","status":"passed","file_path":"./spec/core/book_formats/rtf/rtf_importer_spec.rb","line_number":93,"run_time":0.000332724,"pending_message":null},{"id":"./spec/application/services/reader/annotation_state_service_spec.rb[1:1]","description":"refreshes reader annotations after add","full_description":"Shoko::Application::Services::Reader::AnnotationStateService refreshes reader annotations after add","status":"passed","file_path":"./spec/application/services/reader/annotation_state_service_spec.rb","line_number":20,"run_time":0.000643066,"pending_message":null},{"id":"./spec/application/services/reader/annotation_state_service_spec.rb[1:3]","description":"fails fast when refresh raises","full_description":"Shoko::Application::Services::Reader::AnnotationStateService fails fast when refresh raises","status":"passed","file_path":"./spec/application/services/reader/annotation_state_service_spec.rb","line_number":47,"run_time":0.000365315,"pending_message":null},{"id":"./spec/application/services/reader/annotation_state_service_spec.rb[1:2]","description":"refreshes reader annotations after update and delete","full_description":"Shoko::Application::Services::Reader::AnnotationStateService refreshes reader annotations after update and delete","status":"passed","file_path":"./spec/application/services/reader/annotation_state_service_spec.rb","line_number":33,"run_time":0.000720121,"pending_message":null},{"id":"./spec/adapters/output/terminal/terminal_color_mode_spec.rb[1:3]","description":"queries OSC only when explicitly enabled","full_description":"Shoko::Adapters::Output::Terminal::Terminal queries OSC only when explicitly enabled","status":"passed","file_path":"./spec/adapters/output/terminal/terminal_color_mode_spec.rb","line_number":32,"run_time":0.000302357,"pending_message":null},{"id":"./spec/adapters/output/terminal/terminal_color_mode_spec.rb[1:2]","description":"uses COLORFGBG before OSC queries when set","full_description":"Shoko::Adapters::Output::Terminal::Terminal uses COLORFGBG before OSC queries when set","status":"passed","file_path":"./spec/adapters/output/terminal/terminal_color_mode_spec.rb","line_number":23,"run_time":0.00016559,"pending_message":null},{"id":"./spec/adapters/output/terminal/terminal_color_mode_spec.rb[1:1]","description":"honors explicit SHOKO_COLOR_MODE without querying OSC","full_description":"Shoko::Adapters::Output::Terminal::Terminal honors explicit SHOKO_COLOR_MODE without querying OSC","status":"passed","file_path":"./spec/adapters/output/terminal/terminal_color_mode_spec.rb","line_number":14,"run_time":0.00014954,"pending_message":null},{"id":"./spec/adapters/output/terminal/buffer_spec.rb[1:3]","description":"handles binary-encoded input without raising encoding errors","full_description":"Shoko::Adapters::Output::Terminal::TerminalBuffer::Frame handles binary-encoded input without raising encoding errors","status":"passed","file_path":"./spec/adapters/output/terminal/buffer_spec.rb","line_number":34,"run_time":0.000222767,"pending_message":null},{"id":"./spec/adapters/output/terminal/buffer_spec.rb[1:2]","description":"preserves ANSI and tab behavior when fast path is enabled","full_description":"Shoko::Adapters::Output::Terminal::TerminalBuffer::Frame preserves ANSI and tab behavior when fast path is enabled","status":"passed","file_path":"./spec/adapters/output/terminal/buffer_spec.rb","line_number":25,"run_time":0.000167284,"pending_message":null},{"id":"./spec/adapters/output/terminal/buffer_spec.rb[1:1]","description":"produces identical output for ASCII text with fast path on and off","full_description":"Shoko::Adapters::Output::Terminal::TerminalBuffer::Frame produces identical output for ASCII text with fast path on and off","status":"passed","file_path":"./spec/adapters/output/terminal/buffer_spec.rb","line_number":16,"run_time":0.000204323,"pending_message":null},{"id":"./spec/adapters/storage/json_cache_store_spec.rb[1:1]","description":"writes and reads cached payloads","full_description":"Shoko::Adapters::Storage::JsonCacheStore writes and reads cached payloads","status":"passed","file_path":"./spec/adapters/storage/json_cache_store_spec.rb","line_number":7,"run_time":0.001408281,"pending_message":null},{"id":"./spec/adapters/storage/json_cache_store_spec.rb[1:2]","description":"mutates layouts in place","full_description":"Shoko::Adapters::Storage::JsonCacheStore mutates layouts in place","status":"passed","file_path":"./spec/adapters/storage/json_cache_store_spec.rb","line_number":46,"run_time":0.000818545,"pending_message":null},{"id":"./spec/application/use_cases/catalog_service_spec.rb[1:3]","description":"returns an empty list when no cached entries exist","full_description":"Shoko::Application::UseCases::CatalogService returns an empty list when no cached entries exist","status":"passed","file_path":"./spec/application/use_cases/catalog_service_spec.rb","line_number":45,"run_time":0.000318267,"pending_message":null},{"id":"./spec/application/use_cases/catalog_service_spec.rb[1:1]","description":"adds last_accessed from recent files when listing cached books","full_description":"Shoko::Application::UseCases::CatalogService adds last_accessed from recent files when listing cached books","status":"passed","file_path":"./spec/application/use_cases/catalog_service_spec.rb","line_number":21,"run_time":0.000279083,"pending_message":null},{"id":"./spec/application/use_cases/catalog_service_spec.rb[1:2]","description":"returns an empty list when cached repository is not available","full_description":"Shoko::Application::UseCases::CatalogService returns an empty list when cached repository is not available","status":"passed","file_path":"./spec/application/use_cases/catalog_service_spec.rb","line_number":36,"run_time":0.000237765,"pending_message":null},{"id":"./spec/adapters/input/controllers/sidebar_mouse_handler_spec.rb[1:1:1]","description":"throttles rapid same-direction wheel events","full_description":"Shoko::Adapters::Input::Controllers::SidebarMouseHandler#sidebar_wheel_event_allowed? throttles rapid same-direction wheel events","status":"passed","file_path":"./spec/adapters/input/controllers/sidebar_mouse_handler_spec.rb","line_number":13,"run_time":0.000242225,"pending_message":null},{"id":"./spec/adapters/input/controllers/sidebar_mouse_handler_spec.rb[1:1:2]","description":"allows immediate direction changes","full_description":"Shoko::Adapters::Input::Controllers::SidebarMouseHandler#sidebar_wheel_event_allowed? allows immediate direction changes","status":"passed","file_path":"./spec/adapters/input/controllers/sidebar_mouse_handler_spec.rb","line_number":25,"run_time":0.000169698,"pending_message":null},{"id":"./spec/core/architecture/no_rescue_numeric_default_spec.rb[1:1]","description":"forbids rescue branches that default to numeric literals","full_description":"No rescue numeric defaults forbids rescue branches that default to numeric literals","status":"passed","file_path":"./spec/core/architecture/no_rescue_numeric_default_spec.rb","line_number":9,"run_time":0.608347325,"pending_message":null},{"id":"./spec/bin/start_spec.rb[1:1]","description":"invokes the CLI directly without gem bin recursion","full_description":"bin/start invokes the CLI directly without gem bin recursion","status":"passed","file_path":"./spec/bin/start_spec.rb","line_number":6,"run_time":0.000169839,"pending_message":null},{"id":"./spec/core/ports/outbound/state_and_input_ports_spec.rb[1:6]","description":"defines ReaderRenderRequester contract methods","full_description":"Application state and boundary port contracts defines ReaderRenderRequester contract methods","status":"passed","file_path":"./spec/core/ports/outbound/state_and_input_ports_spec.rb","line_number":93,"run_time":0.000142086,"pending_message":null},{"id":"./spec/core/ports/outbound/state_and_input_ports_spec.rb[1:4]","description":"defines PaginationStateWriter contract methods","full_description":"Application state and boundary port contracts defines PaginationStateWriter contract methods","status":"passed","file_path":"./spec/core/ports/outbound/state_and_input_ports_spec.rb","line_number":65,"run_time":0.000127029,"pending_message":null},{"id":"./spec/core/ports/outbound/state_and_input_ports_spec.rb[1:2]","description":"defines SidebarStateReader contract methods","full_description":"Application state and boundary port contracts defines SidebarStateReader contract methods","status":"passed","file_path":"./spec/core/ports/outbound/state_and_input_ports_spec.rb","line_number":37,"run_time":0.000153137,"pending_message":null},{"id":"./spec/core/ports/outbound/state_and_input_ports_spec.rb[1:7]","description":"defines FolderScanner and FolderImporter contract methods","full_description":"Application state and boundary port contracts defines FolderScanner and FolderImporter contract methods","status":"passed","file_path":"./spec/core/ports/outbound/state_and_input_ports_spec.rb","line_number":102,"run_time":0.000102892,"pending_message":null},{"id":"./spec/core/ports/outbound/state_and_input_ports_spec.rb[1:5]","description":"defines ReaderStateWriter contract methods","full_description":"Application state and boundary port contracts defines ReaderStateWriter contract methods","status":"passed","file_path":"./spec/core/ports/outbound/state_and_input_ports_spec.rb","line_number":76,"run_time":0.000243166,"pending_message":null},{"id":"./spec/core/ports/outbound/state_and_input_ports_spec.rb[1:1]","description":"defines UiStateReader contract methods","full_description":"Application state and boundary port contracts defines UiStateReader contract methods","status":"passed","file_path":"./spec/core/ports/outbound/state_and_input_ports_spec.rb","line_number":24,"run_time":0.000124304,"pending_message":null},{"id":"./spec/core/ports/outbound/state_and_input_ports_spec.rb[1:3]","description":"defines CommandBus inbound contract methods","full_description":"Application state and boundary port contracts defines CommandBus inbound contract methods","status":"passed","file_path":"./spec/core/ports/outbound/state_and_input_ports_spec.rb","line_number":54,"run_time":0.000121187,"pending_message":null},{"id":"./spec/adapters/ui/components/ui/annotation_markup_spec.rb[1:1]","description":"keeps markers and applies strikethrough","full_description":"Shoko::Adapters::Ui::Components::Ui::AnnotationMarkup keeps markers and applies strikethrough","status":"passed","file_path":"./spec/adapters/ui/components/ui/annotation_markup_spec.rb","line_number":10,"run_time":0.000187963,"pending_message":null},{"id":"./spec/adapters/ui/components/ui/annotation_markup_spec.rb[1:2]","description":"applies bold markers","full_description":"Shoko::Adapters::Ui::Components::Ui::AnnotationMarkup applies bold markers","status":"passed","file_path":"./spec/adapters/ui/components/ui/annotation_markup_spec.rb","line_number":18,"run_time":0.000107662,"pending_message":null},{"id":"./spec/adapters/ui/components/ui/annotation_markup_spec.rb[1:5]","description":"allows escaping markers","full_description":"Shoko::Adapters::Ui::Components::Ui::AnnotationMarkup allows escaping markers","status":"passed","file_path":"./spec/adapters/ui/components/ui/annotation_markup_spec.rb","line_number":43,"run_time":0.000094728,"pending_message":null},{"id":"./spec/adapters/ui/components/ui/annotation_markup_spec.rb[1:4]","description":"carries styles across lines","full_description":"Shoko::Adapters::Ui::Components::Ui::AnnotationMarkup carries styles across lines","status":"passed","file_path":"./spec/adapters/ui/components/ui/annotation_markup_spec.rb","line_number":35,"run_time":0.000098084,"pending_message":null},{"id":"./spec/adapters/ui/components/ui/annotation_markup_spec.rb[1:6]","description":"keeps unmatched markers visible and unstyled","full_description":"Shoko::Adapters::Ui::Components::Ui::AnnotationMarkup keeps unmatched markers visible and unstyled","status":"passed","file_path":"./spec/adapters/ui/components/ui/annotation_markup_spec.rb","line_number":51,"run_time":0.000092294,"pending_message":null},{"id":"./spec/adapters/ui/components/ui/annotation_markup_spec.rb[1:7]","description":"moves cursor left and right by visible characters","full_description":"Shoko::Adapters::Ui::Components::Ui::AnnotationMarkup moves cursor left and right by visible characters","status":"passed","file_path":"./spec/adapters/ui/components/ui/annotation_markup_spec.rb","line_number":59,"run_time":0.000113052,"pending_message":null},{"id":"./spec/adapters/ui/components/ui/annotation_markup_spec.rb[1:3]","description":"does not parse nested markers inside code","full_description":"Shoko::Adapters::Ui::Components::Ui::AnnotationMarkup does not parse nested markers inside code","status":"passed","file_path":"./spec/adapters/ui/components/ui/annotation_markup_spec.rb","line_number":26,"run_time":0.0001014,"pending_message":null},{"id":"./spec/adapters/ui/components/ui/annotation_markup_spec.rb[1:8]","description":"moves cursor up and down across lines","full_description":"Shoko::Adapters::Ui::Components::Ui::AnnotationMarkup moves cursor up and down across lines","status":"passed","file_path":"./spec/adapters/ui/components/ui/annotation_markup_spec.rb","line_number":67,"run_time":0.000099246,"pending_message":null},{"id":"./spec/core/architecture/no_swallowing_rescue_spec.rb[1:1]","description":"requires fatal external-input rescue branches to terminate or re-raise","full_description":"No swallowing fatal-input rescues requires fatal external-input rescue branches to terminate or re-raise","status":"passed","file_path":"./spec/core/architecture/no_swallowing_rescue_spec.rb","line_number":47,"run_time":0.000529192,"pending_message":null},{"id":"./spec/application/use_cases/commands/navigation_command_spec.rb[1:1]","description":"executes semantic navigation with typed context","full_description":"Shoko::Application::UseCases::Commands::NavigationCommand executes semantic navigation with typed context","status":"passed","file_path":"./spec/application/use_cases/commands/navigation_command_spec.rb","line_number":31,"run_time":0.000390001,"pending_message":null},{"id":"./spec/application/use_cases/commands/navigation_command_spec.rb[1:2]","description":"fails deterministically for untyped context","full_description":"Shoko::Application::UseCases::Commands::NavigationCommand fails deterministically for untyped context","status":"passed","file_path":"./spec/application/use_cases/commands/navigation_command_spec.rb","line_number":42,"run_time":0.000153958,"pending_message":null},{"id":"./spec/core/ports/outbound/reader_navigation_reader_spec.rb[1:1]","description":"defines required navigation reader methods","full_description":"Shoko::Core::Ports::Outbound::ReaderNavigationReader defines required navigation reader methods","status":"passed","file_path":"./spec/core/ports/outbound/reader_navigation_reader_spec.rb","line_number":12,"run_time":0.000238537,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch/document_preparation_spec.rb[1:1]","description":"loads and registers reader document when canonical path differs","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunch::DocumentPreparation loads and registers reader document when canonical path differs","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch/document_preparation_spec.rb","line_number":47,"run_time":0.000630141,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch/document_preparation_spec.rb[1:2]","description":"reuses current document when canonical path already matches","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunch::DocumentPreparation reuses current document when canonical path already matches","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch/document_preparation_spec.rb","line_number":63,"run_time":0.000434064,"pending_message":null},{"id":"./spec/core/services/dictionary_service_spec.rb[1:2:3]","description":"returns empty when fuzzy search raises a typed repository failure","full_description":"Shoko::Core::Services::DictionaryService#fuzzy_search returns empty when fuzzy search raises a typed repository failure","status":"passed","file_path":"./spec/core/services/dictionary_service_spec.rb","line_number":134,"run_time":0.000359134,"pending_message":null},{"id":"./spec/core/services/dictionary_service_spec.rb[1:2:1]","description":"maps repository matches to FuzzyMatch objects","full_description":"Shoko::Core::Services::DictionaryService#fuzzy_search maps repository matches to FuzzyMatch objects","status":"passed","file_path":"./spec/core/services/dictionary_service_spec.rb","line_number":115,"run_time":0.000301585,"pending_message":null},{"id":"./spec/core/services/dictionary_service_spec.rb[1:2:2]","description":"returns empty when repository is missing","full_description":"Shoko::Core::Services::DictionaryService#fuzzy_search returns empty when repository is missing","status":"passed","file_path":"./spec/core/services/dictionary_service_spec.rb","line_number":125,"run_time":0.000155522,"pending_message":null},{"id":"./spec/core/services/dictionary_service_spec.rb[1:3:1]","description":"returns true when repository reports pairs","full_description":"Shoko::Core::Services::DictionaryService#available? returns true when repository reports pairs","status":"passed","file_path":"./spec/core/services/dictionary_service_spec.rb","line_number":148,"run_time":0.000211226,"pending_message":null},{"id":"./spec/core/services/dictionary_service_spec.rb[1:3:2]","description":"returns false when repository is missing","full_description":"Shoko::Core::Services::DictionaryService#available? returns false when repository is missing","status":"passed","file_path":"./spec/core/services/dictionary_service_spec.rb","line_number":153,"run_time":0.000123432,"pending_message":null},{"id":"./spec/core/services/dictionary_service_spec.rb[1:1:2]","description":"returns unavailable result when repository is nil","full_description":"Shoko::Core::Services::DictionaryService#lookup returns unavailable result when repository is nil","status":"passed","file_path":"./spec/core/services/dictionary_service_spec.rb","line_number":28,"run_time":0.000161583,"pending_message":null},{"id":"./spec/core/services/dictionary_service_spec.rb[1:1:3]","description":"returns unavailable result when language pair is missing","full_description":"Shoko::Core::Services::DictionaryService#lookup returns unavailable result when language pair is missing","status":"passed","file_path":"./spec/core/services/dictionary_service_spec.rb","line_number":39,"run_time":0.000236233,"pending_message":null},{"id":"./spec/core/services/dictionary_service_spec.rb[1:1:6]","description":"falls back to default languages when config is blank","full_description":"Shoko::Core::Services::DictionaryService#lookup falls back to default languages when config is blank","status":"passed","file_path":"./spec/core/services/dictionary_service_spec.rb","line_number":80,"run_time":0.000286818,"pending_message":null},{"id":"./spec/core/services/dictionary_service_spec.rb[1:1:7]","description":"returns typed error result when repository raises a typed failure","full_description":"Shoko::Core::Services::DictionaryService#lookup returns typed error result when repository raises a typed failure","status":"passed","file_path":"./spec/core/services/dictionary_service_spec.rb","line_number":99,"run_time":0.000285124,"pending_message":null},{"id":"./spec/core/services/dictionary_service_spec.rb[1:1:4]","description":"builds dictionary entries from repository results","full_description":"Shoko::Core::Services::DictionaryService#lookup builds dictionary entries from repository results","status":"passed","file_path":"./spec/core/services/dictionary_service_spec.rb","line_number":46,"run_time":0.000291236,"pending_message":null},{"id":"./spec/core/services/dictionary_service_spec.rb[1:1:1]","description":"returns an empty result for blank input","full_description":"Shoko::Core::Services::DictionaryService#lookup returns an empty result for blank input","status":"passed","file_path":"./spec/core/services/dictionary_service_spec.rb","line_number":22,"run_time":0.000142607,"pending_message":null},{"id":"./spec/core/services/dictionary_service_spec.rb[1:1:5]","description":"passes configured languages to repository search","full_description":"Shoko::Core::Services::DictionaryService#lookup passes configured languages to repository search","status":"passed","file_path":"./spec/core/services/dictionary_service_spec.rb","line_number":68,"run_time":0.000268704,"pending_message":null},{"id":"./spec/core/services/dictionary_service_spec.rb[1:4:2]","description":"returns empty when repository is missing","full_description":"Shoko::Core::Services::DictionaryService#available_language_pairs returns empty when repository is missing","status":"passed","file_path":"./spec/core/services/dictionary_service_spec.rb","line_number":169,"run_time":0.000131857,"pending_message":null},{"id":"./spec/core/services/dictionary_service_spec.rb[1:4:1]","description":"returns pairs from repository","full_description":"Shoko::Core::Services::DictionaryService#available_language_pairs returns pairs from repository","status":"passed","file_path":"./spec/core/services/dictionary_service_spec.rb","line_number":164,"run_time":0.000222257,"pending_message":null},{"id":"./spec/core/architecture/layer_dependency_spec.rb[1:3]","description":"forbids local requires into adapters from shared","full_description":"Layer dependency boundaries forbids local requires into adapters from shared","status":"passed","file_path":"./spec/core/architecture/layer_dependency_spec.rb","line_number":83,"run_time":0.002913173,"pending_message":null},{"id":"./spec/core/architecture/layer_dependency_spec.rb[1:1]","description":"enforces strict layer dependency matrix","full_description":"Layer dependency boundaries enforces strict layer dependency matrix","status":"passed","file_path":"./spec/core/architecture/layer_dependency_spec.rb","line_number":47,"run_time":0.150887495,"pending_message":null},{"id":"./spec/core/architecture/layer_dependency_spec.rb[1:2]","description":"forbids local requires into bootstrap from application and adapters","full_description":"Layer dependency boundaries forbids local requires into bootstrap from application and adapters","status":"passed","file_path":"./spec/core/architecture/layer_dependency_spec.rb","line_number":69,"run_time":0.082801189,"pending_message":null},{"id":"./spec/core/architecture/layer_dependency_spec.rb[1:4]","description":"forbids Shoko::Bootstrap constants outside bootstrap, bin, and test_support","full_description":"Layer dependency boundaries forbids Shoko::Bootstrap constants outside bootstrap, bin, and test_support","status":"passed","file_path":"./spec/core/architecture/layer_dependency_spec.rb","line_number":97,"run_time":0.032133677,"pending_message":null},{"id":"./spec/core/architecture/layer_dependency_spec.rb[1:5]","description":"forbids context.ui_controller/state_controller in application command use-cases","full_description":"Layer dependency boundaries forbids context.ui_controller/state_controller in application command use-cases","status":"passed","file_path":"./spec/core/architecture/layer_dependency_spec.rb","line_number":111,"run_time":0.001433929,"pending_message":null},{"id":"./spec/core/services/pagination/internal/pagination_workflow_spec.rb[1:1]","description":"passes text metrics to absolute pagination fallback builder","full_description":"Shoko::Core::Services::Pagination::Internal::PaginationWorkflow passes text metrics to absolute pagination fallback builder","status":"passed","file_path":"./spec/core/services/pagination/internal/pagination_workflow_spec.rb","line_number":6,"run_time":0.001202004,"pending_message":null},{"id":"./spec/adapters/storage/data_cleanup_adapter_spec.rb[1:3:1]","description":"removes only selected user data files","full_description":"Shoko::Adapters::Storage::DataCleanupAdapter#remove_user_data_files removes only selected user data files","status":"passed","file_path":"./spec/adapters/storage/data_cleanup_adapter_spec.rb","line_number":38,"run_time":0.000511149,"pending_message":null},{"id":"./spec/adapters/storage/data_cleanup_adapter_spec.rb[1:1:1]","description":"removes cache directory when basename is allowed","full_description":"Shoko::Adapters::Storage::DataCleanupAdapter#remove_cache_root removes cache directory when basename is allowed","status":"passed","file_path":"./spec/adapters/storage/data_cleanup_adapter_spec.rb","line_number":10,"run_time":0.000284714,"pending_message":null},{"id":"./spec/adapters/storage/data_cleanup_adapter_spec.rb[1:2:1]","description":"removes downloads directory under config root","full_description":"Shoko::Adapters::Storage::DataCleanupAdapter#remove_downloads_root removes downloads directory under config root","status":"passed","file_path":"./spec/adapters/storage/data_cleanup_adapter_spec.rb","line_number":24,"run_time":0.00027751,"pending_message":null},{"id":"./spec/core/architecture/book_rendering_guardrails_spec.rb[1:2]","description":"forbids removed dead BookDocument artifacts from reappearing","full_description":"Book rendering and extraction guardrails forbids removed dead BookDocument artifacts from reappearing","status":"passed","file_path":"./spec/core/architecture/book_rendering_guardrails_spec.rb","line_number":22,"run_time":0.000265348,"pending_message":null},{"id":"./spec/core/architecture/book_rendering_guardrails_spec.rb[1:3]","description":"forbids reintroduction of removed DocumentService TOC API","full_description":"Book rendering and extraction guardrails forbids reintroduction of removed DocumentService TOC API","status":"passed","file_path":"./spec/core/architecture/book_rendering_guardrails_spec.rb","line_number":40,"run_time":0.000196127,"pending_message":null},{"id":"./spec/core/architecture/book_rendering_guardrails_spec.rb[1:1]","description":"forbids adapter-local reader document path resolver duplication","full_description":"Book rendering and extraction guardrails forbids adapter-local reader document path resolver duplication","status":"passed","file_path":"./spec/core/architecture/book_rendering_guardrails_spec.rb","line_number":15,"run_time":0.000083987,"pending_message":null},{"id":"./spec/adapters/storage/repositories/storage/annotation_file_store_spec.rb[1:1]","description":"generates unique ids even when entries share the same timestamp","full_description":"Shoko::Adapters::Storage::Repositories::Storage::AnnotationFileStore generates unique ids even when entries share the same timestamp","status":"passed","file_path":"./spec/adapters/storage/repositories/storage/annotation_file_store_spec.rb","line_number":23,"run_time":0.00062398,"pending_message":null},{"id":"./spec/core/ports/inbound/reader_command_contexts_spec.rb[1:1]","description":"defines ReaderNavigationCommandContext methods","full_description":"Reader semantic command context contracts defines ReaderNavigationCommandContext methods","status":"passed","file_path":"./spec/core/ports/inbound/reader_command_contexts_spec.rb","line_number":12,"run_time":0.000148218,"pending_message":null},{"id":"./spec/core/ports/inbound/reader_command_contexts_spec.rb[1:2]","description":"defines ReaderBookmarkCommandContext methods","full_description":"Reader semantic command context contracts defines ReaderBookmarkCommandContext methods","status":"passed","file_path":"./spec/core/ports/inbound/reader_command_contexts_spec.rb","line_number":19,"run_time":0.000110537,"pending_message":null},{"id":"./spec/adapters/runtime/rexml_security_limits_adapter_spec.rb[1:1]","description":"applies entity expansion limits from runtime config","full_description":"Shoko::Adapters::Runtime::REXMLSecurityLimitsAdapter applies entity expansion limits from runtime config","status":"passed","file_path":"./spec/adapters/runtime/rexml_security_limits_adapter_spec.rb","line_number":6,"run_time":0.000186048,"pending_message":null},{"id":"./spec/core/services/in_book_search_service_spec.rb[1:4]","description":"returns empty result for blank query","full_description":"Shoko::Core::Services::InBookSearchService returns empty result for blank query","status":"passed","file_path":"./spec/core/services/in_book_search_service_spec.rb","line_number":100,"run_time":0.000191359,"pending_message":null},{"id":"./spec/core/services/in_book_search_service_spec.rb[1:2]","description":"matches full words for simple word queries","full_description":"Shoko::Core::Services::InBookSearchService matches full words for simple word queries","status":"passed","file_path":"./spec/core/services/in_book_search_service_spec.rb","line_number":83,"run_time":0.000561913,"pending_message":null},{"id":"./spec/core/services/in_book_search_service_spec.rb[1:3]","description":"caps the number of returned matches while keeping full total count","full_description":"Shoko::Core::Services::InBookSearchService caps the number of returned matches while keeping full total count","status":"passed","file_path":"./spec/core/services/in_book_search_service_spec.rb","line_number":93,"run_time":0.000717746,"pending_message":null},{"id":"./spec/core/services/in_book_search_service_spec.rb[1:5]","description":"scans all chapters through get_chapter when chapter content is lazily hydrated","full_description":"Shoko::Core::Services::InBookSearchService scans all chapters through get_chapter when chapter content is lazily hydrated","status":"passed","file_path":"./spec/core/services/in_book_search_service_spec.rb","line_number":107,"run_time":0.0005276,"pending_message":null},{"id":"./spec/core/services/in_book_search_service_spec.rb[1:1]","description":"finds matches across chapters with context","full_description":"Shoko::Core::Services::InBookSearchService finds matches across chapters with context","status":"passed","file_path":"./spec/core/services/in_book_search_service_spec.rb","line_number":71,"run_time":0.000807233,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb[1:7:1]","description":"respects minimum overlay dimensions","full_description":"Shoko::Adapters::Ui::Components::DictionaryPopupComponent overlay sizing respects minimum overlay dimensions","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb","line_number":205,"run_time":0.000141605,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb[1:4:1]","description":"returns close for cancel key","full_description":"Shoko::Adapters::Ui::Components::DictionaryPopupComponent#handle_key returns close for cancel key","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb","line_number":63,"run_time":0.000126758,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb[1:2:2]","description":"does not advance while in fuzzy mode","full_description":"Shoko::Adapters::Ui::Components::DictionaryPopupComponent#next_entry does not advance while in fuzzy mode","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb","line_number":44,"run_time":0.000109295,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb[1:2:1]","description":"cycles through entries when available","full_description":"Shoko::Adapters::Ui::Components::DictionaryPopupComponent#next_entry cycles through entries when available","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb","line_number":37,"run_time":0.000112371,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb[1:6:2]","description":"supports suggestion navigation and quick-apply keys","full_description":"Shoko::Adapters::Ui::Components::DictionaryPopupComponent setup mode supports suggestion navigation and quick-apply keys","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb","line_number":125,"run_time":0.00017572,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb[1:6:3]","description":"emits a swap event on S in target stage","full_description":"Shoko::Adapters::Ui::Components::DictionaryPopupComponent setup mode emits a swap event on S in target stage","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb","line_number":143,"run_time":0.000085039,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb[1:6:4]","description":"keeps existing result mode behavior unchanged","full_description":"Shoko::Adapters::Ui::Components::DictionaryPopupComponent setup mode keeps existing result mode behavior unchanged","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb","line_number":156,"run_time":0.000110887,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb[1:6:1]","description":"enters setup mode and emits submit/change events","full_description":"Shoko::Adapters::Ui::Components::DictionaryPopupComponent setup mode enters setup mode and emits submit/change events","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb","line_number":107,"run_time":0.000244058,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb[1:6:5]","description":"renders structured setup lines without full reset codes","full_description":"Shoko::Adapters::Ui::Components::DictionaryPopupComponent setup mode renders structured setup lines without full reset codes","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb","line_number":163,"run_time":0.000276899,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb[1:6:6]","description":"uses import-style progress bar glyphs in downloading stage","full_description":"Shoko::Adapters::Ui::Components::DictionaryPopupComponent setup mode uses import-style progress bar glyphs in downloading stage","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb","line_number":187,"run_time":0.000126176,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb[1:3:1]","description":"toggles fuzzy mode on and off","full_description":"Shoko::Adapters::Ui::Components::DictionaryPopupComponent#toggle_fuzzy toggles fuzzy mode on and off","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb","line_number":52,"run_time":0.000099898,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb[1:5:2]","description":"renders setup content (not a blank popup)","full_description":"Shoko::Adapters::Ui::Components::DictionaryPopupComponent#render renders setup content (not a blank popup)","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb","line_number":89,"run_time":0.001435011,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb[1:5:1]","description":"renders lookup result content (not a blank popup)","full_description":"Shoko::Adapters::Ui::Components::DictionaryPopupComponent#render renders lookup result content (not a blank popup)","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb","line_number":79,"run_time":0.000507171,"pending_message":null},{"id":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb[1:1:1]","description":"toggles visibility and resets state","full_description":"Shoko::Adapters::Ui::Components::DictionaryPopupComponent#show and #hide toggles visibility and resets state","status":"passed","file_path":"./spec/adapters/ui/components/dictionary_popup_component_spec.rb","line_number":24,"run_time":0.000110047,"pending_message":null},{"id":"./spec/core/ports/inbound/reader_intent_handler_spec.rb[1:2]","description":"raises NotImplementedError for unimplemented methods by default","full_description":"Shoko::Core::Ports::Inbound::ReaderIntentHandler raises NotImplementedError for unimplemented methods by default","status":"passed","file_path":"./spec/core/ports/inbound/reader_intent_handler_spec.rb","line_number":66,"run_time":0.000126247,"pending_message":null},{"id":"./spec/core/ports/inbound/reader_intent_handler_spec.rb[1:1]","description":"defines explicit reader intent symbols","full_description":"Shoko::Core::Ports::Inbound::ReaderIntentHandler defines explicit reader intent symbols","status":"passed","file_path":"./spec/core/ports/inbound/reader_intent_handler_spec.rb","line_number":12,"run_time":0.000057087,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/annotation_edit_screen_component_spec.rb[1:1]","description":"renders the annotation editor without raising","full_description":"Shoko::Adapters::Ui::Components::Screens::AnnotationEditScreenComponent renders the annotation editor without raising","status":"passed","file_path":"./spec/adapters/ui/components/screens/annotation_edit_screen_component_spec.rb","line_number":48,"run_time":0.001586265,"pending_message":null},{"id":"./spec/core/architecture/no_mixed_symbol_string_key_reads_in_application_spec.rb[1:1]","description":"forbids `x[:k] || x['k']` dual-key fallback reads","full_description":"No mixed key reads in application layer forbids `x[:k] || x['k']` dual-key fallback reads","status":"passed","file_path":"./spec/core/architecture/no_mixed_symbol_string_key_reads_in_application_spec.rb","line_number":18,"run_time":0.006602471,"pending_message":null},{"id":"./spec/application/services/pagination/pagination_coordinator_spec.rb[1:5]","description":"keeps pagination rebuild successful when render requester raises typed failure","full_description":"Shoko::Application::Services::Pagination::PaginationCoordinator keeps pagination rebuild successful when render requester raises typed failure","status":"passed","file_path":"./spec/application/services/pagination/pagination_coordinator_spec.rb","line_number":117,"run_time":0.000962445,"pending_message":null},{"id":"./spec/application/services/pagination/pagination_coordinator_spec.rb[1:1]","description":"applies pending progress when page map already exists","full_description":"Shoko::Application::Services::Pagination::PaginationCoordinator applies pending progress when page map already exists","status":"passed","file_path":"./spec/application/services/pagination/pagination_coordinator_spec.rb","line_number":51,"run_time":0.000617548,"pending_message":null},{"id":"./spec/application/services/pagination/pagination_coordinator_spec.rb[1:3]","description":"routes sidebar layout sync through pagination session in dynamic mode","full_description":"Shoko::Application::Services::Pagination::PaginationCoordinator routes sidebar layout sync through pagination session in dynamic mode","status":"passed","file_path":"./spec/application/services/pagination/pagination_coordinator_spec.rb","line_number":72,"run_time":0.000631304,"pending_message":null},{"id":"./spec/application/services/pagination/pagination_coordinator_spec.rb[1:2]","description":"skips applying pending progress when no pages are built","full_description":"Shoko::Application::Services::Pagination::PaginationCoordinator skips applying pending progress when no pages are built","status":"passed","file_path":"./spec/application/services/pagination/pagination_coordinator_spec.rb","line_number":63,"run_time":0.000625894,"pending_message":null},{"id":"./spec/application/services/pagination/pagination_coordinator_spec.rb[1:6]","description":"invalidates pagination cache via session and publishes success notification","full_description":"Shoko::Application::Services::Pagination::PaginationCoordinator invalidates pagination cache via session and publishes success notification","status":"passed","file_path":"./spec/application/services/pagination/pagination_coordinator_spec.rb","line_number":134,"run_time":0.000828724,"pending_message":null},{"id":"./spec/application/services/pagination/pagination_coordinator_spec.rb[1:4]","description":"rebuilds pagination through session and requests a render","full_description":"Shoko::Application::Services::Pagination::PaginationCoordinator rebuilds pagination through session and requests a render","status":"passed","file_path":"./spec/application/services/pagination/pagination_coordinator_spec.rb","line_number":95,"run_time":0.000890199,"pending_message":null},{"id":"./spec/adapters/storage/recent_files_spec.rb[1:1]","description":"adds and clears recent file entries","full_description":"Shoko::Adapters::Storage::RecentFiles adds and clears recent file entries","status":"passed","file_path":"./spec/adapters/storage/recent_files_spec.rb","line_number":6,"run_time":0.000615484,"pending_message":null},{"id":"./spec/core/book_formats/kindle/mobi_header_parser_spec.rb[1:7]","description":"reads extra_data_flags correctly","full_description":"Shoko::Core::BookFormats::Kindle::MobiHeaderParser reads extra_data_flags correctly","status":"passed","file_path":"./spec/core/book_formats/kindle/mobi_header_parser_spec.rb","line_number":118,"run_time":0.000187321,"pending_message":null},{"id":"./spec/core/book_formats/kindle/mobi_header_parser_spec.rb[1:6]","description":"extracts full book name","full_description":"Shoko::Core::BookFormats::Kindle::MobiHeaderParser extracts full book name","status":"passed","file_path":"./spec/core/book_formats/kindle/mobi_header_parser_spec.rb","line_number":111,"run_time":0.000149521,"pending_message":null},{"id":"./spec/core/book_formats/kindle/mobi_header_parser_spec.rb[1:5]","description":"detects DRM","full_description":"Shoko::Core::BookFormats::Kindle::MobiHeaderParser detects DRM","status":"passed","file_path":"./spec/core/book_formats/kindle/mobi_header_parser_spec.rb","line_number":103,"run_time":0.000204764,"pending_message":null},{"id":"./spec/core/book_formats/kindle/mobi_header_parser_spec.rb[1:4]","description":"returns correct encoding name","full_description":"Shoko::Core::BookFormats::Kindle::MobiHeaderParser returns correct encoding name","status":"passed","file_path":"./spec/core/book_formats/kindle/mobi_header_parser_spec.rb","line_number":95,"run_time":0.000309039,"pending_message":null},{"id":"./spec/core/book_formats/kindle/mobi_header_parser_spec.rb[1:1]","description":"parses compression type and text metadata","full_description":"Shoko::Core::BookFormats::Kindle::MobiHeaderParser parses compression type and text metadata","status":"passed","file_path":"./spec/core/book_formats/kindle/mobi_header_parser_spec.rb","line_number":69,"run_time":0.000214913,"pending_message":null},{"id":"./spec/core/book_formats/kindle/mobi_header_parser_spec.rb[1:3]","description":"reports KF8 for version 8","full_description":"Shoko::Core::BookFormats::Kindle::MobiHeaderParser reports KF8 for version 8","status":"passed","file_path":"./spec/core/book_formats/kindle/mobi_header_parser_spec.rb","line_number":87,"run_time":0.000305413,"pending_message":null},{"id":"./spec/core/book_formats/kindle/mobi_header_parser_spec.rb[1:8]","description":"raises on invalid MOBI magic","full_description":"Shoko::Core::BookFormats::Kindle::MobiHeaderParser raises on invalid MOBI magic","status":"passed","file_path":"./spec/core/book_formats/kindle/mobi_header_parser_spec.rb","line_number":127,"run_time":0.000245681,"pending_message":null},{"id":"./spec/core/book_formats/kindle/mobi_header_parser_spec.rb[1:2]","description":"detects EXTH header presence","full_description":"Shoko::Core::BookFormats::Kindle::MobiHeaderParser detects EXTH header presence","status":"passed","file_path":"./spec/core/book_formats/kindle/mobi_header_parser_spec.rb","line_number":79,"run_time":0.000269164,"pending_message":null},{"id":"./spec/adapters/storage/sqlite_dictionary_adapter_spec.rb[1:2:2]","description":"returns false when the database is missing","full_description":"Shoko::Adapters::Storage::SqliteDictionaryAdapter#language_pair_available? returns false when the database is missing","status":"passed","file_path":"./spec/adapters/storage/sqlite_dictionary_adapter_spec.rb","line_number":31,"run_time":0.000214192,"pending_message":null},{"id":"./spec/adapters/storage/sqlite_dictionary_adapter_spec.rb[1:2:1]","description":"returns true when the database exists","full_description":"Shoko::Adapters::Storage::SqliteDictionaryAdapter#language_pair_available? returns true when the database exists","status":"passed","file_path":"./spec/adapters/storage/sqlite_dictionary_adapter_spec.rb","line_number":22,"run_time":0.000211697,"pending_message":null},{"id":"./spec/adapters/storage/sqlite_dictionary_adapter_spec.rb[1:5:1]","description":"raises a typed unavailable error when sqlite3 is unavailable","full_description":"Shoko::Adapters::Storage::SqliteDictionaryAdapter#require_sqlite3! raises a typed unavailable error when sqlite3 is unavailable","status":"passed","file_path":"./spec/adapters/storage/sqlite_dictionary_adapter_spec.rb","line_number":86,"run_time":0.000279304,"pending_message":null},{"id":"./spec/adapters/storage/sqlite_dictionary_adapter_spec.rb[1:4:2]","description":"raises a typed repository error when sqlite encounters a database error","full_description":"Shoko::Adapters::Storage::SqliteDictionaryAdapter#search raises a typed repository error when sqlite encounters a database error","status":"passed","file_path":"./spec/adapters/storage/sqlite_dictionary_adapter_spec.rb","line_number":60,"run_time":0.001025202,"pending_message":null},{"id":"./spec/adapters/storage/sqlite_dictionary_adapter_spec.rb[1:4:1]","description":"returns empty results when database is missing","full_description":"Shoko::Adapters::Storage::SqliteDictionaryAdapter#search returns empty results when database is missing","status":"passed","file_path":"./spec/adapters/storage/sqlite_dictionary_adapter_spec.rb","line_number":50,"run_time":0.000269254,"pending_message":null},{"id":"./spec/adapters/storage/sqlite_dictionary_adapter_spec.rb[1:1:1]","description":"detects language pairs from database files","full_description":"Shoko::Adapters::Storage::SqliteDictionaryAdapter#available_language_pairs detects language pairs from database files","status":"passed","file_path":"./spec/adapters/storage/sqlite_dictionary_adapter_spec.rb","line_number":8,"run_time":0.000338435,"pending_message":null},{"id":"./spec/adapters/storage/sqlite_dictionary_adapter_spec.rb[1:3:1]","description":"normalizes language names to codes","full_description":"Shoko::Adapters::Storage::SqliteDictionaryAdapter#database_path_for normalizes language names to codes","status":"passed","file_path":"./spec/adapters/storage/sqlite_dictionary_adapter_spec.rb","line_number":40,"run_time":0.000150984,"pending_message":null},{"id":"./spec/adapters/input/controllers/sidebar_controller_spec.rb[1:3]","description":"routes TOC keyboard navigation through filtered visible indices","full_description":"Shoko::Adapters::Input::Controllers::SidebarController routes TOC keyboard navigation through filtered visible indices","status":"passed","file_path":"./spec/adapters/input/controllers/sidebar_controller_spec.rb","line_number":106,"run_time":0.00101315,"pending_message":null},{"id":"./spec/adapters/input/controllers/sidebar_controller_spec.rb[1:2]","description":"falls back to chapter jump when no TOC anchor offset is available","full_description":"Shoko::Adapters::Input::Controllers::SidebarController falls back to chapter jump when no TOC anchor offset is available","status":"passed","file_path":"./spec/adapters/input/controllers/sidebar_controller_spec.rb","line_number":95,"run_time":0.000765816,"pending_message":null},{"id":"./spec/adapters/input/controllers/sidebar_controller_spec.rb[1:4]","description":"does not toggle collapse while toc filter is active","full_description":"Shoko::Adapters::Input::Controllers::SidebarController does not toggle collapse while toc filter is active","status":"passed","file_path":"./spec/adapters/input/controllers/sidebar_controller_spec.rb","line_number":123,"run_time":0.000706976,"pending_message":null},{"id":"./spec/adapters/input/controllers/sidebar_controller_spec.rb[1:1]","description":"jumps via chapter offset when TOC anchor resolves","full_description":"Shoko::Adapters::Input::Controllers::SidebarController jumps via chapter offset when TOC anchor resolves","status":"passed","file_path":"./spec/adapters/input/controllers/sidebar_controller_spec.rb","line_number":84,"run_time":0.000731091,"pending_message":null},{"id":"./spec/adapters/input/controllers/sidebar_controller_spec.rb[1:5]","description":"selects visible filtered toc entry instead of hidden raw index","full_description":"Shoko::Adapters::Input::Controllers::SidebarController selects visible filtered toc entry instead of hidden raw index","status":"passed","file_path":"./spec/adapters/input/controllers/sidebar_controller_spec.rb","line_number":139,"run_time":0.001023288,"pending_message":null},{"id":"./spec/application/workflows/menu/dictionary_workflow_spec.rb[1:1]","description":"requires menu_runtime","full_description":"Shoko::Application::Workflows::Menu::DictionaryWorkflow requires menu_runtime","status":"passed","file_path":"./spec/application/workflows/menu/dictionary_workflow_spec.rb","line_number":81,"run_time":0.000555011,"pending_message":null},{"id":"./spec/application/workflows/menu/dictionary_workflow_spec.rb[1:2:1]","description":"uses dictionary_storage.ensure_databases_path as download destination","full_description":"Shoko::Application::Workflows::Menu::DictionaryWorkflow#download_dictionary uses dictionary_storage.ensure_databases_path as download destination","status":"passed","file_path":"./spec/application/workflows/menu/dictionary_workflow_spec.rb","line_number":98,"run_time":0.000716604,"pending_message":null},{"id":"./spec/adapters/ui/components/surface_spec.rb[1:1]","description":"clips text to the bounds width","full_description":"Shoko::Adapters::Ui::Components::Surface clips text to the bounds width","status":"passed","file_path":"./spec/adapters/ui/components/surface_spec.rb","line_number":11,"run_time":0.000124754,"pending_message":null},{"id":"./spec/adapters/ui/components/surface_spec.rb[1:2]","description":"ignores writes outside the bounds","full_description":"Shoko::Adapters::Ui::Components::Surface ignores writes outside the bounds","status":"passed","file_path":"./spec/adapters/ui/components/surface_spec.rb","line_number":17,"run_time":0.000089939,"pending_message":null},{"id":"./spec/adapters/ui/components/surface_spec.rb[1:3]","description":"applies dim styling when requested","full_description":"Shoko::Adapters::Ui::Components::Surface applies dim styling when requested","status":"passed","file_path":"./spec/adapters/ui/components/surface_spec.rb","line_number":23,"run_time":0.000094006,"pending_message":null},{"id":"./spec/adapters/output/terminal/input/mouse_tracking_spec.rb[1:1]","description":"enables and disables any-motion mouse tracking sequences","full_description":"Shoko::Adapters::Output::Terminal::TerminalInput enables and disables any-motion mouse tracking sequences","status":"passed","file_path":"./spec/adapters/output/terminal/input/mouse_tracking_spec.rb","line_number":7,"run_time":0.000096792,"pending_message":null},{"id":"./spec/shared/key_definitions_spec.rb[1:1]","description":"exposes canonical key groups for navigation, actions, reader, and menu","full_description":"Shoko::Shared::KeyDefinitions exposes canonical key groups for navigation, actions, reader, and menu","status":"passed","file_path":"./spec/shared/key_definitions_spec.rb","line_number":6,"run_time":0.000096181,"pending_message":null},{"id":"./spec/core/architecture/no_rescue_literal_default_spec.rb[1:1]","description":"forbids fallback literal defaults directly after rescue branches","full_description":"No rescue literal defaults forbids fallback literal defaults directly after rescue branches","status":"passed","file_path":"./spec/core/architecture/no_rescue_literal_default_spec.rb","line_number":9,"run_time":0.590921919,"pending_message":null},{"id":"./spec/adapters/book_sources/gutendex_client_spec.rb[1:1:3]","description":"raises a helpful error for invalid json","full_description":"Shoko::Adapters::BookSources::GutendexClient#search raises a helpful error for invalid json","status":"passed","file_path":"./spec/adapters/book_sources/gutendex_client_spec.rb","line_number":49,"run_time":0.001146791,"pending_message":null},{"id":"./spec/adapters/book_sources/gutendex_client_spec.rb[1:1:1]","description":"requests the search endpoint with encoded query and parses json","full_description":"Shoko::Adapters::BookSources::GutendexClient#search requests the search endpoint with encoded query and parses json","status":"passed","file_path":"./spec/adapters/book_sources/gutendex_client_spec.rb","line_number":20,"run_time":0.000770675,"pending_message":null},{"id":"./spec/adapters/book_sources/gutendex_client_spec.rb[1:1:2]","description":"follows redirects when searching","full_description":"Shoko::Adapters::BookSources::GutendexClient#search follows redirects when searching","status":"passed","file_path":"./spec/adapters/book_sources/gutendex_client_spec.rb","line_number":38,"run_time":0.002333726,"pending_message":null},{"id":"./spec/adapters/book_sources/gutendex_client_spec.rb[1:2:1]","description":"downloads bytes to disk and reports progress","full_description":"Shoko::Adapters::BookSources::GutendexClient#download downloads bytes to disk and reports progress","status":"passed","file_path":"./spec/adapters/book_sources/gutendex_client_spec.rb","line_number":59,"run_time":0.001026916,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/config_helpers_spec.rb[1:3]","description":"extracts config_reader from context objects","full_description":"Shoko::Adapters::Ui::Components::Reading::ConfigHelpers extracts config_reader from context objects","status":"passed","file_path":"./spec/adapters/ui/components/reading/config_helpers_spec.rb","line_number":22,"run_time":0.000153167,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/config_helpers_spec.rb[1:1]","description":"defaults to highlighting quotes when unset","full_description":"Shoko::Adapters::Ui::Components::Reading::ConfigHelpers defaults to highlighting quotes when unset","status":"passed","file_path":"./spec/adapters/ui/components/reading/config_helpers_spec.rb","line_number":12,"run_time":0.000122309,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/config_helpers_spec.rb[1:2]","description":"defaults to not highlighting keywords when unset","full_description":"Shoko::Adapters::Ui::Components::Reading::ConfigHelpers defaults to not highlighting keywords when unset","status":"passed","file_path":"./spec/adapters/ui/components/reading/config_helpers_spec.rb","line_number":17,"run_time":0.00008043,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/config_helpers_spec.rb[1:4]","description":"returns config_reader directly if it responds to line_spacing","full_description":"Shoko::Adapters::Ui::Components::Reading::ConfigHelpers returns config_reader directly if it responds to line_spacing","status":"passed","file_path":"./spec/adapters/ui/components/reading/config_helpers_spec.rb","line_number":28,"run_time":0.000069451,"pending_message":null},{"id":"./spec/core/events/domain_event_bus_spec.rb[1:2]","description":"notifies subscribers for published event classes","full_description":"Shoko::Core::Events::DomainEventBus notifies subscribers for published event classes","status":"passed","file_path":"./spec/core/events/domain_event_bus_spec.rb","line_number":28,"run_time":0.000524774,"pending_message":null},{"id":"./spec/core/events/domain_event_bus_spec.rb[1:1]","description":"publishes domain events through the EventPublisher port","full_description":"Shoko::Core::Events::DomainEventBus publishes domain events through the EventPublisher port","status":"passed","file_path":"./spec/core/events/domain_event_bus_spec.rb","line_number":19,"run_time":0.000230412,"pending_message":null},{"id":"./spec/core/events/domain_event_bus_spec.rb[1:3]","description":"rejects non-domain-event inputs","full_description":"Shoko::Core::Events::DomainEventBus rejects non-domain-event inputs","status":"passed","file_path":"./spec/core/events/domain_event_bus_spec.rb","line_number":37,"run_time":0.000145613,"pending_message":null},{"id":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb[1:5]","description":"recovers text from escaped JSON-ish payloads instead of rendering raw hashes","full_description":"Shoko::Core::BookFormats::Pdf::PdfContentParser recovers text from escaped JSON-ish payloads instead of rendering raw hashes","status":"passed","file_path":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb","line_number":98,"run_time":0.000241112,"pending_message":null},{"id":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb[1:1]","description":"preserves heading and epigraph semantics from layout payloads","full_description":"Shoko::Core::BookFormats::Pdf::PdfContentParser preserves heading and epigraph semantics from layout payloads","status":"passed","file_path":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb","line_number":17,"run_time":0.000699361,"pending_message":null},{"id":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb[1:4]","description":"parses double-encoded JSON layout payload strings","full_description":"Shoko::Core::BookFormats::Pdf::PdfContentParser parses double-encoded JSON layout payload strings","status":"passed","file_path":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb","line_number":83,"run_time":0.00017618,"pending_message":null},{"id":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb[1:8]","description":"parses multi-line epigraph attributions with mixed-case source titles","full_description":"Shoko::Core::BookFormats::Pdf::PdfContentParser parses multi-line epigraph attributions with mixed-case source titles","status":"passed","file_path":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb","line_number":160,"run_time":0.00040577,"pending_message":null},{"id":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb[1:3]","description":"parses top-level array layout payloads from older PDF caches","full_description":"Shoko::Core::BookFormats::Pdf::PdfContentParser parses top-level array layout payloads from older PDF caches","status":"passed","file_path":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb","line_number":62,"run_time":0.000212698,"pending_message":null},{"id":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb[1:6]","description":"keeps centered attribution signatures out of heading classification","full_description":"Shoko::Core::BookFormats::Pdf::PdfContentParser keeps centered attribution signatures out of heading classification","status":"passed","file_path":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb","line_number":108,"run_time":0.000621455,"pending_message":null},{"id":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb[1:9]","description":"recognizes title-cased author and source attribution signatures","full_description":"Shoko::Core::BookFormats::Pdf::PdfContentParser recognizes title-cased author and source attribution signatures","status":"passed","file_path":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb","line_number":184,"run_time":0.000209713,"pending_message":null},{"id":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb[1:2]","description":"falls back to paragraph parsing for legacy plain text payloads","full_description":"Shoko::Core::BookFormats::Pdf::PdfContentParser falls back to paragraph parsing for legacy plain text payloads","status":"passed","file_path":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb","line_number":51,"run_time":0.000096391,"pending_message":null},{"id":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb[1:7]","description":"does not classify mid-body mixed-italic lines as epigraph blockquotes","full_description":"Shoko::Core::BookFormats::Pdf::PdfContentParser does not classify mid-body mixed-italic lines as epigraph blockquotes","status":"passed","file_path":"./spec/core/book_formats/pdf/pdf_content_parser_spec.rb","line_number":136,"run_time":0.001141331,"pending_message":null},{"id":"./spec/application/workflows/menu/reader_launch/runtime_execution_spec.rb[1:1]","description":"runs reader and restores menu mode on completion","full_description":"Shoko::Application::Workflows::Menu::ReaderLaunch::RuntimeExecution runs reader and restores menu mode on completion","status":"passed","file_path":"./spec/application/workflows/menu/reader_launch/runtime_execution_spec.rb","line_number":43,"run_time":0.000548628,"pending_message":null},{"id":"./spec/core/architecture/no_overlapping_rescue_chains_spec.rb[1:1]","description":"forbids overlapping rescue classes after explicit re-raise in same rescue chain","full_description":"No overlapping rescue chains forbids overlapping rescue classes after explicit re-raise in same rescue chain","status":"passed","file_path":"./spec/core/architecture/no_overlapping_rescue_chains_spec.rb","line_number":9,"run_time":0.038936794,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/annotation_detail_screen_component_spec.rb[1:1]","description":"renders coherent annotation detail layout in dark mode at 80x24","full_description":"Shoko::Adapters::Ui::Components::Screens::AnnotationDetailScreenComponent renders coherent annotation detail layout in dark mode at 80x24","status":"passed","file_path":"./spec/adapters/ui/components/screens/annotation_detail_screen_component_spec.rb","line_number":33,"run_time":0.000922139,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/annotation_detail_screen_component_spec.rb[1:3]","description":"renders coherent annotation detail layout in dark mode at 120x40","full_description":"Shoko::Adapters::Ui::Components::Screens::AnnotationDetailScreenComponent renders coherent annotation detail layout in dark mode at 120x40","status":"passed","file_path":"./spec/adapters/ui/components/screens/annotation_detail_screen_component_spec.rb","line_number":33,"run_time":0.001918668,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/annotation_detail_screen_component_spec.rb[1:2]","description":"renders coherent annotation detail layout in light mode at 80x24","full_description":"Shoko::Adapters::Ui::Components::Screens::AnnotationDetailScreenComponent renders coherent annotation detail layout in light mode at 80x24","status":"passed","file_path":"./spec/adapters/ui/components/screens/annotation_detail_screen_component_spec.rb","line_number":33,"run_time":0.000342172,"pending_message":null},{"id":"./spec/adapters/ui/components/screens/annotation_detail_screen_component_spec.rb[1:4]","description":"renders coherent annotation detail layout in light mode at 120x40","full_description":"Shoko::Adapters::Ui::Components::Screens::AnnotationDetailScreenComponent renders coherent annotation detail layout in light mode at 120x40","status":"passed","file_path":"./spec/adapters/ui/components/screens/annotation_detail_screen_component_spec.rb","line_number":33,"run_time":0.001870147,"pending_message":null},{"id":"./spec/bootstrap/dependencies/bundle_guardrails_spec.rb[1:4]","description":"requires mandatory reader controller dependencies","full_description":"Dependency bundles requires mandatory reader controller dependencies","status":"passed","file_path":"./spec/bootstrap/dependencies/bundle_guardrails_spec.rb","line_number":45,"run_time":0.000220594,"pending_message":null},{"id":"./spec/bootstrap/dependencies/bundle_guardrails_spec.rb[1:7]","description":"exposes reader controller facades for state/workflow/rendering/lifecycle","full_description":"Dependency bundles exposes reader controller facades for state/workflow/rendering/lifecycle","status":"passed","file_path":"./spec/bootstrap/dependencies/bundle_guardrails_spec.rb","line_number":73,"run_time":0.000178896,"pending_message":null},{"id":"./spec/bootstrap/dependencies/bundle_guardrails_spec.rb[1:3]","description":"keeps nested service bundles within the same 16-field budget","full_description":"Dependency bundles keeps nested service bundles within the same 16-field budget","status":"passed","file_path":"./spec/bootstrap/dependencies/bundle_guardrails_spec.rb","line_number":29,"run_time":0.000065222,"pending_message":null},{"id":"./spec/bootstrap/dependencies/bundle_guardrails_spec.rb[1:2]","description":"keeps service bundle roles explicitly segmented","full_description":"Dependency bundles keeps service bundle roles explicitly segmented","status":"passed","file_path":"./spec/bootstrap/dependencies/bundle_guardrails_spec.rb","line_number":22,"run_time":0.000061204,"pending_message":null},{"id":"./spec/bootstrap/dependencies/bundle_guardrails_spec.rb[1:1]","description":"keeps bundle object field counts bounded","full_description":"Dependency bundles keeps bundle object field counts bounded","status":"passed","file_path":"./spec/bootstrap/dependencies/bundle_guardrails_spec.rb","line_number":8,"run_time":0.000084208,"pending_message":null},{"id":"./spec/bootstrap/dependencies/bundle_guardrails_spec.rb[1:5]","description":"requires mandatory menu controller dependencies","full_description":"Dependency bundles requires mandatory menu controller dependencies","status":"passed","file_path":"./spec/bootstrap/dependencies/bundle_guardrails_spec.rb","line_number":50,"run_time":0.000099366,"pending_message":null},{"id":"./spec/bootstrap/dependencies/bundle_guardrails_spec.rb[1:6]","description":"keeps removed runtime bootstrap dependency bundles deleted","full_description":"Dependency bundles keeps removed runtime bootstrap dependency bundles deleted","status":"passed","file_path":"./spec/bootstrap/dependencies/bundle_guardrails_spec.rb","line_number":55,"run_time":0.000079559,"pending_message":null},{"id":"./spec/core/book_formats/metadata_schema_contract_spec.rb[1:1]","description":"enforces canonical parser schema for PDF metadata parser","full_description":"Metadata parser schema contract enforces canonical parser schema for PDF metadata parser","status":"passed","file_path":"./spec/core/book_formats/metadata_schema_contract_spec.rb","line_number":7,"run_time":0.000089938,"pending_message":null},{"id":"./spec/core/book_formats/metadata_schema_contract_spec.rb[1:2]","description":"enforces canonical parser schema for RTF metadata parser","full_description":"Metadata parser schema contract enforces canonical parser schema for RTF metadata parser","status":"passed","file_path":"./spec/core/book_formats/metadata_schema_contract_spec.rb","line_number":18,"run_time":0.000144581,"pending_message":null},{"id":"./spec/core/book_formats/metadata_schema_contract_spec.rb[1:3]","description":"enforces canonical parser schema for FB2 metadata parser","full_description":"Metadata parser schema contract enforces canonical parser schema for FB2 metadata parser","status":"passed","file_path":"./spec/core/book_formats/metadata_schema_contract_spec.rb","line_number":34,"run_time":0.000815229,"pending_message":null},{"id":"./spec/core/book_formats/metadata_schema_contract_spec.rb[1:4]","description":"enforces canonical parser schema for Kindle metadata parser","full_description":"Metadata parser schema contract enforces canonical parser schema for Kindle metadata parser","status":"passed","file_path":"./spec/core/book_formats/metadata_schema_contract_spec.rb","line_number":55,"run_time":0.000190598,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_importer_spec.rb[1:2:1]","description":"splits on closing paragraph tags case-insensitively","full_description":"Shoko::Adapters::BookSources::Kindle::KindleImporter fallback chapter splitting splits on closing paragraph tags case-insensitively","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_importer_spec.rb","line_number":171,"run_time":0.000559469,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_importer_spec.rb[1:1:4:1]","description":"raises FileNotFoundError for missing file","full_description":"Shoko::Adapters::BookSources::Kindle::KindleImporter#import error handling raises FileNotFoundError for missing file","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_importer_spec.rb","line_number":127,"run_time":0.000203272,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_importer_spec.rb[1:1:4:2]","description":"raises BookParseError for invalid file content","full_description":"Shoko::Adapters::BookSources::Kindle::KindleImporter#import error handling raises BookParseError for invalid file content","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_importer_spec.rb","line_number":133,"run_time":0.000366728,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_importer_spec.rb[1:1:5:1]","description":"is registered for .mobi","full_description":"Shoko::Adapters::BookSources::Kindle::KindleImporter#import FormatRegistry integration is registered for .mobi","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_importer_spec.rb","line_number":147,"run_time":0.000098295,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_importer_spec.rb[1:1:5:3]","description":"is registered for .azw3","full_description":"Shoko::Adapters::BookSources::Kindle::KindleImporter#import FormatRegistry integration is registered for .azw3","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_importer_spec.rb","line_number":157,"run_time":0.000070592,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_importer_spec.rb[1:1:5:2]","description":"is registered for .azw","full_description":"Shoko::Adapters::BookSources::Kindle::KindleImporter#import FormatRegistry integration is registered for .azw","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_importer_spec.rb","line_number":152,"run_time":0.000077776,"pending_message":null},{"id":"./spec/core/book_formats/kindle/kindle_importer_spec.rb[1:1:5:4]","description":"reports all three extensions as supported","full_description":"Shoko::Adapters::BookSources::Kindle::KindleImporter#import FormatRegistry integration reports all three extensions as supported","status":"passed","file_path":"./spec/core/book_formats/kindle/kindle_importer_spec.rb","line_number":162,"run_time":0.000073638,"pending_message":null},{"id":"./spec/core/events/base_domain_event_spec.rb[1:2]","description":"stores injected metadata and serializes it","full_description":"Shoko::Core::Events::BaseDomainEvent stores injected metadata and serializes it","status":"passed","file_path":"./spec/core/events/base_domain_event_spec.rb","line_number":17,"run_time":0.000104026,"pending_message":null},{"id":"./spec/core/events/base_domain_event_spec.rb[1:1]","description":"requires injected event metadata","full_description":"Shoko::Core::Events::BaseDomainEvent requires injected event metadata","status":"passed","file_path":"./spec/core/events/base_domain_event_spec.rb","line_number":11,"run_time":0.000151374,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/menu_workflow_bridges_spec.rb[2:1]","description":"reads typed selected annotation from the menu workflow API","full_description":"Shoko::Adapters::Input::Controllers::Menu::AnnotationSelectionBridge reads typed selected annotation from the menu workflow API","status":"passed","file_path":"./spec/adapters/input/controllers/menu/menu_workflow_bridges_spec.rb","line_number":40,"run_time":0.000153779,"pending_message":null},{"id":"./spec/core/book_formats/pdf/pdf_text_extractor_spec.rb[1:2]","description":"tracks italic ratio so mixed inline italics do not force a full italic line","full_description":"Shoko::Core::BookFormats::Pdf::PdfTextExtractor tracks italic ratio so mixed inline italics do not force a full italic line","status":"passed","file_path":"./spec/core/book_formats/pdf/pdf_text_extractor_spec.rb","line_number":108,"run_time":0.000215093,"pending_message":null},{"id":"./spec/core/book_formats/pdf/pdf_text_extractor_spec.rb[1:1]","description":"extracts line layout with x positions and italic font hints","full_description":"Shoko::Core::BookFormats::Pdf::PdfTextExtractor extracts line layout with x positions and italic font hints","status":"passed","file_path":"./spec/core/book_formats/pdf/pdf_text_extractor_spec.rb","line_number":89,"run_time":0.000171171,"pending_message":null},{"id":"./spec/adapters/input/cli_directory_import_spec.rb[1:1]","description":"routes directory args to folder import and exits without launching app when user selects exit","full_description":"Shoko::Adapters::Input::CLI routes directory args to folder import and exits without launching app when user selects exit","status":"passed","file_path":"./spec/adapters/input/cli_directory_import_spec.rb","line_number":49,"run_time":0.000891472,"pending_message":null},{"id":"./spec/adapters/input/cli_directory_import_spec.rb[1:4]","description":"reprompts on invalid action input","full_description":"Shoko::Adapters::Input::CLI reprompts on invalid action input","status":"passed","file_path":"./spec/adapters/input/cli_directory_import_spec.rb","line_number":152,"run_time":0.000673864,"pending_message":null},{"id":"./spec/adapters/input/cli_directory_import_spec.rb[1:3]","description":"imports only the selected file type for action 2 and then opens menu mode","full_description":"Shoko::Adapters::Input::CLI imports only the selected file type for action 2 and then opens menu mode","status":"passed","file_path":"./spec/adapters/input/cli_directory_import_spec.rb","line_number":117,"run_time":0.001321658,"pending_message":null},{"id":"./spec/adapters/input/cli_directory_import_spec.rb[1:2]","description":"imports all documents for action 1 and then opens menu mode","full_description":"Shoko::Adapters::Input::CLI imports all documents for action 1 and then opens menu mode","status":"passed","file_path":"./spec/adapters/input/cli_directory_import_spec.rb","line_number":77,"run_time":0.000856115,"pending_message":null},{"id":"./spec/adapters/input/cli_directory_import_spec.rb[1:5]","description":"keeps file arguments on the reader path and bypasses folder import flow","full_description":"Shoko::Adapters::Input::CLI keeps file arguments on the reader path and bypasses folder import flow","status":"passed","file_path":"./spec/adapters/input/cli_directory_import_spec.rb","line_number":183,"run_time":0.000684343,"pending_message":null},{"id":"./spec/adapters/book_sources/xhtml_content_parser_spec.rb[1:2]","description":"parses tables into table blocks with metadata","full_description":"Shoko::Core::BookFormats::Epub::XHTMLContentParser parses tables into table blocks with metadata","status":"passed","file_path":"./spec/adapters/book_sources/xhtml_content_parser_spec.rb","line_number":18,"run_time":0.001374507,"pending_message":null},{"id":"./spec/adapters/book_sources/xhtml_content_parser_spec.rb[1:1]","description":"parses paragraphs into content blocks with segments","full_description":"Shoko::Core::BookFormats::Epub::XHTMLContentParser parses paragraphs into content blocks with segments","status":"passed","file_path":"./spec/adapters/book_sources/xhtml_content_parser_spec.rb","line_number":6,"run_time":0.001041313,"pending_message":null},{"id":"./spec/adapters/book_sources/xhtml_content_parser_spec.rb[1:5]","description":"preserves underline, strikethrough, superscript, and subscript inline styles","full_description":"Shoko::Core::BookFormats::Epub::XHTMLContentParser preserves underline, strikethrough, superscript, and subscript inline styles","status":"passed","file_path":"./spec/adapters/book_sources/xhtml_content_parser_spec.rb","line_number":89,"run_time":0.00071971,"pending_message":null},{"id":"./spec/adapters/book_sources/xhtml_content_parser_spec.rb[1:4]","description":"attaches anchor ids to block metadata","full_description":"Shoko::Core::BookFormats::Epub::XHTMLContentParser attaches anchor ids to block metadata","status":"passed","file_path":"./spec/adapters/book_sources/xhtml_content_parser_spec.rb","line_number":69,"run_time":0.000942788,"pending_message":null},{"id":"./spec/adapters/book_sources/xhtml_content_parser_spec.rb[1:3]","description":"captures paragraph and table cell alignment","full_description":"Shoko::Core::BookFormats::Epub::XHTMLContentParser captures paragraph and table cell alignment","status":"passed","file_path":"./spec/adapters/book_sources/xhtml_content_parser_spec.rb","line_number":46,"run_time":0.000657012,"pending_message":null},{"id":"./spec/adapters/book_sources/xhtml_content_parser_spec.rb[1:7]","description":"parses tables even when chapter text includes raw code operators that break strict XML","full_description":"Shoko::Core::BookFormats::Epub::XHTMLContentParser parses tables even when chapter text includes raw code operators that break strict XML","status":"passed","file_path":"./spec/adapters/book_sources/xhtml_content_parser_spec.rb","line_number":125,"run_time":0.001209979,"pending_message":null},{"id":"./spec/adapters/book_sources/xhtml_content_parser_spec.rb[1:6]","description":"maps vertical-align styles to superscript/subscript segments","full_description":"Shoko::Core::BookFormats::Epub::XHTMLContentParser maps vertical-align styles to superscript/subscript segments","status":"passed","file_path":"./spec/adapters/book_sources/xhtml_content_parser_spec.rb","line_number":108,"run_time":0.00052253,"pending_message":null},{"id":"./spec/core/ports/render_state_writer_spec.rb[1:1:2]","description":"defines #update_rendered_lines","full_description":"Shoko::Core::Ports::Outbound::RenderStateWriter port interface defines #update_rendered_lines","status":"passed","file_path":"./spec/core/ports/render_state_writer_spec.rb","line_number":17,"run_time":0.000118101,"pending_message":null},{"id":"./spec/core/ports/render_state_writer_spec.rb[1:1:1]","description":"defines #clear_rendered_lines","full_description":"Shoko::Core::Ports::Outbound::RenderStateWriter port interface defines #clear_rendered_lines","status":"passed","file_path":"./spec/core/ports/render_state_writer_spec.rb","line_number":13,"run_time":0.000249558,"pending_message":null},{"id":"./spec/adapters/input/controllers/mouseable_reader_spec.rb[1:2:1]","description":"does not trap 'q' behind a stale mouse prefix buffer","full_description":"Shoko::Adapters::Input::Controllers::MouseableReader#filter_mouse_sequences does not trap 'q' behind a stale mouse prefix buffer","status":"passed","file_path":"./spec/adapters/input/controllers/mouseable_reader_spec.rb","line_number":29,"run_time":0.000098996,"pending_message":null},{"id":"./spec/adapters/input/controllers/mouseable_reader_spec.rb[1:3:2]","description":"consumes the first release after context popup open","full_description":"Shoko::Adapters::Input::Controllers::MouseableReader#handle_overlay_click consumes the first release after context popup open","status":"passed","file_path":"./spec/adapters/input/controllers/mouseable_reader_spec.rb","line_number":49,"run_time":0.000302617,"pending_message":null},{"id":"./spec/adapters/input/controllers/mouseable_reader_spec.rb[1:3:1]","description":"handles popup context trigger on mouse press events before release gate","full_description":"Shoko::Adapters::Input::Controllers::MouseableReader#handle_overlay_click handles popup context trigger on mouse press events before release gate","status":"passed","file_path":"./spec/adapters/input/controllers/mouseable_reader_spec.rb","line_number":41,"run_time":0.000262582,"pending_message":null},{"id":"./spec/adapters/input/controllers/mouseable_reader_spec.rb[1:1:2]","description":"drops escape after mouse tokens","full_description":"Shoko::Adapters::Input::Controllers::MouseableReader#spurious_post_mouse_key? drops escape after mouse tokens","status":"passed","file_path":"./spec/adapters/input/controllers/mouseable_reader_spec.rb","line_number":15,"run_time":0.000059301,"pending_message":null},{"id":"./spec/adapters/input/controllers/mouseable_reader_spec.rb[1:1:1]","description":"does not drop 'q' after mouse tokens","full_description":"Shoko::Adapters::Input::Controllers::MouseableReader#spurious_post_mouse_key? does not drop 'q' after mouse tokens","status":"passed","file_path":"./spec/adapters/input/controllers/mouseable_reader_spec.rb","line_number":9,"run_time":0.000075511,"pending_message":null},{"id":"./spec/application/use_cases/command_bus_gateway_registry_spec.rb[1:6]","description":"returns :error and logs command.invalid_payload for payload conversion errors","full_description":"Command bus intent registry returns :error and logs command.invalid_payload for payload conversion errors","status":"passed","file_path":"./spec/application/use_cases/command_bus_gateway_registry_spec.rb","line_number":245,"run_time":0.000246342,"pending_message":null},{"id":"./spec/application/use_cases/command_bus_gateway_registry_spec.rb[1:3]","description":"builds explicit command objects for reader/menu intent symbols","full_description":"Command bus intent registry builds explicit command objects for reader/menu intent symbols","status":"passed","file_path":"./spec/application/use_cases/command_bus_gateway_registry_spec.rb","line_number":185,"run_time":0.000828694,"pending_message":null},{"id":"./spec/application/use_cases/command_bus_gateway_registry_spec.rb[1:2]","description":"keeps reader and menu symbol snapshots stable","full_description":"Command bus intent registry keeps reader and menu symbol snapshots stable","status":"passed","file_path":"./spec/application/use_cases/command_bus_gateway_registry_spec.rb","line_number":64,"run_time":0.000350267,"pending_message":null},{"id":"./spec/application/use_cases/command_bus_gateway_registry_spec.rb[1:1]","description":"covers every reader/menu bound symbol in command bus registry","full_description":"Command bus intent registry covers every reader/menu bound symbol in command bus registry","status":"passed","file_path":"./spec/application/use_cases/command_bus_gateway_registry_spec.rb","line_number":57,"run_time":0.000318948,"pending_message":null},{"id":"./spec/application/use_cases/command_bus_gateway_registry_spec.rb[1:4]","description":"routes shared symbols through explicit shared intent symbols","full_description":"Command bus intent registry routes shared symbols through explicit shared intent symbols","status":"passed","file_path":"./spec/application/use_cases/command_bus_gateway_registry_spec.rb","line_number":209,"run_time":0.000081413,"pending_message":null},{"id":"./spec/application/use_cases/command_bus_gateway_registry_spec.rb[1:5]","description":"returns :error and logs command.unknown for unknown symbols","full_description":"Command bus intent registry returns :error and logs command.unknown for unknown symbols","status":"passed","file_path":"./spec/application/use_cases/command_bus_gateway_registry_spec.rb","line_number":218,"run_time":0.000144171,"pending_message":null},{"id":"./spec/application/use_cases/command_bus_gateway_registry_spec.rb[1:7]","description":"returns :error and logs command.contract_mismatch when context violates intent contract","full_description":"Command bus intent registry returns :error and logs command.contract_mismatch when context violates intent contract","status":"passed","file_path":"./spec/application/use_cases/command_bus_gateway_registry_spec.rb","line_number":278,"run_time":0.000153308,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/reader_launch_bridges_spec.rb[1:1]","description":"reads selected book from explicit menu workflow API","full_description":"Shoko::Adapters::Input::Controllers::Menu::ReaderLaunchBookSelectionBridge reads selected book from explicit menu workflow API","status":"passed","file_path":"./spec/adapters/input/controllers/menu/reader_launch_bridges_spec.rb","line_number":16,"run_time":0.000123952,"pending_message":null},{"id":"./spec/adapters/input/controllers/menu/reader_launch_bridges_spec.rb[1:2]","description":"reads filtered books from explicit menu workflow API","full_description":"Shoko::Adapters::Input::Controllers::Menu::ReaderLaunchBookSelectionBridge reads filtered books from explicit menu workflow API","status":"passed","file_path":"./spec/adapters/input/controllers/menu/reader_launch_bridges_spec.rb","line_number":23,"run_time":0.00011727,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/line_geometry_builder_spec.rb[1:1]","description":"builds geometry with cell metadata","full_description":"Shoko::Adapters::Ui::Components::Reading::LineGeometryBuilder builds geometry with cell metadata","status":"passed","file_path":"./spec/adapters/ui/components/reading/line_geometry_builder_spec.rb","line_number":22,"run_time":0.00022942,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/line_geometry_builder_spec.rb[1:2]","description":"reuses cached cell arrays when cell cache is enabled","full_description":"Shoko::Adapters::Ui::Components::Reading::LineGeometryBuilder reuses cached cell arrays when cell cache is enabled","status":"passed","file_path":"./spec/adapters/ui/components/reading/line_geometry_builder_spec.rb","line_number":30,"run_time":0.000138349,"pending_message":null},{"id":"./spec/adapters/ui/components/reading/line_geometry_builder_spec.rb[1:3]","description":"builds new cell arrays when cell cache is disabled","full_description":"Shoko::Adapters::Ui::Components::Reading::LineGeometryBuilder builds new cell arrays when cell cache is disabled","status":"passed","file_path":"./spec/adapters/ui/components/reading/line_geometry_builder_spec.rb","line_number":39,"run_time":0.000186169,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb[1:11:1]","description":"includes focused reader state ports","full_description":"Shoko::Adapters::Runtime::SessionState::ReaderStateReaderAdapter port compliance includes focused reader state ports","status":"passed","file_path":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb","line_number":95,"run_time":0.000155321,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb[1:7:1]","description":"reads from state","full_description":"Shoko::Adapters::Runtime::SessionState::ReaderStateReaderAdapter#current_page reads from state","status":"passed","file_path":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb","line_number":66,"run_time":0.000186039,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb[1:2:1]","description":"reads from state","full_description":"Shoko::Adapters::Runtime::SessionState::ReaderStateReaderAdapter#total_chapters reads from state","status":"passed","file_path":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb","line_number":26,"run_time":0.000144881,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb[1:2:2]","description":"returns 0 when nil","full_description":"Shoko::Adapters::Runtime::SessionState::ReaderStateReaderAdapter#total_chapters returns 0 when nil","status":"passed","file_path":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb","line_number":31,"run_time":0.000138189,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb[1:10:1]","description":"delegates to ReaderSelectors","full_description":"Shoko::Adapters::Runtime::SessionState::ReaderStateReaderAdapter#bookmarks delegates to ReaderSelectors","status":"passed","file_path":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb","line_number":87,"run_time":0.000206227,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb[1:6:1]","description":"delegates to ReaderSelectors","full_description":"Shoko::Adapters::Runtime::SessionState::ReaderStateReaderAdapter#single_page delegates to ReaderSelectors","status":"passed","file_path":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb","line_number":59,"run_time":0.000168395,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb[1:3:1]","description":"delegates to ReaderSelectors","full_description":"Shoko::Adapters::Runtime::SessionState::ReaderStateReaderAdapter#current_page_index delegates to ReaderSelectors","status":"passed","file_path":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb","line_number":38,"run_time":0.0002135,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb[1:5:1]","description":"delegates to ReaderSelectors","full_description":"Shoko::Adapters::Runtime::SessionState::ReaderStateReaderAdapter#right_page delegates to ReaderSelectors","status":"passed","file_path":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb","line_number":52,"run_time":0.000163166,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb[1:4:1]","description":"delegates to ReaderSelectors","full_description":"Shoko::Adapters::Runtime::SessionState::ReaderStateReaderAdapter#left_page delegates to ReaderSelectors","status":"passed","file_path":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb","line_number":45,"run_time":0.00018106,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb[1:9:1]","description":"reads from state","full_description":"Shoko::Adapters::Runtime::SessionState::ReaderStateReaderAdapter#book_path reads from state","status":"passed","file_path":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb","line_number":80,"run_time":0.000139923,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb[1:1:1]","description":"delegates to ReaderSelectors","full_description":"Shoko::Adapters::Runtime::SessionState::ReaderStateReaderAdapter#current_chapter delegates to ReaderSelectors","status":"passed","file_path":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb","line_number":14,"run_time":0.000161373,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb[1:1:2]","description":"returns 0 when nil","full_description":"Shoko::Adapters::Runtime::SessionState::ReaderStateReaderAdapter#current_chapter returns 0 when nil","status":"passed","file_path":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb","line_number":19,"run_time":0.000157685,"pending_message":null},{"id":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb[1:8:1]","description":"delegates to ReaderSelectors","full_description":"Shoko::Adapters::Runtime::SessionState::ReaderStateReaderAdapter#page_map delegates to ReaderSelectors","status":"passed","file_path":"./spec/adapters/runtime/session_state/reader_state_reader_adapter_spec.rb","line_number":73,"run_time":0.000180309,"pending_message":null}],"summary":{"duration":7.534192975,"example_count":973,"failure_count":0,"pending_count":0,"errors_outside_of_examples_count":0},"summary_line":"973 examples, 0 failures"}
|