week_1-3: Module C — real 319-row golden dataset from OpenCRE DB#4
Open
PRAteek-singHWY wants to merge 2 commits into
Open
week_1-3: Module C — real 319-row golden dataset from OpenCRE DB#4PRAteek-singHWY wants to merge 2 commits into
PRAteek-singHWY wants to merge 2 commits into
Conversation
Replaces the 10-row seed fixture with the real DB-derived golden set, sized
to clear the master-guide §9.3 / golden-dataset-plan §3 bar of "at least the
277 ASVS-core". Final breakdown:
positive 292 (277 ASVS 1:1 + 15 multi-link from OWASP Top 10 + CWE)
hard_negative 12 (ASVS reqs with "do not / does not / shall not /
should not" phrasing, real DB CRE; this is the
cross-encoder vs cosine negation case)
explicit 5 (synthesized text literally citing real cre.external_id)
update 5 (synthesized before/after of real ASVS reqs, real CRE)
ambiguous 5 (broad SDLC/governance statements, decision=review)
Ground truth comes from standards_cache.sqlite via the join
node -> cre_node_links -> cre, so labels are the OpenCRE graph the team
already curated. Multi-link rows exercise the Q-D rule (Jaccard >= 0.5 of
expected CRE set AND top-1 in set) with real data.
Adds scripts/build_golden_dataset.py to make the derivation reproducible.
The script's --check mode re-derives from the DB and exits non-zero on any
drift, so CI can guarantee the committed JSON tracks the live mappings.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds dataset_test.py with: - Every row validates against both the Pydantic GoldenDatasetRow and the canonical gsoc-notes/bonding/golden_dataset.schema.json (jsonschema). - At least 277 positive rows derived from the OpenCRE DB are present (the master guide's hard floor). - All 5 slices are present and each has >=5 rows so the harness stratifies. - At least one multi-link positive row exists so the Q-D rule has data to operate on. - Every row carries provenance.ground_truth_source (no anonymous rows). - All row ids are unique. - Determinism: running build_golden_dataset.py --check against the committed JSON exits 0 (skipped if standards_cache.sqlite is absent). 48/48 librarian tests green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PRAteek-singHWY
pushed a commit
that referenced
this pull request
Jun 25, 2026
OWASP#928) * feat(module-b): add Pydantic v2 schemas + hashing for Module A input contract Establishes the data contract Module B consumes from Module A. ChangeRecord is a Pydantic v2 model matching A's actual emission shape: nested source (discriminated union on type for github/rss), span (chunk position + heading_path + char/line offsets), and locator (addressing scheme). Internal models ClassifyResult and QueuePayload prep for later stages. hashing.py provides normalize_text + compute_content_hash since Module A does not emit content_hash; B computes its own (SHA-256 of normalized text) for use as the knowledge_queue dedup key. 22 unittest cases cover the round-trip, the discriminated union, hash determinism, normalization rules, code-fence preservation, and idempotency. Full make test: 271 passing, no regressions. Part of GSoC 2026 OpenCRE Scraper & Indexer (Project OIE) Module B. * feat(module-b): add Module A mock fixture + generated JSON Schema artifact module_a_mock.jsonl: Module A's canonical 20-record mock shared 2026-05-29, saved as JSONL (one record per line per the contract). Becomes a permanent integration-test fixture for B's parser and a reference shape for the Module A contributor. module_a_contract.schema.json: JSON Schema generated from B's Pydantic ChangeRecord model via model_json_schema(). 246 lines covering all four nested types (ChangeRecord, GithubSource, RssSource, Span, Locator). Source of truth for cross-module CI validation. Part of GSoC 2026 OpenCRE Scraper & Indexer (Project OIE) Module B. * feat(module-b): add OWASP harvester, labeling TUI, and labeled dataset build_labeled_dataset.py: PyGithub-based harvester that acts as Module A's stand-in for producing benchmark data. Fetches recent commits from 4 OWASP repos (WSTG, ASVS, CheatSheetSeries, SAMM), applies the contract's normalization rules, splits into chunks at markdown heading boundaries with a fence-aware stack-based walker that tracks heading_path + char/line offsets, and emits records in Module A's actual nested shape. Pluggable via GITHUB_TOKEN env var. Reproducible: python scripts/build_labeled_dataset.py regenerates the candidate set. label_dataset.py: resumable interactive TUI for manual classification. Atomic-writes labeled_data.json after every keystroke; lookup by chunk_id for resume. Embeds the recall-first definition (agreed with maintainer 2026-06-01) so labelers see the rule front-of-mind: KNOWLEDGE for any chunk with security signal, NOISE only for pure organizational content. candidate_commits.json: 100 records, 25 per repo, all Pydantic-valid against ChangeRecord. 90/100 have non-empty heading_path; 10 multi-chunk artifacts captured. labeled_data.json: 100/100 labeled by hand under the recall-first rule. Distribution 55 KNOWLEDGE / 40 NOISE / 5 UNCERTAIN. Per-repo skew is visible: CheatSheetSeries 92% K, SAMM 0% K (the SAMM commits sampled landed entirely on Website/Sponsorship/meetings paths -- empirical input for Week 2's noise_patterns.yaml). Part of GSoC 2026 OpenCRE Scraper & Indexer (Project OIE) Module B. * style(module-b): apply Black formatting to Week 1 files Super-Linter (Black 24.4.2) flagged 4 files in the previous push. Applied `black` (same pinned version) to bring them in line with the repo's formatting standard. Cosmetic changes only: blank lines around section-separator comments, one multi-line dict join. No behavior or test changes -- `make test` remains 271 passing, 1 skip. * chore(module-b): address CodeRabbit Week 1 review comments - Sort __all__ lists in hashing.py and schemas.py to satisfy Ruff RUF022. - Declare JSON Schema dialect ($schema = draft 2020-12, which is what Pydantic v2 model_json_schema() emits) on the contract artifact. - Wrap load_labeled() in scripts/label_dataset.py with try/except so a corrupted labeled_data.json prints an actionable hint instead of a raw JSONDecodeError stack trace. Deferred to Week 2 (will be addressed when we touch the harvester): - chunker should also track <pre> open/close, not just ``` fences - _split_chunk_by_size cursor arithmetic assumes \\n\\n separator even on hard-split sub-chunks Tests: 271 passing, 1 skip (unchanged). Black: clean. * feat(module-b): add Stage 1.5 sanitize.py vendored from TRACT Defensive text cleanup (PDF ligatures, zero-width chars, HTML, hyphenation). Vendored from rocklambros/TRACT under CC0; drops their whitespace-collapse step so structure (newlines, paragraphs) is preserved for Module B's LLM. 26 unit tests, all passing. * feat(module-b): add Stage 1 regex_filter + noise_patterns.yaml Path-based filter with extension/filename/glob deny rules and allow_overrides. Patterns are deliberately conservative under the recall-first labeling rule. 15 unit tests including >=90% rejection / 0% false-positive acceptance criteria. * fix(module-b): chunker tracks <pre> blocks; correct hard-split cursor math Addresses CodeRabbit comments #4 and OWASP#5 on the Week 1 PR. * chore(module-b): address CodeRabbit Week 2 review comments * chore(module-b): address Week 2 maintainer review on noise_patterns.yaml --------- Signed-off-by: Manshu Saini <149303743+manshusainishab@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR is
The third and final PR of Module C, Week 1. It replaces the 10-row seed dataset from
week_1-2with the real golden dataset — 319 rows derived fromstandards_cache.sqlite(the OpenCRE graph the team already curated). This is the actual ruler every later C PR will be measured against in CI.Stacked on
gsocmodule_C_week_1_2. When PR 2 merges, GitHub re-targets this tomain.Why this PR is the most important one in Week 1
W1 PR 1 nailed the contracts. W1 PR 2 nailed the harness scaffolding. But neither has a real measurement. The 10-row seed in PR 2 only proved the wiring; with this PR landed, every later C PR is measured against 319 real rows with real DB-grounded ground truth, and an accuracy drop > 2pts blocks the PR. That's the W1 promise from your
golden-dataset-plan.md: "It makes a mapping change behave like a code change: versioned, measured, and revertible."What's in this PR, step by step
1. The build script —
scripts/build_golden_dataset.pyA deterministic derivation from
standards_cache.sqlite:node → cre_node_links → creto pull ground-truth labels. The OpenCRE graph is the ground truth — pergolden-dataset-plan.md§3, "Ground truth = the existing OpenCRE DB mappings."ORDER BYso output is byte-stable.--checkmode re-derives and exits non-zero if the committed JSON has drifted from what the DB now produces. CI runs this to guarantee the JSON tracks live mappings.section_idand fetch the real CREexternal_idat build time — text is synthesized but ground truth stays real.2. The dataset —
application/tests/librarian/fixtures/golden_dataset.json319 rows total, by slice:
positive(1:1)positive(multi-link)hard_negativedo not / does not / shall not / should not, with real DB CRE (cross-encoder must beat cosine without losing the right CRE)explicitcre.external_idupdateambiguousdecision=review,reason_code=BELOW_THRESHOLD / NO_CANDIDATESEvery row carries an honest
provenance.ground_truth_sourcerecording whether the ground truth came from the DB (most rows) or was manually synthesized (the broad ambiguous slice).3. The validation + determinism tests —
application/tests/librarian/dataset_test.pyWhat CI now guarantees, on every PR:
GoldenDatasetRow(Pydantic) andgolden_dataset.schema.json(jsonschema).provenance.ground_truth_source.ids are unique.build_golden_dataset.py --checkagainst the committed JSON exits 0. (Auto-skipped if the DB file is absent.)4. Multi-link rule consistency
Per your proposal's Q-D rule (
scoring.pyfromweek_1-2):The dataset honours this by including 15 genuine multi-link positive rows from OWASP Top 10 and CWE, where the expected
cre_idslist has 2–4 entries pulled straight from the DB. The hard floor is set so that this rule has real data to exercise, not just a single hand-crafted multi-link example.How to verify locally
The
319 stripped leaking hub entriesis exactly the point of the firewall — the W1 stub hub is seeded from the rows' own text, so without the firewall every row would leak.5/319 correctis the W1 baseline: the 5 ambiguous rows have no expectedcre_idsso empty predictions match; the 314 linked-decision rows correctly show as not-yet-predicted (real predictions arrive when the pipeline lands W3–W6).What this PR does NOT claim
GoldenDatasetRowwas nailed down inweek_1-1.Why some slices are smaller than others
descriptionfields in the DB — no usable text. That's why multi-link rows come from OWASP Top 10 + CWE (the standards with both multi-CRE mappings and real text), not WSTG.That closes Week 1: contracts (PR 1) → harness (PR 2) → real ruler (PR 3). Mentor confirmation of Q-D at the Friday call unblocks merging PR 2 and the multi-link reasoning in this PR. After that, week 2 starts the deterministic stage — the
SectionNormalizer(RFC contract → internalSection, no ML yet).