Skip to content

feat(workstream-c): add cheatsheet categorizer and grouping#934

Open
shreeshtripurwarcomp23-coder wants to merge 2 commits into
OWASP:mainfrom
shreeshtripurwarcomp23-coder:workstream-c-clean
Open

feat(workstream-c): add cheatsheet categorizer and grouping#934
shreeshtripurwarcomp23-coder wants to merge 2 commits into
OWASP:mainfrom
shreeshtripurwarcomp23-coder:workstream-c-clean

Conversation

@shreeshtripurwarcomp23-coder

@shreeshtripurwarcomp23-coder shreeshtripurwarcomp23-coder commented Jun 15, 2026

Copy link
Copy Markdown
Contributor
  • Implement categorize_cheatsheet() with 29-label controlled taxonomy
  • Implement group_cheatsheets() with stable sha256-based group IDs
  • Deterministic keyword/rule baseline, no LLM dependency
  • LLM-optional path with safe fallback on failure
  • Validate all CheatsheetRecord fields in post_init
  • 50 tests covering all acceptance criteria from RFC Issue C

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 80f7c9ad-5a79-43e6-9435-562acf79a594

📥 Commits

Reviewing files that changed from the base of the PR and between 12e041f and 2592552.

📒 Files selected for processing (1)
  • application/utils/external_project_parsers/parsers/cheatsheet_categorizer.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • application/utils/external_project_parsers/parsers/cheatsheet_categorizer.py

Summary by CodeRabbit

  • New Features

    • Added cheatsheet categorization with a fixed set of labels and a fallback “uncategorized” label.
    • Added optional grouping of cheatsheets by category labels, with stable group IDs and consistent ordering.
    • Enabled an optional AI-assisted categorization path that falls back safely when results are invalid or unavailable.
  • Tests

    • Added broad test coverage for categorization, fallback behavior, grouping, and label validation to improve reliability.

Walkthrough

Adds a cheatsheet categorizer module with controlled taxonomy labels, deterministic and LLM-assisted categorization, stable grouping by label set, and a new unittest suite covering taxonomy integrity, categorization behavior, validation, and grouping.

Changes

Cheatsheet Categorization System

Layer / File(s) Summary
Taxonomy and group contract
application/utils/external_project_parsers/parsers/cheatsheet_categorizer.py, application/tests/test_cheatsheet_categorizer.py
TAXONOMY, UNCATEGORIZED, and CheatsheetGroup.make_group_id are defined; tests verify taxonomy uniqueness, lowercase labels, minimum size, and stable 12-character lowercase hex group IDs.
Categorization helpers and validation
application/utils/external_project_parsers/parsers/cheatsheet_categorizer.py, application/tests/test_cheatsheet_categorizer.py
Search-text building, deterministic keyword categorization, LLM label validation, and categorize_cheatsheet with fallback behavior are implemented; tests cover deterministic mappings, uncategorized fallback, LLM success and failure paths, label validation, and helper outputs.
Grouping by label set
application/utils/external_project_parsers/parsers/cheatsheet_categorizer.py, application/tests/test_cheatsheet_categorizer.py
group_cheatsheets buckets records by label-set-derived group ID and returns sorted groups; tests cover co-grouping, separation, uncategorized grouping, stable IDs, full membership coverage, empty input, and direct module execution.

Estimated code review effort: 3 (Moderate) | ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.42% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding cheatsheet categorization and grouping.
Description check ✅ Passed The description matches the changeset by describing categorization, grouping, fallback behavior, and tests.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@application/tests/test_cheatsheet_categorizer.py`:
- Around line 42-48: The _make_record helper function creates CheatsheetRecord
instances with an empty summary string, but CheatsheetRecord.__post_init__
enforces that summary must be non-empty, causing construction to fail before
test assertions run. Replace the empty string assignment `summary=""` in the
_make_record function with a minimal non-empty placeholder value (such as a
single space, period, or descriptive placeholder text like "Test summary") to
satisfy the validation requirement.

In
`@application/utils/external_project_parsers/parsers/cheatsheet_categorizer.py`:
- Around line 194-210: The __post_init__ method in CheatsheetRecord currently
validates only string-typed fields but does not validate the element types of
list-typed fields (headings and category_hints). This causes runtime crashes
when non-string items reach code expecting to call " ".join() on these fields.
Add validation in __post_init__ to ensure that headings and category_hints are
lists containing only string elements, raising a ValueError with a clear message
if any element is not a string, so that parser input validation fails fast at
construction time rather than later during string joining operations.
- Around line 366-381: The `_validate_labels` function currently allows
`uncategorized` to be returned alongside other valid labels, which violates the
sentinel semantics where `uncategorized` should only be returned when it is the
sole valid label. Modify the function to add logic after building the deduped
list: if `uncategorized` (or the appropriate constant reference from TAXONOMY)
is present in the result AND there are other valid labels alongside it, remove
the `uncategorized` entry from the returned list. This ensures that
`uncategorized` is only returned when no other categories match, preserving its
role as a fallback indicator and preventing inconsistent downstream grouping and
UX.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: ca9bd7d2-9738-4eb1-9bf6-5c1b32faf0db

📥 Commits

Reviewing files that changed from the base of the PR and between e853cd3 and f91b995.

📒 Files selected for processing (2)
  • application/tests/test_cheatsheet_categorizer.py
  • application/utils/external_project_parsers/parsers/cheatsheet_categorizer.py

Comment thread application/tests/test_cheatsheet_categorizer.py
Comment thread application/utils/external_project_parsers/parsers/cheatsheet_categorizer.py Outdated
Comment thread application/utils/external_project_parsers/parsers/cheatsheet_categorizer.py Outdated
@shreeshtripurwarcomp23-coder shreeshtripurwarcomp23-coder marked this pull request as draft June 15, 2026 05:06
@shreeshtripurwarcomp23-coder shreeshtripurwarcomp23-coder marked this pull request as ready for review June 15, 2026 05:10
@shreeshtripurwarcomp23-coder shreeshtripurwarcomp23-coder marked this pull request as draft June 15, 2026 05:11
Implements Workstream C from the RFC: Autonomous LLM Pipeline for
OWASP Cheat Sheet to CRE Mapping.

- categorize_cheatsheet(record) with 29-label controlled taxonomy
- group_cheatsheets(records) with stable sha256-based group IDs
- Deterministic keyword/rule baseline, no LLM dependency required
- LLM-optional path with safe fallback on any failure
- UNCATEGORIZED sentinel stripped when real labels are present
- Uses CheatsheetRecord from application.defs.cheatsheet_defs (Workstream B, PR OWASP#921)
- 50 tests covering all acceptance criteria from RFC Issue C
@shreeshtripurwarcomp23-coder shreeshtripurwarcomp23-coder marked this pull request as ready for review June 30, 2026 07:52

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
application/utils/external_project_parsers/parsers/cheatsheet_categorizer.py (1)

328-345: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Return validated LLM labels in canonical order.

categorize_cheatsheet() documents a sorted result, but _validate_labels() preserves the LLM’s order. That makes the LLM path non-deterministic for the same label set and breaks the public contract.

Suggested fix
     real = [lbl for lbl in deduped if lbl != UNCATEGORIZED]
-    return real if real else deduped
+    return sorted(real if real else deduped)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@application/utils/external_project_parsers/parsers/cheatsheet_categorizer.py`
around lines 328 - 345, The `_validate_labels` helper in
`cheatsheet_categorizer.py` preserves the LLM’s input order, which conflicts
with the documented sorted output from `categorize_cheatsheet()`. Update
`_validate_labels()` to return approved labels in the canonical `TAXONOMY` order
after filtering and deduping, while still stripping `UNCATEGORIZED` when real
labels exist. Keep the fix localized to `_validate_labels` so the LLM path
matches the deterministic contract everywhere it is used.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@application/utils/external_project_parsers/parsers/cheatsheet_categorizer.py`:
- Around line 280-291: `group_cheatsheets()` is currently keying the `bucket` by
the truncated `CheatsheetGroup.make_group_id(labels)` value, which can merge
distinct label sets on collision; change the grouping map to use the canonical
sorted unique labels as the key while still deriving `group_id` from
`CheatsheetGroup.make_group_id` for the created `CheatsheetGroup`. Update the
`bucket` population logic in `group_cheatsheets()` so groups are formed strictly
by label set identity, and keep `CheatsheetGroup(group_id=...,
labels=sorted(labels))` as the stored object.

---

Duplicate comments:
In
`@application/utils/external_project_parsers/parsers/cheatsheet_categorizer.py`:
- Around line 328-345: The `_validate_labels` helper in
`cheatsheet_categorizer.py` preserves the LLM’s input order, which conflicts
with the documented sorted output from `categorize_cheatsheet()`. Update
`_validate_labels()` to return approved labels in the canonical `TAXONOMY` order
after filtering and deduping, while still stripping `UNCATEGORIZED` when real
labels exist. Keep the fix localized to `_validate_labels` so the LLM path
matches the deterministic contract everywhere it is used.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: a607e96a-00c8-4fb8-9d70-f8a4dd5baeaa

📥 Commits

Reviewing files that changed from the base of the PR and between f8472d4 and 12e041f.

📒 Files selected for processing (2)
  • application/tests/test_cheatsheet_categorizer.py
  • application/utils/external_project_parsers/parsers/cheatsheet_categorizer.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • application/tests/test_cheatsheet_categorizer.py

Comment thread application/utils/external_project_parsers/parsers/cheatsheet_categorizer.py Outdated
…categorizer.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Shreesh Tripurwar <shreesh.tripurwar_comp23@pccoer.in>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant