-
Notifications
You must be signed in to change notification settings - Fork 4
#53: retrieval-quality gate hardening — golden set 24→35 + direct-surface eval matrix #57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
dde09b6
#53: retrieval-quality gate hardening — golden set 24→35 + direct-sur…
mobileskyfi e2a803b
#53 review: surface eval fails loudly on a misconfigured golden query
mobileskyfi 429c52b
#53 review: fail eval on misconfigured surface queries
mobileskyfi 89ecc57
#53 review: infer direct eval surface from shape
mobileskyfi 154908a
Add Copilot Gate workflow to block merge while review is pending
mobileskyfi 7564758
#53 review: accurate surface message, mirror effectiveSurface in comp…
mobileskyfi d47e6f1
#53 review: harden copilot-gate workflow (CodeRabbit)
mobileskyfi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| name: Copilot Gate | ||
| on: | ||
| pull_request: | ||
| types: [opened, synchronize, reopened, ready_for_review, review_requested, review_request_removed] | ||
| pull_request_review: | ||
| types: [submitted, dismissed] | ||
|
|
||
| # Minimal token scope: the gate only reads PR requested-reviewer state via `gh api`. | ||
| permissions: | ||
| contents: read | ||
| pull-requests: read | ||
|
|
||
| # One gate run per PR: cancel an in-flight run when a newer review event lands so a | ||
| # stale result can't outlive the reviewer-state change that superseded it. | ||
| concurrency: | ||
| group: copilot-gate-${{ github.event.pull_request.number }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| check-pending: | ||
| runs-on: ubuntu-latest | ||
|
mobileskyfi marked this conversation as resolved.
|
||
| steps: | ||
| - name: Check Copilot Review Status | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| PR_NUMBER: ${{ github.event.pull_request.number }} | ||
| REPO: ${{ github.repository }} | ||
| run: | | ||
| set -euo pipefail | ||
| echo "Checking if Copilot is a pending requested reviewer on PR #$PR_NUMBER..." | ||
| PENDING=$(gh api "repos/$REPO/pulls/$PR_NUMBER" --jq '.requested_reviewers[].login') | ||
| if echo "$PENDING" | grep -qxF 'copilot-pull-request-reviewer'; then | ||
| echo "::error::Copilot review is currently pending! Blocking merge." | ||
| exit 1 | ||
| fi | ||
| echo "Copilot is not a pending reviewer. Gate is green." | ||
|
github-advanced-security[bot] marked this conversation as resolved.
Fixed
|
||
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| # B-0020 — 0.11 retrieval-quality audit (golden-set expansion, 0.10.0 compare, self-eval, Bug Ledger) | ||
|
|
||
| **Status:** research + decision record for issue #53. Grounded against real DBs (see below). | ||
| **Date:** 2026-07-12. **Sibling:** #26 (ranking), #28 (umbrella "did we regress from HTML"), B-0012 (migration), B-0010 (eval phases). | ||
|
|
||
| ## What was measured, and against what | ||
|
|
||
| Three DBs, all real (no assumptions that main == 0.10.0): | ||
|
|
||
| | DB | corpus | how obtained | | ||
| |----|--------|--------------| | ||
| | current | Docusaurus `/docs` (363 pages, 4402 props, 1311 changelogs, 1953 video segments) | fresh local `make extract` off live manual.mikrotik.com, 2026-07-12 | | ||
| | v0.10.0 | Confluence HTML (321 pages, no `rosetta_id`) | published `v0.10.0` release DB, clean | | ||
| | v0.10.0-compat | v0.10.0 + empty schema-v8 tables | `db.ts` idempotent init on a copy (pages untouched) — only so current `searchAll` can run against it (see BL-6) | | ||
|
|
||
| ## Finding 1 — No net regression from the Confluence→Docusaurus swap | ||
|
|
||
| `src/eval/corpus-compare.ts` (one-off, not a CI gate) runs the golden search queries against | ||
| both corpora and matches on a **corpus-agnostic topic token** (the golden set keys on | ||
| `rosetta_id`, which v0.10.0 lacks entirely, so page-recall can't be compared directly). | ||
|
|
||
| **Result: 14/16 (88%) topic-hit@5 on BOTH corpora. Zero topic-level regressions.** The existing | ||
| 24-query golden set also scores Recall@5 **91.7%** / MRR 86.8% / classifier 100% on the current | ||
| corpus — at or above the pre-swap baseline. The corpus swap did not degrade what `routeros_search` | ||
| finds for bread-and-butter questions. | ||
|
|
||
| ## Finding 2 — #26's two "regressions" fail on 0.10.0 too (premise correction) | ||
|
|
||
| `nl-firewall-filter` ("block traffic from a specific IP address") and `nl-bgp` ("establish a BGP | ||
| peer with my upstream") miss on the **v0.10.0 Confluence corpus** as well: | ||
|
|
||
| - 0.10.0 firewall query top-5: ROSE-storage, General Properties, First Time Configuration, | ||
| Scripting, HotSpot — no Filter page. | ||
| - 0.10.0 BGP query top-5: Routing Protocol Overview, VRF, DHCP — no dedicated BGP page. | ||
|
|
||
| So #26 ("ranking regressions **from the Docusaurus corpus swap**") is mis-titled: this is a | ||
| **pre-existing query-core weakness** (AND-only FTS candidate pool + BM25 length bias on | ||
| verbose NL questions), independent of corpus. Still worth fixing in #26; just not swap-induced. | ||
| Posted as a comment on #26. | ||
|
|
||
| ## Finding 3 — Self-supervised eval: floors pass, baseline was stale | ||
|
|
||
| The blocking self-eval rehearsal (`eval_self_blocking=true`, maintainer CI run 29210060933, and | ||
| reproduced locally) FAILED — but only on **regression vs baseline**, while every absolute | ||
| strategy floor passed on the current corpus (title hit@5 96.7%, section hit@10 78.8%, property | ||
| hit@10 80%, cmd-path hit@5 70%, mrr 59.4%). Root cause: `self-supervised-baseline.json` was | ||
| generated **2026-04-22 against the Confluence corpus** and never regenerated after the swap, so | ||
| every post-swap run shows a phantom ~5–7pp "regression." Top misses are generic ambiguous | ||
| headings ("Example #1", "Configuration example", "Read-only properties") — inherent low signal | ||
| of the section strategy, not retrieval bugs; none earn a golden-set row. **Action taken:** | ||
| regenerated the baseline against Docusaurus (200 queries) → blocking rehearsal now green. Counts | ||
| as rehearsal #1 of the ≥3 in the `V-retrieval-self` promotion path (VALIDATION.md). | ||
|
|
||
| ## Bug Ledger — ETL/MCP issues surfaced (NOT fixed here; per maintainer, surface don't hide) | ||
|
|
||
| Discipline: golden fixtures point at the CORRECT answer and fail loudly; none were loosened to | ||
| green the board. Items below are real defects found while authoring the net. | ||
|
|
||
| - **BL-1 — command-path→page→property link broken on core menus (has a durable failing anchor).** | ||
| `lookupProperty(name, path)` returns only low-confidence rows (no HIGH resolution) for | ||
| `/ip/firewall/filter action` (19 rows, 0 high), `/ip/dhcp-server lease-time`, `/ip/ipsec/peer | ||
| exchange-mode`, `/routing/bgp/connection distance`. Worse, `/ip/dhcp-server address-pool` | ||
| resolves HIGH to the **wrong page** (hotspot-captive-portal, not DHCP). The property exists and | ||
| the command path exists; they just aren't linked. Pinned by golden query | ||
| `prop-firewall-filter-action` (known-failing). Owning follow-up issue filed. | ||
| - **BL-2 — noisy command→page links.** Some `commands.page_id` links are semantically wrong, | ||
| e.g. `/ip/service/print` → docs/containers, `/certificate/scep-server/*` → capsman page. | ||
| Same root area as BL-1. Tracked in the BL-1 follow-up. | ||
| - **BL-3 — dotted WiFi properties not extracted.** `/interface/wifi security.authentication-types`, | ||
| `configuration.mode`, `channel.width` return **0 property rows**; `/interface/wifi ssid` returns | ||
| 9 rows but 0 high-confidence. The new manual's nested/dotted wifi property structure isn't | ||
| captured by the Docusaurus property parser. Tracked in the BL-1 follow-up. | ||
| - **BL-4 — classifier false-positive on an NL question.** "port forward to an internal server" | ||
| is classified as command path `/port/forward/to/an/internal/server`. NL questions with | ||
| path-shaped words get mis-detected. Candidate for the classifier-improvement backlog. | ||
| - **BL-5 — see Finding 2** (#26 is not swap-induced). Commented on #26. | ||
| - **BL-6 — `searchAll` crashes on a pre-v8 DB.** `SQLiteError: no such table: device_aliases` | ||
| (query.ts:391, the alias probe added in #51). No graceful degradation when a schema-v8 table | ||
| is absent. Only bites cross-version DB use (e.g. this audit); noted for robustness. | ||
|
|
||
| ## What shipped in #53 (the framework) | ||
|
|
||
| - Golden set 24 → 35: +2 nl (pppoe, dns), +4 property (2 clean HIGH anchors, 1 free-form search, | ||
| 1 known-failing BL-1 anchor), +3 changelog (CVE / feature / version-scoped), +2 video. | ||
| - `src/eval/retrieval.ts`: `surface` dispatch (property/changelog/video → the dedicated tools) + | ||
| informational `surface_matrix` (per-surface hit@5), kept out of the gated search aggregates; | ||
| soft per-query "was passing, now misses" surface-regression WARNING. | ||
| - `_thresholds` recomputed for 27 search queries (0.88/0.82/0.75/0.90) — the pre-#53 0.85/0.70/0.65 | ||
| had drifted loose over the larger set; the 2pp regression check remains the tight forward guard. | ||
| - Both baselines regenerated against the current Docusaurus corpus. |
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.