Unofficial Python API and agentic skill for Google Gemini Notebook. Full programmatic access to NotebookLM's features—including capabilities the web UI doesn't expose—via Python, CLI, and AI agents like Claude Code, Codex, and OpenClaw.
This report presents the forensic synthetic code analysis of teng-lin/notebooklm-py, a Python project with 18,987 GitHub stars. SynthScan v2.0 examined 747,603 lines of code across 1390 source files, recording 17763 pattern matches distributed across 21 syntactic categories. The overall adjusted score of 32.6 places this repository in the Strong AI signal band.
The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).
This chart maps the temporal evolution of the adjusted synthetic code score across successive scan runs. An upward trajectory indicates ongoing incorporation of AI-generated code or expanding LLM-assisted scaffolding; a stable or declining trajectory may reflect active human refactoring, code removal, or the adoption of stricter authorship policies. The dashed secondary line (right axis) independently tracks total raw pattern hit count, which can diverge from the normalised score when codebase size changes significantly between scans.
Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.
This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.
The scanner identified 17763 distinct pattern matches across 21 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/conftest.py | 353 | def pytest_collection_modifyitems(config, items): | CODE |
| LOW | tests/conftest.py | 515 | def mock_list_notebooks_response(): | STRING |
| LOW | tests/conftest.py | 635 | def legacy_vcr_follow_up_probe(monkeypatch): | STRING |
| LOW | tests/conftest.py | 646 | async def _count_prior_server_turns( | STRING |
| LOW | tests/conftest.py | 658 | def legacy_vcr_add_url_baseline(monkeypatch): | CODE |
| LOW | tests/cassette_patterns.py | 1579 | def synthetic_error_cassette_name(mode: str, slug: str) -> str: | CODE |
| LOW | tests/cassette_patterns.py | 1596 | def build_synthetic_error_response( | CODE |
| LOW | tests/vcr_config.py | 181 | def _substitute_synthetic_error(response: dict[str, Any]) -> dict[str, Any]: | CODE |
| LOW | tests/vcr_config.py | 502 | def _is_create_artifact_client_options(node: Any) -> bool: | CODE |
| LOW | tests/vcr_config.py | 518 | def _normalize_create_artifact_options(decoded_outer: Any) -> Any: | CODE |
| LOW | tests/_helpers/client_factory.py | 29 | def build_client_shell_for_tests( | CODE |
| LOW⚡ | tests/unit/test_artifacts_helpers.py | 30 | def test_extract_data_table_rows_happy_path() -> None: | CODE |
| LOW⚡ | tests/unit/test_artifacts_helpers.py | 51 | def test_extract_data_table_rows_missing_inner_list() -> None: | CODE |
| LOW⚡ | tests/unit/test_artifacts_helpers.py | 61 | def test_extract_data_table_rows_wrong_type_at_one_level() -> None: | CODE |
| LOW⚡ | tests/unit/test_artifacts_helpers.py | 70 | def test_extract_data_table_rows_truncated_structure() -> None: | CODE |
| LOW⚡ | tests/unit/test_artifacts_helpers.py | 83 | def test_extract_data_table_rows_non_list_inner_value( | CODE |
| LOW⚡ | tests/unit/test_artifacts_helpers.py | 105 | def test_parse_data_table_raises_artifact_parse_error_on_drift() -> None: | CODE |
| LOW | tests/unit/test_artifacts_helpers.py | 118 | def test_parse_data_table_raises_on_empty_rows() -> None: | CODE |
| LOW | tests/unit/test_artifacts_helpers.py | 126 | def test_parse_data_table_happy_path() -> None: | CODE |
| LOW | tests/unit/test_artifacts_helpers.py | 154 | def test_parse_data_table_skips_malformed_row_sections() -> None: | CODE |
| LOW⚡ | tests/unit/test_json_stdout_purity.py | 1238 | def test_matched_partial_id_goes_to_stderr_in_json_mode(runner: CliRunner, mock_auth_env) -> None: | CODE |
| LOW | tests/unit/test_json_stdout_purity.py | 228 | async def wait_for_research_completion( | CODE |
| LOW | tests/unit/test_json_stdout_purity.py | 326 | def _customize_suggest_prompts(client: MagicMock) -> None: | CODE |
| LOW | tests/unit/test_json_stdout_purity.py | 339 | def _customize_share_view_level(client: MagicMock) -> None: | CODE |
| LOW | tests/unit/test_json_stdout_purity.py | 343 | def _customize_source_fulltext(client: MagicMock) -> None: | CODE |
| LOW | tests/unit/test_json_stdout_purity.py | 365 | def _customize_source_add_research(client: MagicMock) -> None: | CODE |
| LOW | tests/unit/test_json_stdout_purity.py | 401 | def _customize_research_import(client: MagicMock) -> None: | CODE |
| LOW | tests/unit/test_json_stdout_purity.py | 427 | def _customize_research_cancel(client: MagicMock) -> None: | CODE |
| LOW | tests/unit/test_json_stdout_purity.py | 433 | def _customize_notebook_create(client: MagicMock) -> None: | CODE |
| LOW | tests/unit/test_json_stdout_purity.py | 734 | def test_json_mode_stdout_is_parseable( | CODE |
| LOW | tests/unit/test_json_stdout_purity.py | 1138 | def test_all_json_commands_have_sweep_entry() -> None: | CODE |
| LOW | tests/unit/test_json_stdout_purity.py | 1257 | def test_matched_partial_id_still_goes_to_stdout_in_human_mode( | CODE |
| LOW | tests/unit/test_client_keepalive.py | 61 | async def _read_storage_text_when_available(storage_path): | CODE |
| LOW | tests/unit/test_client_keepalive.py | 71 | async def _wait_until_storage_contains(storage_path, needle: str, failure_message: str) -> None: | CODE |
| LOW | tests/unit/test_client_keepalive.py | 83 | async def _wait_for_rotate_requests( | CODE |
| LOW | tests/unit/test_client_keepalive.py | 104 | async def test_keepalive_off_by_default(self, mock_auth, httpx_mock: HTTPXMock): | CODE |
| LOW | tests/unit/test_client_keepalive.py | 120 | async def test_spawns_task_on_enter_cancels_on_exit(self, mock_auth, httpx_mock: HTTPXMock): | CODE |
| LOW | tests/unit/test_client_keepalive.py | 148 | async def test_floor_clamps_low_interval(self, mock_auth): | CODE |
| LOW | tests/unit/test_client_keepalive.py | 158 | async def test_floor_does_not_lower_higher_interval(self, mock_auth): | CODE |
| LOW | tests/unit/test_client_keepalive.py | 180 | def test_rejects_non_positive_or_non_finite_keepalive(self, mock_auth, bad): | CODE |
| LOW | tests/unit/test_client_keepalive.py | 186 | def test_rejects_non_positive_or_non_finite_floor(self, mock_auth, bad): | CODE |
| LOW | tests/unit/test_client_keepalive.py | 227 | async def test_failure_does_not_crash_loop(self, mock_auth, httpx_mock: HTTPXMock, monkeypatch): | CODE |
| LOW | tests/unit/test_client_keepalive.py | 273 | async def test_persistence_failure_logs_warning_and_continues( | CODE |
| LOW | tests/unit/test_client_keepalive.py | 321 | async def test_explicit_storage_path_used_when_auth_lacks_one( | CODE |
| LOW | tests/unit/test_client_keepalive.py | 380 | def test_explicit_storage_path_normalizes_onto_auth_without_mutating_caller(self, tmp_path): | CODE |
| LOW | tests/unit/test_client_keepalive.py | 412 | async def test_close_persists_to_explicit_storage_path(self, tmp_path, httpx_mock: HTTPXMock): | CODE |
| LOW | tests/unit/test_client_keepalive.py | 448 | async def test_persists_rotated_cookies_without_aexit(self, tmp_path, httpx_mock: HTTPXMock): | CODE |
| LOW | tests/unit/test_client_keepalive.py | 491 | async def test_save_cookies_takes_in_process_lock_before_writing(self, tmp_path): | CODE |
| LOW | tests/unit/test_client_keepalive.py | 542 | async def test_refresh_auth_routes_save_through_save_cookies( | CODE |
| LOW | tests/unit/test_client_keepalive.py | 626 | def test_save_cookies_to_storage_acquires_file_lock(self, tmp_path, monkeypatch): | CODE |
| LOW | tests/unit/test_client_keepalive.py | 668 | def test_save_cookies_to_storage_creates_lock_sentinel(self, tmp_path): | CODE |
| LOW | tests/unit/test_drain_tracker_hooks.py | 26 | async def test_run_drain_hooks_fires_in_registration_order() -> None: | CODE |
| LOW | tests/unit/test_drain_tracker_hooks.py | 54 | async def test_run_drain_hooks_continues_when_one_hook_raises(caplog) -> None: | CODE |
| LOW | tests/unit/test_drain_tracker_hooks.py | 93 | async def test_run_drain_hooks_is_noop_when_none_registered() -> None: | CODE |
| LOW | tests/unit/test_drain_tracker_hooks.py | 101 | async def test_register_drain_hook_overwrites_same_name() -> None: | CODE |
| LOW⚡ | tests/unit/test_chat_characterization.py | 1971 | def test_parse_single_citation_returns_none_when_not_list(self, auth_tokens): | CODE |
| LOW⚡ | tests/unit/test_chat_characterization.py | 1977 | def test_parse_single_citation_returns_none_when_too_short(self, auth_tokens): | CODE |
| LOW⚡ | tests/unit/test_chat_characterization.py | 1983 | def test_parse_single_citation_returns_none_when_cite_inner_not_list(self, auth_tokens): | CODE |
| LOW⚡ | tests/unit/test_chat_characterization.py | 1989 | def test_parse_single_citation_returns_none_when_no_source_id(self, auth_tokens): | CODE |
| LOW⚡ | tests/unit/test_chat_characterization.py | 2139 | def test_max_depth_zero_returns_none_with_warning(self, auth_tokens): | CODE |
| 11617 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | tests/cassette_patterns.py | 721 | # ============================================================================= | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 723 | # ============================================================================= | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 730 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 732 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 757 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 759 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 766 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 768 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 776 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 778 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 785 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 787 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 862 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 864 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 874 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 876 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 894 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 896 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 901 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 903 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 1230 | # ============================================================================= | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 1232 | # ============================================================================= | COMMENT |
| MEDIUM⚡ | tests/cassette_patterns.py | 1235 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 132 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 134 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 250 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 252 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 303 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 305 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 319 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 321 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 363 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 365 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 411 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 413 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 518 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 520 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 801 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 803 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 828 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 830 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 843 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 845 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 916 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 918 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 940 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 942 | # ------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 955 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 957 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 1546 | # ============================================================================= | COMMENT |
| MEDIUM | tests/cassette_patterns.py | 1548 | # ============================================================================= | COMMENT |
| MEDIUM | tests/vcr_config.py | 319 | # ============================================================================= | COMMENT |
| MEDIUM | tests/vcr_config.py | 321 | # ============================================================================= | COMMENT |
| MEDIUM | tests/vcr_config.py | 761 | # ============================================================================= | COMMENT |
| MEDIUM | tests/vcr_config.py | 763 | # ============================================================================= | COMMENT |
| MEDIUM⚡ | tests/unit/test_artifacts_helpers.py | 25 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/unit/test_artifacts_helpers.py | 27 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/unit/test_artifacts_helpers.py | 46 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/unit/test_artifacts_helpers.py | 48 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/unit/test_artifacts_helpers.py | 78 | # --------------------------------------------------------------------------- | COMMENT |
| 2488 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | hatch_build.py | 21 | CODE | |
| LOW | desktop-extension/run_server.py | 24 | CODE | |
| LOW | tests/cassette_patterns.py | 126 | CODE | |
| LOW | tests/_helpers/client_factory.py | 3 | CODE | |
| LOW | tests/unit/test_artifacts_helpers.py | 12 | CODE | |
| LOW | tests/unit/test_json_stdout_purity.py | 19 | CODE | |
| LOW | tests/unit/test_drain_tracker_hooks.py | 18 | CODE | |
| LOW | tests/unit/test_refresh_lock_registry.py | 20 | CODE | |
| LOW | tests/unit/test_from_storage_dual_protocol.py | 18 | CODE | |
| LOW | tests/unit/test_curl_cffi_transport_poc.py | 14 | CODE | |
| LOW | tests/unit/test_firefox_containers.py | 12 | CODE | |
| LOW | tests/unit/test_storage_writer.py | 12 | CODE | |
| LOW | tests/unit/test_vcr_scrubbing.py | 30 | CODE | |
| LOW | tests/unit/test_auth_refresh_profile_store.py | 3 | CODE | |
| LOW | tests/unit/test_collection_exceptions.py | 3 | CODE | |
| LOW | tests/unit/test_auth_instance_invariant.py | 3 | CODE | |
| LOW | tests/unit/test_collections_api.py | 3 | CODE | |
| LOW | tests/unit/test_auth_session_master_token.py | 3 | CODE | |
| LOW | tests/unit/test_vcr_config.py | 20 | CODE | |
| LOW | tests/unit/test_source_upload_coverage.py | 10 | CODE | |
| LOW | tests/unit/test_auth_master_token.py | 7 | CODE | |
| LOW | tests/unit/test_tier_enforcement_hook.py | 39 | CODE | |
| LOW | tests/unit/test_auth_refresh_retry.py | 12 | CODE | |
| LOW | tests/unit/test_deploy_compose_default.py | 10 | CODE | |
| LOW | tests/unit/test_auth_lock_path_derivation.py | 28 | CODE | |
| LOW | tests/unit/test_live_auth_matrix.py | 15 | CODE | |
| LOW | tests/unit/test_serving.py | 9 | CODE | |
| LOW | tests/unit/test_streaming_chat_wire.py | 3 | CODE | |
| LOW | tests/unit/test_streaming_chat_wire.py | 1010 | CODE | |
| LOW | tests/unit/test_get_or_none.py | 15 | CODE | |
| LOW | tests/unit/test_audit_auth_import_graph.py | 3 | CODE | |
| LOW | tests/unit/test_browser_capture_cdp_arm.py | 25 | CODE | |
| LOW | tests/unit/test_concurrency_refresh_race.py | 60 | CODE | |
| LOW | tests/unit/test_middleware_chain_host.py | 28 | CODE | |
| LOW | tests/unit/test_auth_cold_start_recovery.py | 3 | CODE | |
| LOW | tests/unit/test_capture_rpc_registry.py | 8 | CODE | |
| LOW | tests/unit/test_generation_state.py | 15 | CODE | |
| LOW | tests/unit/test_research_row_adapter.py | 15 | CODE | |
| LOW | tests/unit/test_auth_credential_io.py | 3 | CODE | |
| LOW | tests/unit/test_with_client_handle_errors.py | 20 | CODE | |
| LOW | tests/unit/test_logging.py | 3 | CODE | |
| LOW | tests/unit/test_label_exceptions.py | 3 | CODE | |
| LOW | tests/unit/test_check_rpc_health.py | 23 | CODE | |
| LOW | tests/unit/test_auth_headless_reauth.py | 16 | CODE | |
| LOW | tests/unit/test_public_api_behavior.py | 40 | CODE | |
| LOW | tests/unit/test_refresh_state_machine.py | 14 | CODE | |
| LOW | tests/unit/test_download_redirect_revalidation.py | 25 | CODE | |
| LOW | tests/unit/test_timeout_composition.py | 23 | CODE | |
| LOW | tests/unit/test_logging_correlation.py | 3 | CODE | |
| LOW | tests/unit/test_auth_profile_store_minted.py | 3 | CODE | |
| LOW | tests/unit/test_download_result.py | 3 | CODE | |
| LOW | tests/unit/test_auth_master_token_file.py | 3 | CODE | |
| LOW | tests/unit/test_chat_passage_resolver.py | 16 | CODE | |
| LOW | tests/unit/test_auth_session_headless_reauth.py | 19 | CODE | |
| LOW | tests/unit/test_chat_helpers.py | 11 | CODE | |
| LOW | tests/unit/test_auth_psidts_recovery.py | 12 | CODE | |
| LOW | tests/unit/test_tracked_files.py | 3 | CODE | |
| LOW | tests/unit/test_idempotent_create_contract.py | 3 | CODE | |
| LOW | tests/unit/test_mind_maps_api.py | 3 | CODE | |
| LOW | tests/unit/test_error_injection_middleware.py | 41 | CODE | |
| 1820 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | tests/vcr_config.py | 572 | 1. **Streaming-chat envelope** ``[null, "<inner_json>"]`` where the inner | STRING |
| HIGH | tests/vcr_config.py | 578 | 2. **Batchexecute envelope** ``[[[rpc_id, args_json, null, "generic"]]]`` | STRING |
| HIGH | tests/vcr_config.py | 647 | # Streaming-chat envelope: [null, "<inner_json>"]. | COMMENT |
| HIGH | tests/unit/test_vcr_config.py | 84 | JSON envelope is ``[null, "<inner_json>"]`` and ``<inner_json>`` is itself a | STRING |
| HIGH⚡ | tests/unit/test_check_rpc_health.py | 928 | body = ')]}\'\n\n[["wrb.fr","sqTeoe","null",null,null,null,"generic"]]' | CODE |
| HIGH⚡ | tests/unit/test_check_rpc_health.py | 942 | body = ')]}\'\n\n[["wrb.fr","sqTeoe","[[1,2,3]]",null,null,null,"generic"]]' | CODE |
| HIGH⚡ | tests/unit/test_decoder.py | 1286 | payload = f'[["wrb.fr","{self.RPC_ID}",null,null,null,{deep}]]' | CODE |
| HIGH⚡ | tests/unit/test_decoder.py | 1294 | payload = f'[["wrb.fr","{self.RPC_ID}",null,null,null,{deep}]]' | CODE |
| HIGH | tests/unit/test_decoder.py | 893 | """``[5, null, 'x']`` is the same google.rpc.Status at a longer arity. | STRING |
| HIGH⚡ | tests/unit/test_sources_row_adapter.py | 854 | # 402x [null, 2] — no Drive-status slot | COMMENT |
| HIGH⚡ | tests/unit/test_sources_row_adapter.py | 855 | # 4x [null, 2, null, 3] — Drive-backed, ACTIVE | COMMENT |
| HIGH⚡ | tests/unit/test_sources_row_adapter.py | 856 | # 3x [null, 2, [null,null,null,[]]] — a populated settings[2], no [3] | COMMENT |
| HIGH⚡ | tests/unit/test_sources_row_adapter.py | 684 | """A live-shaped web-page row (``metadata[0]`` null, URL at ``[7]``) yields None. | STRING |
| HIGH⚡ | tests/unit/test_sources_row_adapter.py | 871 | """settings ``[null, 2, null, 3]`` — the only populated shape seen live.""" | STRING |
| HIGH⚡ | tests/unit/test_sources_row_adapter.py | 879 | """settings ``[null, 2]`` — 402 of 409 live rows. No Drive claim at all.""" | STRING |
| HIGH⚡ | tests/unit/test_sources_row_adapter.py | 886 | """settings ``[null, 2, [null,null,null,[]]]`` — 3 of 409 live rows. | STRING |
| HIGH⚡ | tests/unit/test_collection_params.py | 93 | # Owner capture: [ [null,null,null,[[nbid]]], [] ] with the type-3 tail. | COMMENT |
| HIGH | tests/unit/test_api_coverage.py | 150 | # Real API returns 3 levels of nesting: [[[null, [summary], [[keywords]], []]]] | COMMENT |
| HIGH | tests/unit/test_api_coverage.py | 187 | # Response format: [[[title, description, null, null, prompt, audience_level], ...]] | COMMENT |
| HIGH⚡ | tests/unit/test_api_coverage.py | 314 | # Verify reference payload: [null, ["source_id"], [2]] | COMMENT |
| HIGH⚡ | tests/unit/test_api_coverage.py | 330 | # Verify reference payload: [null, ["source_id"], [2]] | COMMENT |
| HIGH | tests/unit/test_authed_post_pipeline.py | 1598 | decoded_payload = b')]}\'\n\n[["wrb.fr",null,"[1]",null,null,null,"generic"]]' | CODE |
| HIGH | tests/unit/test_select_artifact.py | 277 | ever emits ``[null, ...]`` at index 15 the sort must coerce that | STRING |
| HIGH | tests/unit/test_auth_cookie_save_race.py | 1031 | f"None-valued cookie must never be persisted as value:null, got: {stored}" | CODE |
| HIGH | tests/unit/test_save_chat_as_note_encoder.py | 136 | # passage[3] = [[null, start, end]]; passage[5] = [[[passage_id], source_id]]; | COMMENT |
| HIGH | tests/unit/test_save_chat_as_note_encoder.py | 232 | assert "[0,0,0,null,null,null,null,0,0]" in actual_json | CODE |
| HIGH⚡ | tests/unit/test_user_settings_api.py | 145 | # GET_USER_SETTINGS inner: [[null,[..limits..],[true,null,null,true,["fr"]], | COMMENT |
| HIGH⚡ | tests/unit/test_user_settings_api.py | 147 | # SET_USER_SETTINGS inner: [null,[..limits..],[true,null,null,true,["en"]], | COMMENT |
| HIGH | tests/unit/test_rate_limit_retry.py | 47 | resp.text = ")]}'\n[null,[" + str(payload).replace("'", '"') + "]]" | CODE |
| HIGH | tests/unit/test_rescrub_cassettes_script.py | 89 | f'[["wrb.fr","JFMDGd","[[null,[\\"{avatar_url}\\"]]]",null,null,null,"generic"]]' | CODE |
| HIGH | tests/unit/test_scrub_rpc_har.py | 59 | freq = json.dumps([[["CCqFvf", '["t",null,null,[2],[1]]', None, "generic"]]]) | CODE |
| HIGH | tests/unit/test_scrub_rpc_har.py | 146 | freq = json.dumps([[["CCqFvf", '["t",null,null,[2],[1]]', None, "generic"]]]) | CODE |
| HIGH⚡ | tests/unit/test_rpc_overrides.py | 181 | '{"LIST_NOTEBOOKS": null, "CREATE_NOTEBOOK": "valid"}', | CODE |
| HIGH⚡ | tests/unit/test_vcr_body_matcher.py | 117 | """Build a streaming-chat ``f.req`` form body (`[null, "<inner_json>"]`).""" | STRING |
| HIGH⚡ | tests/unit/test_vcr_body_matcher.py | 208 | fixtures: the cassette has a trailing ``[null, null]`` while the live | STRING |
| HIGH | tests/unit/test_vcr_body_matcher.py | 106 | is ``[[[rpc_id, "<args_json>", null, "generic"]]]`` and ``<args_json>`` | STRING |
| HIGH | tests/unit/test_vcr_body_matcher.py | 394 | The outer ``[[[rpc, "...", null, "generic"]]]`` shape parses cleanly, | STRING |
| HIGH⚡ | tests/unit/test_chat_row_adapter.py | 402 | # ``[None]`` (leading slot present but null) yields ``None`` — the | COMMENT |
| HIGH | tests/unit/test_source_selection.py | 1078 | # Response format: [[[title, description, null, null, prompt, audience_level], ...]] | COMMENT |
| HIGH⚡ | tests/unit/mcp/test_sources.py | 281 | # ``status: Literal[...] | None`` serializes as an ``anyOf`` of {enum} + {null}. | COMMENT |
| HIGH⚡ | tests/unit/mcp/test_sources.py | 1902 | {"source": null} as success — it projects NOT_FOUND.""" | STRING |
| HIGH⚡ | tests/unit/mcp/test_uploadwidget.py | 75 | assert "uploadUrls[i]=null;confirmUpload(tok)" in _WIDGET_HTML | CODE |
| HIGH | tests/unit/cli/test_note.py | 578 | CLI emitted ``{"id": null, "created": false, "error": "Creation may | STRING |
| HIGH | tests/unit/cli/test_playwright_login_render_contract.py | 778 | " 2. Or run: notebooklm auth logout && notebooklm login\n" | CODE |
| HIGH | tests/unit/cli/test_playwright_login_render_contract.py | 838 | " 2. Or run: notebooklm auth logout && notebooklm login\n" | CODE |
| HIGH | tests/unit/cli/test_playwright_login_render_contract.py | 914 | " 2. Or run: notebooklm auth logout && notebooklm login\n" | CODE |
| HIGH | tests/_guardrails/test_cassette_shapes.py | 397 | f"[null, '<inner-json>'], got {type(freq).__name__} {freq!r:.120}" | CODE |
| HIGH | tests/_guardrails/test_cassette_shapes.py | 29 | the new 9-param outer shape ``[null, "<inner-json-string>"]`` whose inner | STRING |
| HIGH | tests/_guardrails/test_cassette_shapes.py | 389 | Real chat-ask `f.req` is ``[null, "<inner-json>"]`` whose inner JSON | STRING |
| HIGH | tests/_guardrails/_wire_contract.py | 144 | note="live-verified: settings=[null,2] decodes as status COMPLETE", | CODE |
| HIGH | tests/_guardrails/_wire_contract.py | 164 | "Live: 4/409 source rows carry settings=[null,2,null,3] (all " | CODE |
| HIGH | tests/_guardrails/_wire_contract.py | 796 | # [[<user rows>], null, 1000, true, null, null, [3, true, true], false] | COMMENT |
| HIGH | tests/_guardrails/_wire_contract.py | 877 | "index 2 (tag 3) cannot exist on it. The `[null, true, [id]]` shape this " | CODE |
| HIGH | tests/_guardrails/test_golden_decode_coverage.py | 220 | # ([] for web, [[null, true, [id]]] for drive) are pinned to ``is True`` | COMMENT |
| HIGH | tests/integration/test_vcr_comprehensive.py | 853 | # Drive sources return [[null, true, [source_id]]] when fresh | COMMENT |
| HIGH | tests/integration/test_vcr_comprehensive.py | 635 | ``tests/vcr_config.py``), so ``[1, 3]``, ``[3, 1]`` and the ``[null, | STRING |
| HIGH | tests/integration/test_vcr_comprehensive.py | 636 | null]`` this cassette actually recorded are indistinguishable to it. | STRING |
| HIGH | tests/integration/test_sources_idempotency.py | 108 | ``[[id], title, [null, 28940, [ts, ns], [uuid, [ts, ns]], 5, null, 1, [url]], [null, 2]]`` | STRING |
| HIGH | tests/integration/test_rpc_seam_matrix.py | 45 | [[RPCMethod.LIST_NOTEBOOKS.value, "[null,1,null,[2]]", None, "generic"]] | CODE |
| HIGH | tests/integration/test_artifacts_integration.py | 2574 | """An empty (non-null) CREATE_ARTIFACT result drifts and raises. | STRING |
| 57 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | .pre-commit-config.yaml | 21 | # | COMMENT |
| LOW | pyproject.toml | 41 | COMMENT | |
| LOW | deploy/README.md | 21 | # 1. One-time, on a machine with a browser — bootstrap the Google credential: | COMMENT |
| LOW | deploy/docker-compose.build.yml | 1 | # Override: build the notebooklm-mcp image from THIS checkout instead of pulling | COMMENT |
| LOW | deploy/docker-compose.yml | 1 | # Remote notebooklm-mcp behind a tunnel. Pick ONE tunnel via a Compose profile: | COMMENT |
| LOW | deploy/docker-compose.yml | 21 | # out of the box once a stable release exists. Pin a specific release with | COMMENT |
| LOW | deploy/docker-compose.yml | 41 | # Optional self-hosted OAuth (for claude.ai). Unset → bearer-only; set both | COMMENT |
| LOW | deploy/docker-compose.yml | 61 | # `${FASTMCP_STATELESS_HTTP:-}` injects an EMPTY string when unset, and FastMCP's pydantic | COMMENT |
| LOW | deploy/docker-compose.yml | 101 | # `:-` not `:?` — Compose interpolates the WHOLE file before profile filtering, | COMMENT |
| LOW | tests/conftest.py | 141 | # ``_LAST_POKE_ATTEMPT_MONOTONIC`` and ``_POKE_LOCKS_BY_LOOP`` are shared | COMMENT |
| LOW | tests/cassette_patterns.py | 341 | # URL-encoded form for ``?authuser=`` query params. The provider- | COMMENT |
| LOW | tests/cassette_patterns.py | 361 | COMMENT | |
| LOW | tests/cassette_patterns.py | 421 | # extra level (``?``→``%3F``, ``=``→``%3D``, ``@``→``%40``) — issue #1368. Both | COMMENT |
| LOW | tests/cassette_patterns.py | 441 | # Negative-lookahead alternation built from the false-positive allowlist. | COMMENT |
| LOW | tests/cassette_patterns.py | 461 | # | COMMENT |
| LOW | tests/cassette_patterns.py | 481 | COMMENT | |
| LOW | tests/cassette_patterns.py | 521 | # The name-anchored ``_cookie_header_replacer`` patterns above scrub only the | COMMENT |
| LOW | tests/cassette_patterns.py | 721 | # ============================================================================= | COMMENT |
| LOW | tests/cassette_patterns.py | 741 | # values and OAuth flows. | COMMENT |
| LOW | tests/cassette_patterns.py | 761 | # ``__Secure-*`` / ``__Host-*`` umbrellas — the prefix is distinctive | COMMENT |
| LOW | tests/cassette_patterns.py | 801 | # ------------------------------------------------------------------------- | COMMENT |
| LOW | tests/cassette_patterns.py | 821 | # does not itself re-match (idempotent). | COMMENT |
| LOW | tests/cassette_patterns.py | 861 | ), | COMMENT |
| LOW | tests/cassette_patterns.py | 881 | "X-GUploader-UploadID: SCRUBBED_UPLOAD_ID", | COMMENT |
| LOW | tests/cassette_patterns.py | 901 | # ------------------------------------------------------------------------- | COMMENT |
| LOW | tests/cassette_patterns.py | 921 | # ``[\"alice@gmail.com\",1,[],[\"First Last\",\"https://lh3...\"]]``. | COMMENT |
| LOW | tests/cassette_patterns.py | 1101 | ) | COMMENT |
| LOW | tests/cassette_patterns.py | 1121 | # Drive file ID in JSON key: ``"file_id": "<id>"``. | COMMENT |
| LOW | tests/cassette_patterns.py | 1141 | # directly. | COMMENT |
| LOW | tests/cassette_patterns.py | 1161 | # to the ``SCRUBBED_API_KEY`` sentinel (which does not contain the ``AIza`` | COMMENT |
| LOW | tests/cassette_patterns.py | 1181 | # Detectors with ZERO legitimate-occurrence risk anywhere in the repository: | COMMENT |
| LOW | tests/cassette_patterns.py | 1201 | # key on, and the existing high-entropy scan only catches it when it happens to | COMMENT |
| LOW | tests/cassette_patterns.py | 1221 | COMMENT | |
| LOW | tests/cassette_patterns.py | 1241 | # This is not hypothetical: the guard has missed two such shapes historically | COMMENT |
| LOW | tests/cassette_patterns.py | 1261 | # achievable while still catching a planted novel token. This residual-risk | COMMENT |
| LOW | tests/cassette_patterns.py | 1281 | # | COMMENT |
| LOW | tests/cassette_patterns.py | 1501 | # --- 7. Avatar URLs --------------------------------------------------- | COMMENT |
| LOW | tests/cassette_patterns.py | 1521 | # definition — this is the cookie-name-agnostic backstop that closes the | COMMENT |
| LOW | tests/cassette_patterns.py | 1541 | leaks.extend(find_high_entropy_leaks(text)) | COMMENT |
| LOW | tests/vcr_config.py | 361 | # matcher's intent is to catch **structural** drift (different RPC id, different | COMMENT |
| LOW | tests/vcr_config.py | 721 | # Streaming-chat: drop the volatile conversation_id at slot 4 and | COMMENT |
| LOW | tests/vcr_config.py | 741 | c2[4] = SENTINEL | COMMENT |
| LOW | tests/vcr_config.py | 761 | # ============================================================================= | COMMENT |
| LOW | tests/vcr_config.py | 801 | # ``freq`` is wired into the default ``match_on`` tuple above. The matcher | COMMENT |
| LOW | tests/unit/test_vcr_config.py | 361 | assert out.startswith("<html>") | COMMENT |
| LOW | tests/unit/conftest.py | 41 | """ | COMMENT |
| LOW | tests/unit/conftest.py | 61 | # wrapper's ``aiter_bytes`` + rebuild path works on it. Returning a | COMMENT |
| LOW | tests/unit/test_check_rpc_health.py | 1661 | assert captured["base_url_source"] == "--base-url" | COMMENT |
| LOW | tests/unit/test_sources_row_adapter.py | 841 | assert "documentId" not in caplog.text, f"must not warn for {why}" | COMMENT |
| LOW | tests/unit/test_cassette_sanitizer.py | 581 | allowlist = TESTS_DIR / "scripts" / "cassette_repair_allowlist.txt" | COMMENT |
| LOW | tests/unit/test_cassette_sanitizer.py | 601 | # ``artifacts_revise_slide.yaml`` is NOT in this required-set anymore | COMMENT |
| LOW | tests/unit/test_exceptions.py | 341 | with pytest.raises(SourceError): | COMMENT |
| LOW | tests/unit/test_authed_post_pipeline.py | 481 | # Tightened signature pins the explicit-collaborator contract: | COMMENT |
| LOW | tests/unit/test_auth_storage.py | 621 | # COOKIE DOMAIN VALIDATION TESTS | COMMENT |
| LOW | tests/unit/test_notebook_api.py | 381 | # The message names what broke the baseline — otherwise nothing reaching the | COMMENT |
| LOW | tests/unit/test_artifact_downloads_coverage.py | 561 | # out to the temp-file cleanup, keeping the assertion on the original | COMMENT |
| LOW | tests/unit/test_auth_cookie_save_race.py | 1721 | # Explicit barrier: each coroutine records its submission and the | COMMENT |
| LOW | tests/unit/test_auth_cookie_save_race.py | 1741 | COMMENT | |
| LOW | tests/unit/test_user_settings_api.py | 141 | # --------------------------------------------------------------------------- | COMMENT |
| LOW | tests/unit/test_scripts_auth_cookie_domains.py | 401 | # path rather than a method id -- were a separate leak: each hand-built | COMMENT |
| 417 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | tests/cassette_patterns.py | 150 | Re-derive ``<count>`` prefixes in a chunked response body. Google's batchexecute responses are framed as alternatin | STRING |
| HIGH | tests/cassette_patterns.py | 1599 | Return a ``(status_code, body, headers)`` triple for a synthetic error. The shape is intentionally minimal; the cli | STRING |
| HIGH | src/notebooklm/_sharing.py | 39 | Share notebook with a user. Intent wrapper over :meth:`set_users`. The underlying operation is an upser | STRING |
| HIGH | src/notebooklm/_notes.py | 46 | Get a specific note by ID. Args: notebook_id: The notebook ID. note_id: The note ID. | STRING |
| HIGH | src/notebooklm/paths.py | 225 | Get directory for a specific profile. Args: profile: Profile name. If None, resolves via resolve_profile(). | STRING |
| HIGH | src/notebooklm/client.py | 759 | Refresh authentication tokens by fetching the NotebookLM homepage. This helps prevent 'Session Expired' errors | STRING |
| HIGH | src/notebooklm/_idempotency.py | 142 | Probe-then-retry wrapper for mutating create RPCs. Args: create: Coroutine factory that issues the create R | STRING |
| HIGH | src/notebooklm/_chat.py | 276 | Ask the notebook a question. Args: notebook_id: The notebook ID. question: The question | STRING |
| HIGH | src/notebooklm/_chat.py | 539 | Save a chat answer as a citation-rich note (issue #660). Unlike :meth:`NotesAPI.create`, this preserves the ``[ | STRING |
| HIGH | src/notebooklm/_sources.py | 55 | Get details of a specific source. Args: notebook_id: The notebook ID. source_id: The so | STRING |
| HIGH | src/notebooklm/_sources.py | 110 | Wait for a source to become ready. Polls until READY, terminal ERROR, or timeout. Configured transient | STRING |
| HIGH | src/notebooklm/_sources.py | 198 | Wait for a source to be registered server-side (status >= PROCESSING). Polls until the source is visible in the | STRING |
| HIGH | src/notebooklm/_sources.py | 248 | Wait for multiple sources to become ready in parallel. Args: notebook_id: The notebook ID. | STRING |
| HIGH | src/notebooklm/utils.py | 159 | Return the surrounding source-text passage for a chat citation. A :class:`~notebooklm.types.ChatReference` carries | STRING |
| HIGH | src/notebooklm/_lookup.py | 28 | Return ``obj`` unchanged, or raise ``exc`` when ``obj`` is ``None``. The narrow contract is deliberate: callers pas | STRING |
| HIGH | src/notebooklm/artifacts.py | 77 | Run an artifact-generation callable with rate-limit retry. The callable is always invoked at least once. A retry is | STRING |
| HIGH | src/notebooklm/_mind_maps_api.py | 164 | Rename a mind map (dispatches by kind: ``UPDATE_NOTE`` / ``RENAME_ARTIFACT``). Omitting ``kind`` triggers an ex | STRING |
| HIGH | src/notebooklm/_types/documents.py | 817 | A readable flat rendering of the document, or of one range of it. The third of this library's three renderings | STRING |
| HIGH | src/notebooklm/_auth/cookies.py | 236 | Extract Google cookies from Playwright storage state for NotebookLM auth. Filters through the canonical auth-domain | STRING |
| HIGH | src/notebooklm/_auth/cookies.py | 370 | Load Playwright storage state from file or environment variable. This is a shared helper used by load_auth_from_sto | STRING |
| HIGH | src/notebooklm/_auth/cookies.py | 451 | Load cookies as an httpx.Cookies object for authenticated downloads. Unlike load_auth_from_storage() which returns | STRING |
| HIGH | src/notebooklm/_auth/cookies.py | 491 | Extract Google cookies from storage state preserving original identity. Returns a path-aware ``(name, domain, path) | STRING |
| HIGH | src/notebooklm/_auth/cookies.py | 583 | Build an httpx.Cookies jar with original domains preserved. This function loads cookies from storage and creates a | STRING |
| HIGH | src/notebooklm/_auth/tokens.py | 268 | Return the ``Cookie:`` header this session would send to ``url``. .. deprecated:: 0.8.1 Scheduled fo | STRING |
| HIGH | src/notebooklm/_auth/tokens.py | 440 | Create AuthTokens from Playwright storage state file. Compatibility loader for callers that still need a standa | STRING |
| HIGH | src/notebooklm/_auth/tokens.py | 805 | Load Google cookies from storage as a flat name→value dict. Loads authentication cookies with the following precede | STRING |
| HIGH | src/notebooklm/_auth/browser_capture.py | 1214 | Capture NotebookLM storage state by attaching to a running Chrome over CDP. An **alternative credential source** fo | STRING |
| HIGH | src/notebooklm/_auth/extraction.py | 83 | Extract a ``WIZ_global_data[key]`` value from a NotebookLM HTML response. NotebookLM (and other Google products) em | STRING |
| HIGH | src/notebooklm/_auth/extraction.py | 386 | Extract CSRF token (SNlM0e) from NotebookLM page HTML. The CSRF token is embedded in the page's WIZ_global_dat | STRING |
| HIGH | src/notebooklm/_auth/extraction.py | 429 | Extract session ID (FdrFJe) from NotebookLM page HTML. The session ID is embedded in the page's WIZ_global_dat | STRING |
| HIGH | src/notebooklm/_auth/refresh.py | 938 | Internal: fetch CSRF and session tokens using a pre-built cookie jar. This is the single implementation for all tok | STRING |
| HIGH | src/notebooklm/_auth/refresh.py | 1035 | Fetch tokens from a cookie mapping. For backward compatibility. Prefer NotebookLMClient.from_storage(), which prese | STRING |
| HIGH | src/notebooklm/_auth/refresh.py | 1142 | Validate the auth cookies on disk without any side effects. Performs the same token-fetch round-trip (a homepage GE | STRING |
| HIGH | src/notebooklm/_auth/account.py | 112 | Enumerate Google accounts visible to the given cookie jar. Probes ``<configured base URL>/?authuser=N`` (see :f | STRING |
| HIGH | src/notebooklm/mcp/_resolve.py | 278 | Resolve a notebook reference (full/partial id, exact title, or unique title prefix) to its id. Args: client | STRING |
| HIGH | src/notebooklm/mcp/_resolve.py | 306 | Resolve a source reference within a notebook to its id. Args: client: The lifespan-bound client. no | STRING |
| HIGH | src/notebooklm/mcp/_resolve.py | 337 | Resolve many source references within a notebook, listing sources at most once. The per-tool callers ``chat_ask`` / | STRING |
| HIGH | src/notebooklm/mcp/_resolve.py | 398 | Resolve a note reference within a notebook to its id. Same matching rules as :func:`resolve_source`, over the noteb | STRING |
| HIGH | src/notebooklm/mcp/_resolve.py | 429 | Resolve a studio-artifact reference within a notebook to its id. Same matching rules as :func:`resolve_source`, ove | STRING |
| HIGH | src/notebooklm/cli/resolve.py | 44 | Validate and normalize an entity ID. Args: entity_id: The ID to validate. entity_name: Name for err | STRING |
| HIGH | src/notebooklm/cli/resolve.py | 126 | Get notebook ID from argument, env var, or active context. Resolution order (env-var precedence): 1. ``noteboo | STRING |
| HIGH | src/notebooklm/cli/resolve.py | 207 | Resolve a partial ID against a **pre-fetched** item list. Sync core of the partial-ID matching logic. Encapsulates | STRING |
| HIGH | src/notebooklm/cli/resolve.py | 339 | Resolve a case-insensitive partial ID prefix to a full entity ID. Allows users to type partial IDs like ``abc`` ins | STRING |
| HIGH | src/notebooklm/cli/_firefox_containers.py | 231 | Resolve a ``--browser-cookies 'firefox::<spec>'`` to a selector. Args: profile_path: Firefox profile direct | STRING |
| HIGH | src/notebooklm/cli/_firefox_containers.py | 420 | Read ``cookies.sqlite`` filtered to a single container. Args: profile_path: Firefox profile directory conta | STRING |
| HIGH | src/notebooklm/cli/_chromium_profiles.py | 316 | Read and decrypt cookies from a single Chromium user-data profile. Uses ``rookie_cookies.any_browser(db_path, domai | STRING |
| HIGH | src/notebooklm/cli/download_helpers.py | 34 | Resolve a partial artifact ID to a full ID. UUID-shaped IDs (canonical 8-4-4-4-12 hex layout, case-insensitive - | STRING |
| HIGH | src/notebooklm/cli/auth_runtime.py | 84 | Get auth components from context. Args: ctx: Click context with optional storage_path in obj Returns: | STRING |
| HIGH | src/notebooklm/cli/input.py | 11 | Read all of stdin as UTF-8 text and strip surrounding whitespace. Centralizes the Unix ``-`` stdin convention used | STRING |
| HIGH | src/notebooklm/cli/input.py | 44 | Resolve prompt text from a positional argument or ``--prompt-file``. Exactly one source may be provided. The file/s | STRING |
| HIGH | src/notebooklm/cli/services/login/cookie_jar.py | 86 | Probe ``?authuser=N`` against one cookie set and return tagged Accounts. Shared by both the legacy single-jar path | STRING |
| HIGH | src/notebooklm/cli/services/login/profile_targets.py | 46 | Derive a valid profile name from an email address. Profile names are restricted to ``[a-zA-Z0-9_-]`` (see :data | STRING |
| HIGH | src/notebooklm/_web/sharing.py | 189 | Set several users' permissions on a notebook in one request. This is an **upsert**, not an add: an email that i | STRING |
| HIGH | src/notebooklm/_web/research.py | 289 | Start a research session. Args: notebook_id: The notebook ID. query: The research query | STRING |
| HIGH | src/notebooklm/_web/research.py | 472 | Poll until research reaches a terminal state or times out. When the first poll returns a concrete ``task_id``, | STRING |
| HIGH | src/notebooklm/_web/notes.py | 521 | Get a specific note by ID. Args: notebook_id: The notebook ID. note_id: The note ID. | STRING |
| HIGH | src/notebooklm/_web/chat.py | 427 | Read the notebook's current chat configuration. Decodes the chat-settings block from ``GET_NOTEBOOK`` so a *par | STRING |
| HIGH | src/notebooklm/_web/notebooks.py | 407 | Get AI-suggested prompts for a notebook. Backed by ``GeneratePromptSuggestions`` (``otmP3b``): a *general* | STRING |
| HIGH | src/notebooklm/_web/notebooks.py | 606 | Get notebook details. Args: notebook_id: The notebook ID. Returns: Notebook ob | STRING |
| HIGH | src/notebooklm/_web/transport/reqid_counter.py | 173 | Atomically increment the counter and return the new value. Args: step: Increment applied to the cou | STRING |
| 16 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/unit/test_json_stdout_purity.py | 459 | def _setup_fs_doctor(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: | CODE |
| LOW | tests/unit/test_json_stdout_purity.py | 488 | def _setup_fs_profile_list(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: | CODE |
| LOW | tests/unit/test_auth_refresh_profile_store.py | 92 | def _set_live(live: httpx.Cookies, name: str, value: str) -> None: | CODE |
| LOW | tests/unit/test_auth_session_headless_reauth.py | 95 | async def update_auth_tokens(self, *, auth: AuthTokens, csrf: str, session_id: str) -> None: | CODE |
| LOW | tests/unit/test_auth_session_headless_reauth.py | 124 | def update_auth_headers(self, *, auth: AuthTokens, kernel: Any) -> None: | CODE |
| LOW | tests/unit/test_auth_cookie_save_race.py | 92 | def _set_cookie_value(jar: httpx.Cookies, name: str, value) -> None: | CODE |
| LOW | tests/unit/test_auth_session.py | 110 | async def update_auth_tokens(self, *, auth: AuthTokens, csrf: str, session_id: str) -> None: | CODE |
| LOW | tests/unit/test_auth_session.py | 139 | def update_auth_headers(self, *, auth: AuthTokens, kernel: Any) -> None: | CODE |
| LOW | tests/unit/test_auth_session_refresh_cmd.py | 67 | async def update_auth_tokens(self, *, auth: AuthTokens, csrf: str, session_id: str) -> None: | CODE |
| LOW | tests/unit/test_auth_session_refresh_cmd.py | 72 | def update_auth_headers(self, *, auth: AuthTokens, kernel: Any) -> None: | CODE |
| LOW | tests/unit/mcp/conftest.py | 156 | __all__ = ["AsyncMock"] # re-exported for convenience in tool tests | CODE |
| LOW | tests/unit/mcp/test_entrypoint.py | 59 | def _set_oauth_env(monkeypatch: pytest.MonkeyPatch) -> None: | CODE |
| LOW | tests/unit/cli/test_cli_mcp_parity.py | 211 | def _setup(c: Any) -> None: | CODE |
| LOW | tests/unit/cli/test_cli_mcp_parity.py | 226 | def _setup(c: Any) -> None: | CODE |
| LOW | tests/_baselines/registry.py | 316 | __all__ = [ | CODE |
| LOW | tests/_baselines/storage_transaction_policy.py | 72 | __all__ = [ | CODE |
| LOW | tests/_baselines/__init__.py | 20 | __all__ = ["BASELINES", "Baseline"] | CODE |
| LOW | tests/_baselines/module_size.py | 142 | __all__ = [ | CODE |
| LOW | tests/_baselines/guardrail_literals.py | 79 | __all__ = [ | CODE |
| LOW⚡ | tests/_guardrails/test_cookie_persistence_boundary.py | 568 | def _set_local_client(self, name: str, value: bool) -> None: | CODE |
| LOW | tests/integration/cli_vcr/_cassette_expectations.py | 304 | __all__ = [ | CODE |
| LOW | tests/integration/cli_vcr/conftest.py | 59 | __all__ = [ | CODE |
| LOW | tests/integration/cli_vcr/_fixtures.py | 87 | __all__ = [ | CODE |
| LOW⚡ | tests/integration/concurrency/conftest.py | 58 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/integration/concurrency/conftest.py | 210 | def set_delay(self, seconds: float) -> None: | CODE |
| LOW | tests/integration/concurrency/test_chat_history_race.py | 169 | def set_answer(self, question: str, answer: str) -> None: | CODE |
| LOW | tests/integration/concurrency/helpers.py | 47 | logger = logging.getLogger(__name__) | CODE |
| LOW | tests/integration/mcp_vcr/conftest.py | 42 | __all__ = ["build_mcp_client", "build_zero_retry_mcp_client"] | CODE |
| LOW | tests/server/fakes.py | 331 | async def set_mode(self, notebook_id: str, mode: Any) -> None: | CODE |
| LOW | tests/server/fakes.py | 760 | def set_research_failed(self, notebook_id: str, poll_id: str, *, query: str = "q") -> None: | CODE |
| LOW | tests/_fixtures/rpc_error_frames.py | 18 | __all__ = [ | CODE |
| LOW | tests/_fixtures/chain.py | 122 | __all__ = [ | CODE |
| LOW | tests/_fixtures/__init__.py | 22 | __all__ = [ | CODE |
| LOW | scripts/_tracked_files.py | 29 | __all__ = ["tracked_files"] | CODE |
| LOW | scripts/_live_auth_scenarios/__init__.py | 48 | __all__ = [ | CODE |
| LOW | src/notebooklm/_sharing.py | 9 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/notebooklm/_sharing.py | 106 | __all__ = ["SharingAPI"] | CODE |
| LOW | src/notebooklm/_research.py | 14 | __all__ = [ # noqa: F822 - resolved lazily below | CODE |
| LOW | src/notebooklm/auth.py | 107 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/notebooklm/auth.py | 191 | __all__ = [ | CODE |
| LOW | src/notebooklm/_notes.py | 185 | __all__ = ["NotesAPI"] | CODE |
| LOW | src/notebooklm/_logging.py | 33 | __all__ = [ | CODE |
| LOW | src/notebooklm/config.py | 17 | __all__ = [ | CODE |
| LOW | src/notebooklm/_serving.py | 20 | __all__ = [ | CODE |
| LOW | src/notebooklm/paths.py | 45 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/notebooklm/paths.py | 58 | __all__ = [ | CODE |
| LOW | src/notebooklm/paths.py | 78 | def set_active_profile(profile: str | None) -> None: | CODE |
| LOW | src/notebooklm/research.py | 23 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/notebooklm/research.py | 148 | __all__ = [ | CODE |
| LOW | src/notebooklm/log.py | 9 | __all__ = ["install_redaction"] | CODE |
| LOW | src/notebooklm/_transport_drain.py | 54 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/notebooklm/_transport_drain.py | 324 | __all__ = ["TransportDrainTracker", "_TransportOperationToken"] | CODE |
| LOW | src/notebooklm/client.py | 80 | __all__ = ["NotebookLMClient"] | CODE |
| LOW | src/notebooklm/client.py | 82 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/notebooklm/_idempotency.py | 32 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/notebooklm/_idempotency.py | 252 | __all__ = ["idempotent_create", "mark_unconfirmed"] | CODE |
| LOW | src/notebooklm/io.py | 10 | __all__ = ["atomic_update_json", "atomic_write_json", "replace_file_atomically"] | CODE |
| LOW | src/notebooklm/_redact.py | 28 | __all__ = ["DEFAULT_MAX_MESSAGE", "redact"] | CODE |
| LOW | src/notebooklm/_loop_affinity.py | 62 | __all__ = ["assert_bound_loop"] | CODE |
| LOW | src/notebooklm/__init__.py | 215 | __all__ = [ | CODE |
| 242 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/cassette_patterns.py | 570 | CODE | |
| LOW | tests/vcr_config.py | 565 | CODE | |
| LOW | tests/vcr_config.py | 617 | CODE | |
| LOW | tests/unit/test_live_auth_matrix.py | 1043 | CODE | |
| LOW | tests/unit/test_streaming_chat_wire.py | 983 | CODE | |
| LOW | tests/unit/test_concurrency_refresh_race.py | 501 | CODE | |
| LOW | tests/unit/test_auth_cold_start_recovery.py | 438 | CODE | |
| LOW | tests/unit/test_auth_psidts_recovery.py | 434 | CODE | |
| LOW | tests/unit/test_app_master_token.py | 838 | CODE | |
| LOW | tests/unit/test_sources_row_adapter.py | 76 | CODE | |
| LOW | tests/unit/test_auth_mint_service.py | 141 | CODE | |
| LOW | tests/unit/test_init_order.py | 173 | CODE | |
| LOW | tests/unit/test_rpc_types.py | 34 | CODE | |
| LOW | tests/unit/test_rpc_overrides.py | 69 | CODE | |
| LOW | tests/unit/app/test_app_login_cookie.py | 371 | CODE | |
| LOW | tests/unit/cli/test_quiet_enforcement.py | 99 | CODE | |
| LOW | tests/_baselines/storage_transaction_policy.py | 17 | CODE | |
| LOW | tests/_baselines/module_size.py | 98 | CODE | |
| LOW | tests/_baselines/guardrail_literals.py | 54 | CODE | |
| LOW | tests/_guardrails/test_middleware_context_contract.py | 96 | CODE | |
| LOW | tests/_guardrails/test_auth_phase12c_boundaries.py | 253 | CODE | |
| LOW | tests/_guardrails/test_auth_storage_lock_boundary.py | 116 | CODE | |
| LOW | tests/_guardrails/test_auth_cookie_filter_boundary.py | 90 | CODE | |
| LOW | tests/_guardrails/test_auth_cookie_filter_boundary.py | 138 | CODE | |
| LOW | tests/_guardrails/test_no_session.py | 60 | CODE | |
| LOW | tests/_guardrails/test_auth_credential_io_boundary.py | 114 | CODE | |
| LOW | tests/_guardrails/test_cli_boundary.py | 271 | CODE | |
| LOW | tests/_guardrails/test_cli_boundary.py | 302 | CODE | |
| LOW | tests/_guardrails/test_cli_boundary.py | 335 | CODE | |
| LOW | tests/_guardrails/test_cli_boundary.py | 436 | CODE | |
| LOW | tests/_guardrails/test_cli_boundary.py | 561 | CODE | |
| LOW | tests/_guardrails/test_cli_boundary.py | 672 | CODE | |
| LOW | tests/_guardrails/test_auth_profile_store_boundary.py | 477 | CODE | |
| LOW | tests/_guardrails/test_auth_profile_store_boundary.py | 933 | CODE | |
| LOW | tests/_guardrails/test_auth_profile_store_boundary.py | 983 | CODE | |
| LOW | tests/_guardrails/test_auth_profile_store_boundary.py | 2265 | CODE | |
| LOW | tests/_guardrails/test_auth_profile_store_boundary.py | 293 | CODE | |
| LOW | tests/_guardrails/test_auth_profile_store_boundary.py | 1058 | CODE | |
| LOW | tests/_guardrails/test_auth_profile_store_boundary.py | 1409 | CODE | |
| LOW | tests/_guardrails/test_auth_profile_store_boundary.py | 1446 | CODE | |
| LOW | tests/_guardrails/test_auth_storage_compatibility.py | 74 | CODE | |
| LOW | tests/_guardrails/test_auth_storage_compatibility.py | 1251 | CODE | |
| LOW | tests/_guardrails/test_auth_storage_compatibility.py | 1701 | CODE | |
| LOW | tests/_guardrails/test_auth_storage_compatibility.py | 1965 | CODE | |
| LOW | tests/_guardrails/test_rotate_wire_contract.py | 121 | CODE | |
| LOW | tests/_guardrails/test_backend_boundaries.py | 231 | CODE | |
| LOW | tests/_guardrails/test_error_handler_allowlist.py | 104 | CODE | |
| LOW | tests/_guardrails/test_public_surface.py | 288 | CODE | |
| LOW | tests/_guardrails/test_no_session_compat_bridges.py | 165 | CODE | |
| LOW | tests/_guardrails/test_type_boundaries.py | 59 | CODE | |
| LOW | tests/_guardrails/test_type_boundaries.py | 133 | CODE | |
| LOW | tests/_guardrails/test_type_boundaries.py | 161 | CODE | |
| LOW | tests/_guardrails/test_type_boundaries.py | 184 | CODE | |
| LOW | tests/_guardrails/test_storage_writer_boundary.py | 103 | CODE | |
| LOW | tests/_guardrails/test_storage_writer_boundary.py | 185 | CODE | |
| LOW | tests/_guardrails/test_storage_writer_boundary.py | 650 | CODE | |
| LOW | tests/_guardrails/test_storage_writer_boundary.py | 777 | CODE | |
| LOW | tests/_guardrails/test_cli_rpc_envelope.py | 90 | CODE | |
| LOW | tests/_guardrails/test_cli_rpc_envelope.py | 127 | CODE | |
| LOW | tests/_guardrails/test_cli_rpc_envelope.py | 178 | CODE | |
| 197 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | tests/unit/test_auth_cookie_policy.py | 0 | tests for auth token refresh and fetch_tokens (split in d1 pr-2). this file owns one concern from the auth subpackage. t | STRING |
| HIGH | tests/unit/test_auth_storage.py | 0 | tests for auth token refresh and fetch_tokens (split in d1 pr-2). this file owns one concern from the auth subpackage. t | STRING |
| HIGH | tests/unit/test_auth_refresh.py | 0 | tests for auth token refresh and fetch_tokens (split in d1 pr-2). this file owns one concern from the auth subpackage. t | STRING |
| HIGH | tests/unit/cli/test_artifact.py | 0 | path a: uuid-shaped id skips partial-resolve; backend none → exit 1. | STRING |
| HIGH | tests/unit/cli/test_source.py | 0 | path a: uuid-shaped id skips partial-resolve; backend none → exit 1. | STRING |
| HIGH | tests/unit/cli/test_note.py | 0 | path a: uuid-shaped id skips partial-resolve; backend none → exit 1. | STRING |
| HIGH | tests/unit/cli/test_artifact.py | 0 | path a under ``--json``: typed json error doc + exit 1. | STRING |
| HIGH | tests/unit/cli/test_source.py | 0 | path a under ``--json``: typed json error doc + exit 1. | STRING |
| HIGH | tests/unit/cli/test_note.py | 0 | path a under ``--json``: typed json error doc + exit 1. | STRING |
| HIGH | tests/unit/cli/test_artifact.py | 0 | path b: partial-resolve succeeds, backend get() returns none → exit 1. | STRING |
| HIGH | tests/unit/cli/test_source.py | 0 | path b: partial-resolve succeeds, backend get() returns none → exit 1. | STRING |
| HIGH | tests/unit/cli/test_note.py | 0 | path b: partial-resolve succeeds, backend get() returns none → exit 1. | STRING |
| HIGH | tests/_guardrails/test_server_classify_consistency.py | 0 | exactly one exemplar per category, so the parametrization is exhaustive. | STRING |
| HIGH | tests/_guardrails/test_mcp_classify_consistency.py | 0 | exactly one exemplar per category, so the parametrization is exhaustive. | STRING |
| HIGH | …_guardrails/test_classify_error_handler_consistency.py | 0 | exactly one exemplar per category, so the parametrization is exhaustive. | STRING |
| HIGH | …ts/integration/test_artifact_generation_idempotency.py | 0 | extract the ``rpcids=`` query param from a batchexecute request url. | STRING |
| HIGH | tests/integration/test_research_idempotency.py | 0 | extract the ``rpcids=`` query param from a batchexecute request url. | STRING |
| HIGH | tests/integration/test_side_effects_idempotency.py | 0 | extract the ``rpcids=`` query param from a batchexecute request url. | STRING |
| HIGH | tests/integration/test_notes_idempotency.py | 0 | extract the ``rpcids=`` query param from a batchexecute request url. | STRING |
| HIGH | …sts/integration/concurrency/test_idempotency_create.py | 0 | extract the ``rpcids=`` query param from a batchexecute request url. | STRING |
| HIGH | …sts/integration/concurrency/test_note_create_cancel.py | 0 | extract the ``rpcids=`` query param from a batchexecute request url. | STRING |
| HIGH | tests/integration/test_settings_integration.py | 0 | integration tests for sharingapi. moved from ``tests/unit/`` to ``tests/integration/``. mock-backed (``pytest_httpx``); | STRING |
| HIGH | tests/integration/test_notes_integration.py | 0 | integration tests for sharingapi. moved from ``tests/unit/`` to ``tests/integration/``. mock-backed (``pytest_httpx``); | STRING |
| HIGH | tests/integration/test_notebooks_integration.py | 0 | integration tests for sharingapi. moved from ``tests/unit/`` to ``tests/integration/``. mock-backed (``pytest_httpx``); | STRING |
| HIGH | tests/integration/test_sharing_integration.py | 0 | integration tests for sharingapi. moved from ``tests/unit/`` to ``tests/integration/``. mock-backed (``pytest_httpx``); | STRING |
| HIGH | tests/integration/test_chat_delete_conversation_vcr.py | 0 | decode the form-encoded ``f.req`` body into its param list. | STRING |
| HIGH | tests/integration/test_notebooks_suggest_prompts_vcr.py | 0 | decode the form-encoded ``f.req`` body into its param list. | STRING |
| HIGH | tests/integration/test_research_cancel_vcr.py | 0 | decode the form-encoded ``f.req`` body into its param list. | STRING |
| HIGH | tests/integration/cli_vcr/test_generate.py | 0 | cli integration tests for note commands. these tests exercise the full cli → client → rpc path using vcr cassettes. | STRING |
| HIGH | tests/integration/cli_vcr/test_downloads.py | 0 | cli integration tests for note commands. these tests exercise the full cli → client → rpc path using vcr cassettes. | STRING |
| HIGH | tests/integration/cli_vcr/test_notes.py | 0 | cli integration tests for note commands. these tests exercise the full cli → client → rpc path using vcr cassettes. | STRING |
| HIGH | …ipts/_live_auth_scenarios/sibling_concurrent_reload.py | 0 | entry point for ``python -m`` execution by the live-auth matrix. | STRING |
| HIGH | scripts/_live_auth_scenarios/rest_recovery.py | 0 | entry point for ``python -m`` execution by the live-auth matrix. | STRING |
| HIGH | scripts/_live_auth_scenarios/mcp_recovery.py | 0 | entry point for ``python -m`` execution by the live-auth matrix. | STRING |
| HIGH | scripts/_live_auth_scenarios/browser_refresh.py | 0 | entry point for ``python -m`` execution by the live-auth matrix. | STRING |
| HIGH | scripts/_live_auth_scenarios/master_token_recovery.py | 0 | entry point for ``python -m`` execution by the live-auth matrix. | STRING |
| HIGH | src/notebooklm/_artifacts.py | 0 | revise an individual slide in a completed slide deck using a prompt. | STRING |
| HIGH | src/notebooklm/_web/artifacts.py | 0 | revise an individual slide in a completed slide deck using a prompt. | STRING |
| HIGH | src/notebooklm/_web/artifact/generation.py | 0 | revise an individual slide in a completed slide deck using a prompt. | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/conftest.py | 399 | except Exception: | CODE |
| LOW | tests/unit/test_windows_compatibility.py | 312 | except Exception as e: | CODE |
| LOW | tests/unit/mcp/conftest.py | 92 | except Exception as exc: # noqa: BLE001 - scripted per-item outcome | CODE |
| LOW | tests/unit/cli/test_cli_mcp_parity.py | 172 | except Exception as exc: # noqa: BLE001 - caller classifies (see _mcp_capture) | CODE |
| LOW | tests/unit/concurrency/test_close_cancellation_leak.py | 368 | except Exception: | CODE |
| LOW | tests/_guardrails/test_storage_transaction_ratchet.py | 233 | except Exception: | STRING |
| LOW | tests/integration/test_chat_delete_conversation_vcr.py | 139 | except Exception as exc: # noqa: BLE001 | CODE |
| LOW⚡ | tests/integration/test_chat_multi_source_vcr.py | 272 | except Exception as exc: # noqa: BLE001 — best-effort cleanup | CODE |
| LOW | tests/integration/test_chat_oversized_rejection_vcr.py | 144 | except Exception: # noqa: BLE001 — best-effort scratch cleanup | CODE |
| LOW | …sts/integration/test_curl_cffi_cassette_conformance.py | 66 | except Exception: | CODE |
| LOW | tests/integration/test_research_cancel_vcr.py | 152 | except Exception as exc: # noqa: BLE001 | CODE |
| LOW | tests/integration/concurrency/test_add_file_toctou.py | 235 | except Exception: # noqa: BLE001 — defensive | CODE |
| LOW | tests/server/fakes.py | 154 | except Exception as exc: # noqa: BLE001 - scripted per-item outcome | CODE |
| LOW | tests/scripts/setup-generation-notebook.py | 74 | except Exception as exc: # noqa: BLE001 — top-level CLI surface | CODE |
| LOW | tests/scripts/check_cassettes_clean.py | 196 | except Exception: # noqa: BLE001 - degrade to line-scan on any parse/read error | CODE |
| MEDIUM | tests/e2e/conftest.py | 106 | def _ask_with_skip(*args, **kwargs): | CODE |
| LOW⚡ | tests/e2e/conftest.py | 748 | except Exception as e: | CODE |
| LOW⚡ | tests/e2e/conftest.py | 809 | except Exception: | CODE |
| LOW⚡ | tests/e2e/conftest.py | 924 | except Exception: | CODE |
| LOW⚡ | tests/e2e/conftest.py | 933 | except Exception: | CODE |
| LOW⚡ | tests/e2e/conftest.py | 1002 | except Exception as e: | CODE |
| LOW⚡ | tests/e2e/conftest.py | 1028 | except Exception: | CODE |
| LOW⚡ | tests/e2e/conftest.py | 1046 | except Exception: | CODE |
| LOW⚡ | tests/e2e/conftest.py | 1198 | except Exception as e: | CODE |
| LOW | tests/e2e/conftest.py | 889 | except Exception: | CODE |
| LOW | tests/e2e/conftest.py | 891 | except Exception: | CODE |
| LOW | tests/e2e/conftest.py | 902 | except Exception: | CODE |
| LOW | tests/e2e/conftest.py | 904 | except Exception: | CODE |
| LOW | tests/e2e/conftest.py | 1136 | except Exception: | CODE |
| LOW | tests/e2e/conftest.py | 1138 | except Exception: | CODE |
| LOW | tests/e2e/test_downloads.py | 133 | except Exception: | CODE |
| LOW | docs/rpc-reference.md | 210 | except Exception: | CODE |
| LOW | docs/python-api.md | 527 | except Exception as exc: | CODE |
| LOW⚡ | examples/notes.py | 157 | except Exception as e: | CODE |
| LOW | examples/bulk-import.py | 64 | except Exception as e: | STRING |
| LOW | examples/bulk-import.py | 75 | except Exception as e: | STRING |
| LOW | examples/bulk-import.py | 86 | except Exception as e: | STRING |
| LOW⚡ | examples/chat.py | 102 | except Exception as e: | CODE |
| LOW | scripts/diagnose_get_notebook.py | 140 | except Exception as e: | CODE |
| LOW | scripts/capture_rpc_registry.py | 464 | except Exception as exc: | CODE |
| LOW | scripts/mcp_live_smoke.py | 195 | except Exception as exc: # noqa: BLE001 - top-level smoke wants one clean line | CODE |
| LOW | scripts/audit_public_api_compat.py | 272 | except Exception: | CODE |
| LOW | scripts/audit_public_api_compat.py | 351 | except Exception: # pragma: no cover - defensive; repr should not raise | CODE |
| LOW | scripts/audit_public_api_compat.py | 504 | except Exception as exc: | CODE |
| MEDIUM | scripts/audit_public_api_compat.py | 280 | def signature_payload(obj): | CODE |
| LOW | scripts/_onetime_rescrub_cookies.py | 129 | except Exception as exc: # noqa: BLE001 | CODE |
| LOW | scripts/live_auth_matrix.py | 516 | except Exception as exc: # noqa: BLE001 - report only the value-free exception type | CODE |
| MEDIUM | scripts/live_auth_matrix.py | 280 | def run(self) -> int: | CODE |
| LOW | scripts/check_rpc_health.py | 1715 | except Exception as e: # noqa: BLE001 - see "Never raises" above | CODE |
| LOW | scripts/check_rpc_health.py | 1988 | except Exception as e: | CODE |
| LOW | scripts/check_rpc_health.py | 2004 | except Exception as e: | CODE |
| LOW | scripts/check_rpc_health.py | 2020 | except Exception as e: | CODE |
| LOW | scripts/check_rpc_health.py | 2029 | except Exception as e: | CODE |
| LOW | src/notebooklm/client.py | 547 | except Exception as close_exc: | CODE |
| LOW | src/notebooklm/_curl_cffi_transport.py | 164 | except Exception: # noqa: BLE001 — cleanup must not mask the original error | CODE |
| LOW | src/notebooklm/_notebooks.py | 157 | except Exception as exc: | CODE |
| LOW | src/notebooklm/_notebooks.py | 220 | except Exception as exc: | CODE |
| LOW | src/notebooklm/_client_metrics.py | 143 | except Exception as exc: # noqa: BLE001 - observability must not alter behavior | CODE |
| LOW | src/notebooklm/_atomic_io.py | 292 | except Exception: | CODE |
| LOW | src/notebooklm/_atomic_io.py | 296 | except Exception as cleanup_err: | CODE |
| 87 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/cassette_patterns.py | 209 | # fixed number of characters) is robust to alternate-length prefixes if | COMMENT |
| MEDIUM | tests/vcr_config.py | 366 | # matcher robust across recording sessions while still failing on meaningful | COMMENT |
| MEDIUM | tests/vcr_config.py | 748 | # or extra non-volatile dict keys — while staying robust against leaf | COMMENT |
| MEDIUM⚡ | tests/unit/test_json_stdout_purity.py | 449 | # so the mock-client harness can't drive them. The parametrized sweep | COMMENT |
| MEDIUM | tests/unit/test_json_stdout_purity.py | 721 | # the mock-client harness. `notebook_create` goes through the standard | COMMENT |
| MEDIUM | tests/unit/test_json_stdout_purity.py | 746 | # harness — they read NOTEBOOKLM_HOME directly. Stage a clean layout | COMMENT |
| MEDIUM | tests/unit/test_auth_cookie_save_race.py | 1762 | # order) to stay robust across schedulers. | COMMENT |
| MEDIUM⚡ | tests/unit/test_row_adapters.py | 1367 | # TZ-robust: compare the round-tripped epoch, not a wall-time string. | COMMENT |
| MEDIUM⚡ | tests/unit/test_json_error_exit.py | 728 | # then invoke without the mock-client harness (these commands don't | COMMENT |
| MEDIUM | tests/unit/test_json_error_exit.py | 703 | # Filesystem-driven failure cases bypass the mock-client harness — they | COMMENT |
| MEDIUM | tests/unit/test_sources_upload_delegation.py | 53 | # parse bytecode. ``casefold()`` makes the suffix check robust on | COMMENT |
| MEDIUM | tests/unit/test_rpc_golden_payloads.py | 1359 | # Wiring those would require contorting the harness or adding production code | COMMENT |
| MEDIUM⚡ | tests/unit/test_vcr_body_matcher.py | 293 | # Volatile-key stripping — keep matching robust across recording timestamps | COMMENT |
| MEDIUM | tests/unit/app/test_app_doctor.py | 590 | # The ``browser`` extra is installed in CI; pin it so the test is robust | COMMENT |
| MEDIUM | tests/unit/cli/test_login.py | 371 | # rebuilding this harness. | COMMENT |
| MEDIUM | tests/_guardrails/test_no_pinned_cassette_values.py | 170 | # allow-listing the comparison methods) keeps the gate robust as new | COMMENT |
| MEDIUM | tests/integration/concurrency/test_harness_smoke.py | 50 | # concurrency-harness smoke tests against a mock transport; no | COMMENT |
| MEDIUM | tests/integration/concurrency/test_harness_smoke.py | 139 | # Peak in-flight was high — the harness is genuinely fanning out. | COMMENT |
| MEDIUM | …ts/integration/concurrency/test_max_concurrent_rpcs.py | 71 | # concurrency-harness tests against a mock transport; no HTTP, | COMMENT |
| MEDIUM | …ts/integration/concurrency/test_max_concurrent_rpcs.py | 156 | # Anything <= 8 would mean the gate isn't kicking in (the harness | COMMENT |
| MEDIUM | tests/integration/mcp_vcr/test_research.py | 61 | # recorded poll (the "Python programming best practices" task). Pinning it makes | COMMENT |
| MEDIUM | tests/e2e/test_cli_live.py | 49 | # or an enveloped object so the test is robust to the exact shape. | COMMENT |
| MEDIUM⚡ | tests/e2e/test_research_import_verification.py | 92 | # makes this path robust for fast-mode imports too. | COMMENT |
| MEDIUM | scripts/capture_rpc_registry.py | 84 | # is robust to nested ``[...]`` in the options array (a single forward regex | COMMENT |
| MEDIUM | src/notebooklm/_atomic_io.py | 413 | # and re-introduce the divergent-lock race. ``casefold`` is the robust | COMMENT |
| LOW | src/notebooklm/_web/sharing.py | 132 | # Fetch current status and override view_level with what we just set | COMMENT |
| MEDIUM | src/notebooklm/_app/doctor.py | 162 | # Reuse the shared, name-robust extractor (drops non-dict rows and | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/unit/test_storage_writer.py | 596 | (storage_mod.AccountRecord(7, "user@example.com"), "set", 7, "user@example.com"), | CODE |
| LOW⚡ | tests/unit/test_auth_credential_io.py | 104 | "email": "user@example.com", | CODE |
| LOW⚡ | tests/unit/test_auth_credential_io.py | 112 | '{\n "version": 1,\n "email": "user@example.com",\n' | CODE |
| LOW | tests/unit/test_app_master_token.py | 72 | app.MasterTokenLoginPlan("user@example.com", storage, None, False), | CODE |
| LOW | tests/unit/test_app_master_token.py | 121 | plan = app.MasterTokenLoginPlan("user@example.com", storage, "android", False) | CODE |
| LOW | tests/unit/test_app_master_token.py | 137 | assert calls[0][1] == {"email": "user@example.com", "storage_path": storage, "force": False} | CODE |
| LOW | tests/unit/test_app_master_token.py | 141 | "email": "user@example.com", | CODE |
| LOW | tests/unit/test_app_master_token.py | 160 | app.MasterTokenLoginPlan("user@example.com", storage, None, True), | CODE |
| LOW | tests/unit/test_app_master_token.py | 188 | app.MasterTokenLoginPlan("user@example.com", storage, None, False), | CODE |
| LOW | tests/unit/test_app_master_token.py | 215 | app.MasterTokenLoginPlan("user@example.com", storage, None, False), | CODE |
| LOW | tests/unit/test_app_master_token.py | 253 | app.MasterTokenLoginPlan("user@example.com", storage, None, False), | CODE |
| LOW | tests/unit/test_app_master_token.py | 814 | account_email="user@example.com", | CODE |
| LOW | tests/unit/test_auth_profile_store_account.py | 55 | ({"authuser": 3, "email": " user@example.com "}, ProfileAccount(3, "user@example.com")), | CODE |
| LOW⚡ | tests/unit/test_cassette_sanitizer.py | 532 | fake_key = "AIza" + "Z" * 35 | CODE |
| LOW⚡ | tests/unit/test_cassette_sanitizer.py | 535 | (examples / "leak.json").write_text(f'{{"JrWMbf":"{fake_key}"}}\n', encoding="utf-8") | CODE |
| LOW⚡ | tests/unit/test_chat_ask_invariants.py | 170 | account_email="user@example.com", | CODE |
| LOW | tests/unit/test_chat_ask_invariants.py | 191 | assert _extract_query_param(str(request.url), "authuser") == "user@example.com" | CODE |
| LOW⚡ | tests/unit/test_artifact_generation_prompt.py | 102 | raw = _row_with_prompt(ArtifactTypeCode.AUDIO.value, 6, (1, 0), prompt="placeholder") | CODE |
| LOW⚡ | tests/unit/test_token_regex.py | 47 | assert value == "user@example.com" | CODE |
| LOW⚡ | tests/unit/test_cassette_patterns.py | 258 | @pytest.mark.parametrize("placeholder", sorted(SCRUB_PLACEHOLDERS)) | CODE |
| LOW⚡ | tests/unit/test_sharing_types.py | 276 | data = ["user@example.com", 3, [], ["Test User", "https://avatar.url"]] | CODE |
| LOW⚡ | tests/unit/test_sharing_types.py | 279 | assert user.email == "user@example.com" | CODE |
| LOW⚡ | tests/unit/test_sharing_types.py | 303 | data = ["user@example.com", 2, []] | CODE |
| LOW⚡ | tests/unit/test_sharing_types.py | 306 | assert user.email == "user@example.com" | CODE |
| LOW⚡ | tests/unit/test_sharing_types.py | 313 | data = ["user@example.com", 99, []] | CODE |
| LOW⚡ | tests/unit/test_sharing_types.py | 320 | data = ["user@example.com", {"permission": 3}, []] | CODE |
| LOW⚡ | tests/unit/test_sharing_types.py | 366 | data = ["user@example.com", 3, [], ["Just Name"]] | CODE |
| LOW⚡ | tests/unit/test_sharing_types.py | 503 | ["user@example.com", 3, [], ["Name", "https://avatar"]], # full | CODE |
| LOW⚡ | tests/unit/test_sharing_types.py | 504 | ["user@example.com", 2, []], # minimal (no user_info slot) | CODE |
| LOW⚡ | tests/unit/test_sharing_types.py | 505 | ["user@example.com", 3, [], ["Just Name"]], # partial user_info (no avatar) | CODE |
| LOW⚡ | tests/unit/test_sharing_types.py | 506 | ["user@example.com", 99, []], # unknown permission | CODE |
| LOW⚡ | tests/unit/test_sharing_types.py | 507 | ["user@example.com", {"k": 1}, []], # malformed (unhashable) permission | CODE |
| LOW⚡ | tests/unit/app/test_app_sharing.py | 129 | "user@example.com", | CODE |
| LOW⚡ | tests/unit/app/test_app_sharing.py | 139 | "user@example.com", | CODE |
| LOW⚡ | tests/unit/app/test_app_sharing.py | 159 | "user@example.com", | CODE |
| LOW⚡ | tests/unit/app/test_app_sharing.py | 166 | "full_nb_part", "user@example.com", SharePermission.VIEWER | CODE |
| LOW⚡ | tests/unit/app/test_app_sharing.py | 181 | await execute_share_remove_user(client, "nb_1", "user@example.com") | CODE |
| LOW⚡ | tests/unit/app/test_app_sharing.py | 183 | client.sharing.remove_user.assert_awaited_once_with("nb_1", "user@example.com") | CODE |
| LOW⚡ | tests/unit/cli/test_share.py | 176 | ["share", "add", "user@example.com", "-n", "nb_123"], | CODE |
| LOW⚡ | tests/unit/cli/test_share.py | 185 | "user@example.com", | CODE |
| LOW⚡ | tests/unit/cli/test_share.py | 206 | ["share", "add", "user@example.com", "-n", "nb_123", "-p", "editor"], | CODE |
| LOW⚡ | tests/unit/cli/test_share.py | 214 | "user@example.com", | CODE |
| LOW⚡ | tests/unit/cli/test_share.py | 242 | ["share", "remove", "user@example.com", "-n", "nb_123", "-y"], | CODE |
| LOW⚡ | tests/unit/cli/test_share.py | 248 | mock_client.sharing.remove_user.assert_called_once_with("nb_123", "user@example.com") | CODE |
| LOW⚡ | tests/unit/cli/test_share.py | 289 | ["share", "remove", "user@example.com", "-n", "nb_123", "--json"], | CODE |
| LOW⚡ | tests/unit/cli/test_share.py | 294 | assert '"removed_user": "user@example.com"' in result.output | CODE |
| LOW⚡ | tests/unit/cli/test_share.py | 314 | ["share", "remove", "user@example.com", "-n", "nb_123", "--json"], | CODE |
| LOW⚡ | tests/unit/cli/test_share.py | 319 | assert '"removed_user": "user@example.com"' in result.output | CODE |
| LOW⚡ | tests/unit/cli/test_share.py | 321 | mock_client.sharing.remove_user.assert_called_once_with("nb_123", "user@example.com") | CODE |
| LOW⚡ | tests/unit/cli/test_share.py | 487 | assert '"updated_user": "user@example.com"' in result.output | CODE |
| LOW⚡ | tests/unit/cli/test_share.py | 663 | ["share", "add", "user@example.com", "-n", "nb_123", "--json"], | CODE |
| LOW⚡ | tests/unit/cli/test_share.py | 668 | assert '"added_user": "user@example.com"' in result.output | CODE |
| LOW | tests/unit/cli/test_share.py | 265 | ["share", "remove", "user@example.com", "-n", "nb_123"], | CODE |
| LOW | tests/unit/cli/test_share.py | 447 | ["share", "update", "user@example.com", "-n", "nb_123", "-p", "editor"], | CODE |
| LOW | tests/unit/cli/test_share.py | 455 | "nb_123", "user@example.com", SharePermission.EDITOR | CODE |
| LOW | tests/unit/cli/test_share.py | 476 | "user@example.com", | CODE |
| LOW⚡ | tests/unit/cli/test_session_characterization.py | 200 | result = char_runner.invoke(cli, ["login", "--account", "user@example.com"]) | CODE |
| LOW | tests/unit/cli/test_auth_refresh_cold_start.py | 62 | "account": {"authuser": 0, "email": "user@example.com"}, | CODE |
| LOW | tests/integration/test_sharing_integration.py | 358 | ["user@example.com", 2, [], ["User", "https://avatar"]], # Now editor | CODE |
| LOW | tests/integration/test_sharing_integration.py | 369 | "user@example.com", | CODE |
| 14 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/unit/test_cookie_domain_split.py | 614 | # Step 2: storage_state → DomainCookieMap (used by AuthTokens). | COMMENT |
| LOW⚡ | tests/unit/test_cookie_domain_split.py | 620 | # Step 3: storage_state → httpx jar (used by downloads + refresh). | COMMENT |
| LOW⚡ | tests/unit/test_cookie_domain_split.py | 628 | # Step 4: the runtime gate itself accepts every YouTube variant. | COMMENT |
| LOW | tests/unit/test_cookie_domain_split.py | 603 | # Step 1: rookiepy → storage_state conversion must keep the YouTube | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 831 | # Step 0: register_file_source captures a baseline GET_NOTEBOOK | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 834 | # Step 1: Mock RPC registration response (o4cbdc) | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 844 | # Step 2: Mock upload session start response | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 854 | # Step 3: Mock upload finalize response | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 1048 | # Step 0: Baseline GET_NOTEBOOK for the register_file_source probe wrapper. | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 1050 | # Step 1: Mock RPC registration | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 1060 | # Step 2: Mock upload session start | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 1070 | # Step 3: Mock upload finalize | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 2844 | # Step 0: Baseline GET_NOTEBOOK for the register_file_source probe wrapper. | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 2846 | # Step 1: Successful RPC registration | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 2856 | # Step 2: Upload session response WITHOUT the required upload URL header | COMMENT |
| LOW⚡ | tests/e2e/test_research_import_verification.py | 42 | # Step 1: Start fast web research | COMMENT |
| LOW | tests/e2e/test_research_import_verification.py | 56 | # Step 2: Poll until complete | COMMENT |
| LOW | tests/e2e/test_research_import_verification.py | 74 | # Step 3: Get sources to import | COMMENT |
| LOW⚡ | tests/e2e/test_research_import_verification.py | 88 | # Step 4: Import sources. Use the verification-aware variant so an | COMMENT |
| LOW⚡ | tests/e2e/test_research_import_verification.py | 99 | # Step 5: Poll for imported sources to appear | COMMENT |
| LOW | tests/e2e/test_research_import_verification.py | 111 | # Step 6: Verify source count | COMMENT |
| LOW⚡ | tests/e2e/test_research.py | 196 | # Step 1: Start research | COMMENT |
| LOW | tests/e2e/test_research.py | 207 | # Step 2: Poll until complete | COMMENT |
| LOW | tests/e2e/test_research.py | 229 | # Step 3: Import sources (if any found) | COMMENT |
| LOW⚡ | docs/troubleshooting.md | 544 | # Step 1: Install bird (macOS/Linux) | COMMENT |
| LOW⚡ | docs/troubleshooting.md | 547 | # Step 2: Fetch X.com content as markdown | COMMENT |
| LOW⚡ | docs/troubleshooting.md | 550 | # Step 3: Add the local markdown file to NotebookLM | COMMENT |
| LOW | docs/rpc-development.md | 253 | ### Step 1: Capture | COMMENT |
| LOW | docs/rpc-development.md | 262 | ### Step 2: Decode | COMMENT |
| LOW | docs/rpc-development.md | 280 | ### Step 3: Implement | COMMENT |
| LOW | docs/rpc-development.md | 329 | ### Step 4: Test | COMMENT |
| LOW | docs/rpc-development.md | 363 | ### Step 5: Document | COMMENT |
| LOW | examples/video.py | 26 | # Step 1: Create a notebook with content | COMMENT |
| LOW⚡ | examples/video.py | 45 | # Step 2: Generate the video overview | COMMENT |
| LOW | examples/video.py | 80 | # Step 3: Wait for completion with status updates | COMMENT |
| LOW | examples/video.py | 95 | # Step 4: Download the video | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/unit/test_concurrency_refresh_race.py | 82 | # Test-side deadline for any single asyncio.Event in the race scaffolding. | COMMENT |
| MEDIUM | tests/unit/test_concurrency_refresh_race.py | 542 | # Build the same auth scaffold the unit conftest's ``make_core`` produces | COMMENT |
| MEDIUM⚡ | tests/unit/test_check_rpc_health.py | 587 | # The streamed-chat orchestration RPC has no obfuscated method ID to echo back | COMMENT |
| MEDIUM⚡ | tests/unit/test_drive_import.py | 442 | # DriveImportService — orchestration, cleanup, second defense | COMMENT |
| MEDIUM | tests/unit/test_audit_auth_patch_sites.py | 60 | # string-target patch — and it correctly trips both ADR-0007 guardrails | COMMENT |
| MEDIUM | tests/unit/test_rpc_health_coverage.py | 118 | # without re-introducing the whole skip-list scaffolding. | COMMENT |
| MEDIUM⚡ | tests/unit/test_chat_transport.py | 50 | # Test scaffolding | COMMENT |
| MEDIUM⚡ | tests/unit/app/test_app_source_clean.py | 236 | # run_source_clean — orchestration | COMMENT |
| MEDIUM | tests/_guardrails/_wire_contract.py | 52 | #: which lives in its own package rather than the ``orchestration.v1`` wire section. | COMMENT |
| MEDIUM | tests/cassettes/cli_notebook_create.yaml | 2158 | SEO 2026:The Ultimate Roadmap to AI Agent Visibility - Karan Powar\\\",[null,3905,[1773505574,851569000],[\\\"0f | CODE |
| MEDIUM | tests/cassettes/cli_notebook_create.yaml | 2159 | SEO 2026:The Ultimate Roadmap to AI Agent Visibility - Karan Powar\\\",[null,3905,[1773505614,213638000],[\\\"10 | CODE |
| MEDIUM | tests/cassettes/workflow_tracer_bullet.yaml | 2086 | SEO 2026:The Ultimate Roadmap to AI Agent Visibility - Karan Powar\\\",[null,3905,[1773505574,851569000],[\\\"0f | CODE |
| MEDIUM | tests/cassettes/workflow_tracer_bullet.yaml | 2087 | SEO 2026:The Ultimate Roadmap to AI Agent Visibility - Karan Powar\\\",[null,3905,[1773505614,213638000],[\\\"10 | CODE |
| MEDIUM | tests/cassettes/cli_notebook_list.yaml | 2158 | SEO 2026:The Ultimate Roadmap to AI Agent Visibility - Karan Powar\\\",[null,3905,[1773505574,851569000],[\\\"0f | CODE |
| MEDIUM | tests/cassettes/cli_notebook_list.yaml | 2159 | SEO 2026:The Ultimate Roadmap to AI Agent Visibility - Karan Powar\\\",[null,3905,[1773505614,213638000],[\\\"10 | CODE |
| MEDIUM | docs/architecture.md | 1179 | │ ├── login_cookie.py # Click-free login/cookie-import operations: request validation, browser-jar probing, a | CODE |
| MEDIUM | docs/architecture.md | 1194 | │ ├── source_clean.py # Click-free `source clean` core: junk-source classification + batched-deletion orchest | CODE |
| MEDIUM | docs/architecture.md | 1277 | ├── _chat.py # Abstract ChatAPI + shared locks/cache/ask/delete/save-note orchestration and lazy pri | CODE |
| MEDIUM | docs/development.md | 47 | ├── _chat.py # Backend-neutral ChatAPI orchestration | CODE |
| MEDIUM | docs/adr/0013-composable-session-capabilities.md | 263 | - **C-Z. AST-based delegate-surface regression guard** *(historical)* — introduced by PR [#885](https://github.com/teng- | CODE |
| MEDIUM | docs/adr/0013-composable-session-capabilities.md | 263 | - **C-Z. AST-based delegate-surface regression guard** *(historical)* — introduced by PR [#885](https://github.com/teng- | CODE |
| MEDIUM | docs/adr/0014-feature-local-runtime-adapters.md | 219 | ### Rule 4 — `Session` retains only orchestration plus the documented middleware-chain seams | COMMENT |
| MEDIUM | scripts/check_rpc_health.py | 2126 | # Probe the streamed-chat orchestration RPC. It is not an | COMMENT |
| MEDIUM | src/notebooklm/_web/params/notebooks.py | 74 | # what the backend RETURNS for each mode. ``5`` critique / ``6`` debate scaffolding / | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/unit/test_cookie_domain_split.py | 614 | # Step 2: storage_state → DomainCookieMap (used by AuthTokens). | COMMENT |
| LOW⚡ | tests/unit/test_cookie_domain_split.py | 620 | # Step 3: storage_state → httpx jar (used by downloads + refresh). | COMMENT |
| LOW⚡ | tests/unit/test_cookie_domain_split.py | 628 | # Step 4: the runtime gate itself accepts every YouTube variant. | COMMENT |
| LOW | tests/unit/test_cookie_domain_split.py | 603 | # Step 1: rookiepy → storage_state conversion must keep the YouTube | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 831 | # Step 0: register_file_source captures a baseline GET_NOTEBOOK | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 834 | # Step 1: Mock RPC registration response (o4cbdc) | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 844 | # Step 2: Mock upload session start response | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 854 | # Step 3: Mock upload finalize response | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 1048 | # Step 0: Baseline GET_NOTEBOOK for the register_file_source probe wrapper. | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 1050 | # Step 1: Mock RPC registration | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 1060 | # Step 2: Mock upload session start | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 1070 | # Step 3: Mock upload finalize | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 2844 | # Step 0: Baseline GET_NOTEBOOK for the register_file_source probe wrapper. | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 2846 | # Step 1: Successful RPC registration | COMMENT |
| LOW⚡ | tests/integration/test_sources_integration.py | 2856 | # Step 2: Upload session response WITHOUT the required upload URL header | COMMENT |
| LOW⚡ | tests/e2e/test_research_import_verification.py | 42 | # Step 1: Start fast web research | COMMENT |
| LOW | tests/e2e/test_research_import_verification.py | 56 | # Step 2: Poll until complete | COMMENT |
| LOW | tests/e2e/test_research_import_verification.py | 74 | # Step 3: Get sources to import | COMMENT |
| LOW⚡ | tests/e2e/test_research_import_verification.py | 88 | # Step 4: Import sources. Use the verification-aware variant so an | COMMENT |
| LOW⚡ | tests/e2e/test_research_import_verification.py | 99 | # Step 5: Poll for imported sources to appear | COMMENT |
| LOW | tests/e2e/test_research_import_verification.py | 111 | # Step 6: Verify source count | COMMENT |
| LOW⚡ | tests/e2e/test_research.py | 196 | # Step 1: Start research | COMMENT |
| LOW | tests/e2e/test_research.py | 207 | # Step 2: Poll until complete | COMMENT |
| LOW | tests/e2e/test_research.py | 229 | # Step 3: Import sources (if any found) | COMMENT |
| LOW | examples/video.py | 26 | # Step 1: Create a notebook with content | COMMENT |
| LOW⚡ | examples/video.py | 45 | # Step 2: Generate the video overview | COMMENT |
| LOW | examples/video.py | 80 | # Step 3: Wait for completion with status updates | COMMENT |
| LOW | examples/video.py | 95 | # Step 4: Download the video | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| CRITICAL⚡ | tests/unit/mcp/test_studio.py | 1363 | assert mock_client.artifacts.download_quiz.await_args.kwargs.get("output_format") == "markdown" | CODE |
| CRITICAL | tests/unit/cli/test_generate.py | 820 | mock_client.mind_maps.generate.await_args.kwargs.get("instructions") | CODE |
| CRITICAL | tests/unit/cli/test_resolver_characterization.py | 400 | passed_conv_id = mock_client.chat.ask.await_args.kwargs.get("conversation_id") | CODE |
| CRITICAL | tests/integration/test_vcr_example.py | 82 | # Simulate the request format from notebooklm._web.transport.executor.RpcExecutor.rpc_call() | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/unit/test_artifact_downloads.py | 759 | # Create the complex nested structure for data table. | COMMENT |
| MEDIUM⚡ | tests/unit/test_sources_upload.py | 971 | # Create a temp file | COMMENT |
| MEDIUM⚡ | tests/unit/cli/test_resolve.py | 333 | # Create a notebook with a short ID that we'll match exactly | COMMENT |
| MEDIUM | tests/unit/cli/test_source.py | 680 | # Create a temp file | COMMENT |
| MEDIUM | tests/integration/test_vcr_comprehensive.py | 810 | # Create a test file | COMMENT |
| MEDIUM | tests/integration/test_vcr_comprehensive.py | 900 | # Create a source to delete | COMMENT |
| MEDIUM | tests/integration/test_vcr_comprehensive.py | 938 | # Create a notebook to delete | COMMENT |
| MEDIUM | tests/integration/test_vcr_comprehensive.py | 970 | # Create a note to delete | COMMENT |
| MEDIUM | tests/e2e/test_artifacts.py | 246 | # Create a quiz artifact for deletion (different type than flashcards) | COMMENT |
| MEDIUM | tests/e2e/test_sources.py | 121 | # Create a source to delete | COMMENT |
| MEDIUM⚡ | examples/notes.py | 49 | # Create a new note with title and content | COMMENT |
| MEDIUM | examples/notes.py | 27 | # Create a notebook for our examples | COMMENT |
| MEDIUM | examples/chat.py | 23 | # Create a notebook with some content | COMMENT |
| MEDIUM | src/notebooklm/notebooklm_cli.py | 171 | notebooklm create "My Notes" # Create a notebook | STRING |
| MEDIUM | src/notebooklm/_auth/browser_capture.py | 1305 | # Create a TEMPORARY page we own for the navigation, and close ONLY | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | docs/python-api.md | 1212 | # Get AI-generated description (parsed with suggested topics) | COMMENT |
| HIGH | docs/python-api.md | 1321 | # Get AI-generated summary and keywords (returns a typed SourceGuide) | COMMENT |
| HIGH⚡ | examples/video.py | 51 | # - CINEMATIC: AI-generated documentary footage (Veo 3) | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/server/conftest.py | 67 | CODE | |
| MEDIUM | tests/server/test_app_lifecycle.py | 165 | CODE | |
| MEDIUM | tests/server/test_app_lifecycle.py | 217 | CODE | |
| MEDIUM | tests/server/test_app_lifecycle.py | 244 | CODE | |
| MEDIUM | tests/server/test_app_lifecycle.py | 269 | CODE | |
| MEDIUM | tests/server/test_sources.py | 90 | CODE | |
| MEDIUM | tests/server/test_meta.py | 205 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/_helpers/client_factory.py | 29 | CODE | |
| LOW | tests/unit/test_auth_profile_store_minted.py | 37 | CODE | |
| LOW | tests/unit/test_rpc_executor.py | 860 | CODE | |
| LOW | tests/unit/test_rpc_golden_payloads.py | 1579 | CODE | |
| LOW | tests/unit/app/test_app_research.py | 38 | CODE | |
| LOW | tests/unit/cli/test_playwright_login_render_contract.py | 166 | CODE | |
| LOW | tests/_guardrails/test_auth_storage_compatibility.py | 1812 | CODE | |
| LOW | src/notebooklm/_client_assembly.py | 93 | CODE | |
| LOW | src/notebooklm/client.py | 151 | CODE | |
| LOW | src/notebooklm/client.py | 626 | CODE | |
| LOW | src/notebooklm/exceptions.py | 413 | CODE | |
| LOW | src/notebooklm/_auth/refresh.py | 711 | CODE | |
| LOW | src/notebooklm/mcp/tools/studio.py | 313 | CODE | |
| LOW | src/notebooklm/mcp/tools/sources.py | 504 | CODE | |
| LOW | src/notebooklm/cli/resolve.py | 192 | CODE | |
| LOW | src/notebooklm/_web/transport/executor.py | 122 | CODE | |
| LOW | src/notebooklm/_runtime/init.py | 494 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/unit/test_windows_compatibility.py | 261 | # Check if UTF-8 mode is active (either via flag or env var) | COMMENT |
| LOW | tests/unit/test_auth_storage.py | 147 | # Set NOTEBOOKLM_HOME to tmp_path and create a file there | COMMENT |
| LOW⚡ | tests/e2e/test_chat.py | 68 | # Check if any references have cited_text | COMMENT |
| LOW | scripts/check_rpc_health.py | 859 | # Check if error response still contains our expected ID | COMMENT |
| LOW | scripts/check_rpc_health.py | 876 | # Check if expected ID is in response | COMMENT |
| LOW | .github/workflows/nightly.yml | 56 | # Check if it's main or a release branch | COMMENT |
| LOW | src/notebooklm/_auth/cookie_policy.py | 890 | # Check if it's a valid canonical Google domain (base or regional). | COMMENT |
| LOW | src/notebooklm/_app/chat.py | 121 | # Check if the user switched notebooks via the --notebook flag. Only read | COMMENT |