Open Source Introductory Systems Programming Textbook for the University of Illinois
This report summarizes scanner evidence for cs341-illinois/coursebook, a TeX project with 3,817 GitHub stars. SynthScan examined 6,404 lines of code across 47 source files, recording 126 pattern matches distributed across 8 syntactic categories. The legacy adjusted pattern signal is 24.4 (Elevated 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.
Can maintainers explain intent, assumptions, and trade-offs? 107 finding(s).
Are imports declared and package/API names verified? 6 finding(s).
Are wrappers, guards, and repeated structures necessary? 91 finding(s).
Which changes need focused human review? 126 finding(s).
Run additional scans to build a history of the legacy pattern signal. Score changes are not a measure of AI adoption or code quality.
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 126 distinct pattern matches across 8 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⚡ | _scripts/test_verapdf_summary.py | 70 | def test_failing_figure_rule_fails_under_strict(self): | CODE |
| LOW⚡ | _scripts/test_verapdf_summary.py | 74 | def test_failing_figure_rule_only_reports_without_strict(self): | CODE |
| LOW⚡ | _scripts/test_verapdf_summary.py | 80 | def test_non_figure_failure_passes_the_figure_gate(self): | CODE |
| LOW⚡ | _scripts/test_verapdf_summary.py | 86 | def test_unparseable_pdf_fails(self): | CODE |
| LOW⚡ | _scripts/test_verapdf_summary.py | 90 | def test_unparseable_pdf_fails_even_beside_a_good_one(self): | CODE |
| LOW | _scripts/test_verapdf_summary.py | 109 | def test_null_failed_checks_is_tolerated(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 99 | def test_alt_key_wins_over_caption(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 109 | def test_caption_used_when_no_alt_key(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 119 | def test_no_alt_no_caption_raises(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 127 | def test_whitespace_or_placeholder_alt_raises(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 135 | def test_placeholder_alt_falls_back_to_caption(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 140 | def test_latex_escapes_rendered_not_leaked(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 153 | def test_multiline_alt_collapses_whitespace(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 159 | def test_epub_eps_becomes_png(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 163 | def test_wiki_eps_becomes_absolute_png(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 200 | def test_capital_c_listing_is_c_not_objectivec(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 207 | def test_wiki_citation_link_keeps_its_text(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 216 | def test_wiki_ordinary_link_unchanged(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 250 | def test_filter_failure_fails_pandoc(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 257 | def test_empty_date_filled_from_metadata_file(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 267 | def test_missing_date_filled_from_metadata_file(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 272 | def test_empty_date_removed_when_metadata_file_sets_none(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 336 | def test_normalize_smart_typography(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 340 | def test_invalid_latex_alt_raises_cleanly(self): | CODE |
| LOW⚡ | _scripts/test_pandoc_filters.py | 350 | def test_expected_matches_filter_rendering(self): | CODE |
| LOW | _scripts/test_pandoc_filters.py | 176 | def test_figure_becomes_image_and_caption_paragraphs(self): | CODE |
| LOW | _scripts/test_pandoc_filters.py | 185 | def test_gfm_output_is_markdown_not_html(self): | CODE |
| LOW | _scripts/test_pandoc_filters.py | 236 | def test_epub_filter_html_alt(self): | CODE |
| LOW | _scripts/test_pandoc_filters.py | 300 | def test_cover_missing_raises(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 61 | def test_nested_braces_in_alt(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 69 | def test_commented_out_include_is_skipped(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 78 | def test_comment_environment_is_skipped(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 133 | def test_generic_alt_word_warns(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 140 | def test_unsafe_macro_in_alt_warns(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 147 | def test_safe_escapes_do_not_warn(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 155 | def test_escapes_that_leak_into_pdf_alt_warn(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 178 | def test_escaped_dollar_is_not_math(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 184 | def test_allowlisted_title_duck_is_excluded(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 194 | def test_non_allowlisted_title_image_still_checked(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 202 | def test_book_order_used_when_order_yaml_present(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 209 | def test_no_figure_environment_gives_null_caption(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 216 | def test_extra_whitespace_around_equals(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 224 | def test_duplicate_key_last_one_wins(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 231 | def test_starred_includegraphics_is_scanned(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 239 | def test_caption_with_short_title_is_found(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 249 | def test_caption_with_space_before_brace_is_found(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 259 | def test_two_image_caption_pairs_in_one_figure(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 323 | def test_missing_path_group_is_reported(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 329 | def test_unterminated_path_group_is_reported(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 335 | def test_title_macro_hacks_are_not_malformed(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 401 | def test_unreachable_figure_is_reported(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 410 | def test_figure_reached_through_input_chain_is_reachable(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 418 | def test_no_order_yaml_skips_reachability(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 455 | def test_fails_on_missing_alt(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 461 | def test_fails_on_malformed_include(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 467 | def test_fails_on_unreachable_figure(self): | CODE |
| LOW⚡ | _scripts/test_alt_lint.py | 475 | def test_malformed_include_absent_from_json(self): | CODE |
| LOW | _scripts/test_alt_lint.py | 89 | def test_escaped_percent_is_not_a_comment(self): | CODE |
| LOW | _scripts/test_alt_lint.py | 115 | def test_whitespace_only_alt_fails(self): | CODE |
| LOW | _scripts/test_alt_lint.py | 122 | def test_alt_equal_to_caption_warns(self): | CODE |
| 18 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | _scripts/alt_lint.py | 56 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | _scripts/alt_lint.py | 58 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | _scripts/alt_lint.py | 113 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | _scripts/alt_lint.py | 115 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | _scripts/alt_lint.py | 295 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | _scripts/alt_lint.py | 297 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | _scripts/alt_lint.py | 669 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | _scripts/alt_lint.py | 671 | # --------------------------------------------------------------------------- | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | _scripts/epub_cover_alt.py | 57 | CODE | |
| LOW | _scripts/epub_check.py | 151 | CODE | |
| LOW | _scripts/epub_check.py | 65 | CODE | |
| LOW | _scripts/check_pdf_tags.py | 121 | CODE | |
| LOW | _scripts/check_pdf_tags.py | 155 | CODE | |
| LOW | _scripts/check_pdf_tags.py | 336 | CODE | |
| LOW | _scripts/test_pandoc_filters.py | 119 | CODE | |
| LOW | _scripts/test_pandoc_filters.py | 127 | CODE | |
| LOW | _scripts/alt_check_common.py | 37 | CODE | |
| LOW | _scripts/compare_pandoc_ast.py | 90 | CODE | |
| LOW | _scripts/wiki_check.py | 92 | CODE | |
| LOW | _scripts/alt_lint.py | 184 | CODE | |
| LOW | _scripts/alt_lint.py | 231 | CODE | |
| LOW | _scripts/alt_lint.py | 484 | CODE | |
| LOW | _scripts/alt_lint.py | 544 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | _scripts/install.sh | 1 | #!/bin/bash | COMMENT |
| LOW | _scripts/install.sh | 61 | # (texlive/texlive, see .github/workflows/build.yaml), not with | COMMENT |
| LOW | _scripts/compare_pdf_text.sh | 1 | #!/bin/bash | COMMENT |
| LOW | _scripts/check_tex_logs.sh | 1 | #!/bin/bash | COMMENT |
| LOW | _scripts/site_deploy.sh | 1 | #!/bin/bash | COMMENT |
| LOW | _scripts/check_verapdf.sh | 1 | #!/bin/bash | COMMENT |
| LOW | _scripts/epub_metadata.yaml | 1 | # EPUB accessibility metadata (issue #238, Part A step 6). | COMMENT |
| LOW | _scripts/epub_metadata.yaml | 21 | # empty date, which it writes as <dc:date></dc:date> and EPUBCheck rejects | COMMENT |
| LOW | _scripts/epub_metadata.yaml | 41 | # content figure now has alt text (alt_lint.py enforces this). But the | COMMENT |
| LOW | _scripts/alt_lint.py | 61 | # scanned as such: | COMMENT |
| LOW | .github/workflows/deploy.yaml | 81 | # instead, which needs no secret to rotate and survives renames. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | _scripts/pandoc_header_filter.py | 22 | CODE | |
| LOW | _scripts/test_pandoc_filters.py | 16 | CODE | |
| LOW | _scripts/pandoc_epub_filter.py | 19 | CODE | |
| LOW | _scripts/alt_check_common.py | 14 | CODE | |
| LOW | _scripts/gen_wiki.py | 9 | CODE | |
| LOW | _scripts/alt_lint.py | 47 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | _scripts/push_to_wiki.sh | 8 | # Create a temp directory, so we don't get raced by the filesystem | COMMENT |
| MEDIUM | _scripts/gen_wiki.py | 205 | # Create a standalone document, all the tex chapters are chapters | STRING |
| MEDIUM | _scripts/gen_wiki.py | 226 | '-s', # Create a standalone wiki page not a fragment | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | _scripts/check_pdf_tags.py | 75 | except Exception: # noqa: BLE001 | CODE |
| LOW | _scripts/check_pdf_tags.py | 166 | except Exception: # noqa: BLE001 | CODE |
| LOW | _scripts/check_pdf_tags.py | 228 | except Exception as e: # noqa: BLE001 | CODE |
| LOW | _scripts/alt_text.py | 51 | except Exception as e: # e.g. unbalanced braces: name the culprit | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | _scripts/alt_check_common.py | 136 | __all__ = ['latex_to_text', 'normalize', 'expected_alt', 'png_path', | CODE |