Fast and Accurate Code Search for Agents. Uses 99% fewer tokens than grep+read
This report summarizes scanner evidence for MinishLab/semble, a Python project with 6,338 GitHub stars. SynthScan examined 112,250 lines of code across 185 source files, recording 230 pattern matches distributed across 10 syntactic categories. The legacy adjusted pattern signal is 2.6 (Low pattern signal); it is not an authorship estimate.
Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.
Use each vector to guide manual verification of the underlying findings.
Payload schema: 1.0.0 · Engine: 2.0.0 · Scoring: heuristic-density-v1 · Scan date: 2026-10-31.
Can maintainers explain intent, assumptions, and trade-offs? 170 finding(s).
Are imports declared and package/API names verified? 27 finding(s).
Are wrappers, guards, and repeated structures necessary? 192 finding(s).
Which changes need focused human review? 230 finding(s).
This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.
Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.
This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.
The scanner identified 230 distinct pattern matches across 10 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. 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 configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_chunker.py | 29 | def test_chunk_source_empty_string() -> None: | CODE |
| LOW | tests/test_chunker.py | 34 | def test_chunk_source_language() -> None: | CODE |
| LOW⚡ | tests/test_chunker.py | 49 | def test_chunk_source_line_numbers_match_content(language: str | None) -> None: | CODE |
| LOW⚡ | tests/test_chunker.py | 59 | def test_core_chunk_empty_input() -> None: | CODE |
| LOW⚡ | tests/test_chunker.py | 64 | def test_core_chunk_lines_merges_small_lines() -> None: | CODE |
| LOW | tests/test_chunker.py | 75 | def test_core_chunk_recursive_split_and_break() -> None: | CODE |
| LOW | tests/test_chunker.py | 89 | def test_core_chunk_leaf_node_exceeds_desired_length() -> None: | CODE |
| LOW | tests/test_chunker.py | 144 | def test_unsupported_platform_error() -> None: | CODE |
| LOW | tests/test_stats.py | 40 | def test_no_color_disables_color_when_empty(monkeypatch: pytest.MonkeyPatch) -> None: | CODE |
| LOW | tests/test_stats.py | 54 | def test_savings_output_token_suffixes(tmp_path: Path, file_chars: int, expected: str) -> None: | CODE |
| LOW | tests/test_stats.py | 63 | def test_savings_do_not_subtract_unknown_baselines(tmp_path: Path) -> None: | CODE |
| LOW⚡ | tests/test_stats.py | 84 | def test_savings_tolerates_bad_json(tmp_path: Path) -> None: | CODE |
| LOW⚡ | tests/test_stats.py | 91 | def test_savings_cli_dispatch( | CODE |
| LOW⚡ | tests/test_stats.py | 101 | def test_savings_buckets_exclude_old_records(tmp_path: Path) -> None: | CODE |
| LOW⚡ | tests/test_installer.py | 81 | def test_merge_mcp_creates_fresh_file(claude_agent): | CODE |
| LOW⚡ | tests/test_installer.py | 88 | def test_merge_mcp_preserves_comments_and_other_entries(claude_agent): | CODE |
| LOW⚡ | tests/test_installer.py | 98 | def test_merge_mcp_adds_section_when_absent(claude_agent): | CODE |
| LOW⚡ | tests/test_installer.py | 197 | def test_mcp_skipped_when_grammar_unavailable(claude_agent, monkeypatch): | CODE |
| LOW⚡ | tests/test_installer.py | 207 | def test_merge_mcp_reparse_guard(claude_agent, monkeypatch): | CODE |
| LOW⚡ | tests/test_installer.py | 214 | def test_remove_mcp_preserves_comments(claude_agent): | CODE |
| LOW⚡ | tests/test_installer.py | 424 | def test_run_skill_and_instructions_keeps_full_block(run_setup, claude_agent): | CODE |
| LOW⚡ | tests/test_installer.py | 433 | def test_apply_subagent_bundled_file_for_every_agent(tmp_path, agent): | CODE |
| LOW⚡ | tests/test_installer.py | 442 | def test_apply_subagent_codex_toml(tmp_path): | CODE |
| LOW⚡ | tests/test_installer.py | 465 | def test_semble_pin_matches_installed_version(monkeypatch): | CODE |
| LOW⚡ | tests/test_installer.py | 471 | def test_semble_pin_uses_local_path_for_editable_install(monkeypatch, tmp_path): | CODE |
| LOW⚡ | tests/test_installer.py | 480 | def test_semble_pin_uses_git_commit_for_non_editable_git_install(monkeypatch): | CODE |
| LOW⚡ | tests/test_installer.py | 513 | def test_mcp_configs_pin_version(config): | CODE |
| LOW⚡ | tests/test_installer.py | 518 | def test_instructions_pin_version(): | CODE |
| LOW⚡ | tests/test_installer.py | 524 | def test_codex_mcp_block_pins_version(): | CODE |
| LOW⚡ | tests/test_installer.py | 529 | def test_apply_subagent_pins_version(tmp_path): | CODE |
| LOW | tests/test_installer.py | 113 | def test_merge_mcp_into_empty_object_produces_valid_json(claude_agent, initial): | CODE |
| LOW | tests/test_installer.py | 124 | def test_merge_mcp_replaces_stale_entry(claude_agent, stale): | CODE |
| LOW | tests/test_installer.py | 132 | def test_merge_mcp_idempotent(claude_agent, initial, first): | CODE |
| LOW | tests/test_installer.py | 154 | def test_merge_and_remove_json_member_nested_section_key(tmp_path): | CODE |
| LOW | tests/test_installer.py | 186 | def test_merge_mcp_writes_under_agent_key(tmp_path, agent_id, key): | CODE |
| LOW | tests/test_installer.py | 240 | def test_remove_mcp_no_trailing_comma(claude_agent, initial): | CODE |
| LOW | tests/test_installer.py | 247 | def test_remove_mcp_reparse_guard(claude_agent, monkeypatch): | CODE |
| LOW | tests/test_installer.py | 258 | def test_remove_mcp_not_found(claude_agent, setup): | CODE |
| LOW | tests/test_installer.py | 265 | def test_codex_toml_merge_and_remove(tmp_path): | CODE |
| LOW | tests/test_installer.py | 282 | def test_codex_toml_merge_replaces_section_with_inline_comment(tmp_path): | CODE |
| LOW | tests/test_installer.py | 295 | def test_remove_toml_not_found(tmp_path, setup, expected): | CODE |
| LOW | tests/test_installer.py | 303 | def test_remove_toml_deletes_file_when_only_semble(tmp_path): | CODE |
| LOW | tests/test_installer.py | 324 | def test_remove_toml_strips_sub_tables(tmp_path, content): | CODE |
| LOW | tests/test_installer.py | 381 | def test_apply_instructions_none(): | CODE |
| LOW | tests/test_installer.py | 494 | def test_semble_pin_falls_back_when_distribution_lookup_fails(monkeypatch): | CODE |
| LOW | tests/test_installer.py | 552 | def test_is_detected_true_when_config_dir_stat_denied(monkeypatch, tmp_path): | CODE |
| LOW | tests/test_installer.py | 563 | def test_is_detected_false_on_other_os_error(monkeypatch, tmp_path): | CODE |
| LOW | tests/test_installer.py | 637 | def test_replace_or_append_marked(tmp_path, initial, block, expected, present, absent): | CODE |
| LOW | tests/test_installer.py | 648 | def test_remove_marked_strips_block_and_deletes_empty_file(tmp_path): | CODE |
| LOW | tests/test_installer.py | 664 | def test_remove_marked_not_found(tmp_path, initial): | CODE |
| LOW | tests/test_installer.py | 673 | def test_cli_dispatches_to_installer_run(monkeypatch, command): | CODE |
| LOW | tests/test_installer.py | 685 | def test_cli_unattended_flags(monkeypatch, command): | CODE |
| LOW | tests/test_installer.py | 701 | def test_cli_type_without_agent_errors(monkeypatch, capsys): | CODE |
| LOW | tests/test_installer.py | 711 | def test_run_unattended_skips_prompts(run_setup, monkeypatch, claude_agent): | CODE |
| LOW | tests/test_installer.py | 729 | def test_run_unattended_empty_selection_exits(run_setup, agent_ids, integration_ids): | CODE |
| LOW | tests/test_search.py | 118 | def test_search_source_labels( | CODE |
| LOW | tests/test_search.py | 164 | def test_load_model_unreachable_hub_raises_helpful_error() -> None: | CODE |
| LOW⚡ | tests/test_search.py | 183 | def test_load_model_hides_only_unauthenticated_warning( | CODE |
| LOW⚡ | tests/test_search.py | 193 | def test_embed_chunks_empty_returns_empty_array(mock_model: Any) -> None: | CODE |
| LOW⚡ | tests/test_search.py | 200 | def test_selectable_basic_backend_rejects_k_below_one( | CODE |
| 99 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | benchmarks/baselines/codebase_memory.py | 0 | return (mean ndcg@10, p50 latency ms) for a list of tasks. | STRING |
| HIGH | benchmarks/baselines/ripgrep.py | 0 | return (mean ndcg@10, p50 latency ms) for a list of tasks. | STRING |
| HIGH | benchmarks/baselines/colgrep.py | 0 | return (mean ndcg@10, p50 latency ms) for a list of tasks. | STRING |
| HIGH | benchmarks/baselines/zvecgrep.py | 0 | return (mean ndcg@10, p50 latency ms) for a list of tasks. | STRING |
| HIGH | benchmarks/baselines/cs.py | 0 | return (mean ndcg@10, p50 latency ms) for a list of tasks. | STRING |
| HIGH | benchmarks/baselines/ck.py | 0 | return (mean ndcg@10, p50 latency ms) for a list of tasks. | STRING |
| HIGH | benchmarks/baselines/probe.py | 0 | return (mean ndcg@10, p50 latency ms) for a list of tasks. | STRING |
| HIGH | benchmarks/baselines/grepai.py | 0 | return (mean ndcg@10, p50 latency ms) for a list of tasks. | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_cache.py | 1 | CODE | |
| LOW | src/semble/cache.py | 24 | CODE | |
| LOW | src/semble/__init__.py | 1 | CODE | |
| LOW | src/semble/__init__.py | 2 | CODE | |
| LOW | src/semble/__init__.py | 2 | CODE | |
| LOW | src/semble/__init__.py | 2 | CODE | |
| LOW | src/semble/__init__.py | 2 | CODE | |
| LOW | src/semble/__init__.py | 2 | CODE | |
| LOW | src/semble/__init__.py | 3 | CODE | |
| LOW | src/semble/types.py | 1 | CODE | |
| LOW | src/semble/mcp.py | 1 | CODE | |
| LOW | src/semble/utils.py | 1 | CODE | |
| LOW | src/semble/ranking/__init__.py | 1 | CODE | |
| LOW | src/semble/ranking/__init__.py | 1 | CODE | |
| LOW | src/semble/ranking/__init__.py | 1 | CODE | |
| LOW | src/semble/ranking/__init__.py | 2 | CODE | |
| LOW | src/semble/chunking/__init__.py | 1 | CODE | |
| LOW | src/semble/chunking/core.py | 1 | CODE | |
| LOW | src/semble/index/bm25.py | 1 | CODE | |
| LOW | src/semble/index/index.py | 1 | CODE | |
| LOW | src/semble/index/dense.py | 1 | CODE | |
| LOW | src/semble/index/__init__.py | 1 | CODE | |
| LOW | src/semble/index/types.py | 1 | CODE | |
| LOW | src/semble/installer/config.py | 1 | CODE | |
| LOW | src/semble/installer/__init__.py | 1 | CODE | |
| LOW | src/semble/installer/agents.py | 1 | CODE | |
| LOW | src/semble/installer/installer.py | 1 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | benchmarks/baselines/grepai.py | 111 | except (ProcessLookupError, PermissionError): | CODE |
| HIGH | src/semble/stats.py | 93 | except OSError: | CODE |
| HIGH | src/semble/index/index.py | 113 | except OSError: | CODE |
| HIGH | src/semble/installer/agents.py | 61 | except Exception: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/semble/cache.py | 21 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/semble/__init__.py | 5 | __all__ = [ | CODE |
| LOW | src/semble/mcp.py | 23 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/semble/stats.py | 18 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/semble/ranking/__init__.py | 4 | __all__ = ["apply_query_boost", "boost_multi_chunk_files", "rerank_topk", "resolve_alpha"] | CODE |
| LOW | src/semble/chunking/chunking.py | 8 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/semble/chunking/__init__.py | 3 | __all__ = ["chunk_source"] | CODE |
| LOW | src/semble/index/bm25.py | 49 | def set_doc_order(self, chunk_ids: list[str]) -> None: | CODE |
| LOW | src/semble/index/create.py | 37 | logger = logging.getLogger(__name__) | CODE |
| LOW | src/semble/index/__init__.py | 3 | __all__ = ["SembleIndex"] | CODE |
| LOW | src/semble/installer/__init__.py | 3 | __all__ = ["run"] | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | src/semble/cli.py | 64 | except Exception as e: | CODE |
| MEDIUM | src/semble/cli.py | 65 | print(f"Error saving index: {e}", file=sys.stderr) | CODE |
| LOW | src/semble/mcp.py | 46 | except Exception as exc: | CODE |
| LOW | src/semble/mcp.py | 187 | except Exception as exc: | CODE |
| LOW | src/semble/mcp.py | 250 | except Exception: | CODE |
| LOW | src/semble/mcp.py | 325 | except Exception: | CODE |
| LOW | src/semble/chunking/core.py | 33 | except Exception: | CODE |
| LOW | src/semble/installer/config.py | 24 | except Exception: | CODE |
| LOW | src/semble/installer/agents.py | 61 | except Exception: | CODE |
| LOW | src/semble/installer/installer.py | 104 | except Exception: | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_cli.py | 340 | CODE | |
| LOW | tests/index/test_create.py | 166 | CODE | |
| LOW | tests/index/test_index.py | 55 | CODE | |
| LOW | benchmarks/baselines/grepai.py | 49 | CODE | |
| LOW | src/semble/cli.py | 292 | CODE | |
| LOW | src/semble/stats.py | 57 | CODE | |
| LOW | src/semble/index/create.py | 154 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/test_cli.py | 289 | # Create the files that PersistencePath.non_existing checks | COMMENT |
| MEDIUM | scripts/demo/record.sh | 15 | # Create an isolated $HOME with agent config dirs so `semble install` detects some agents. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | benchmarks/README.md | 136 | **How the benchmark was built**: queries and ground-truth relevance labels are generated by Claude Sonnet 4.6. The same | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_search.py | 92 | shared_content = "def helper():\n pass" | CODE |