Skip to content

Commit 47e8f17

Browse files
committed
test: scaffold prose retrieval golden-set schema and stratification plan
Spec-only measurement scaffold (no corpus yet, nothing runs in CI). phase1_plan.json: query_type x difficulty strata (fact_lookup/traceability/synthesis), 60 records + doc-type coverage constraints. golden_v0.schema.json: draft 2020-12 record schema extending the code GoldenLabel (query_type, expected_doc_spans, expected_trace_path, expected_doc_types) with conditional traceability/synthesis rules. examples.jsonl: three schema-validated placeholders. Mirrors tests/eval/pipeline + tests/eval/golden.
1 parent 612578a commit 47e8f17

4 files changed

Lines changed: 223 additions & 0 deletions

File tree

tests/eval/prose/README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Prose Retrieval Golden Set (SDLC document collateral)
2+
3+
**Status: SPEC ONLY — awaiting corpus.** No prose corpus is present in this repo yet, so no records exist and **nothing here runs in CI** (this directory contains data + schema + docs, no `test_*.py` for pytest to collect). This is the measurement scaffold that must exist *before* any retrieval tuning, mirroring the code eval set.
4+
5+
This is the prose sibling of the code eval pipeline (`tests/eval/golden/`, `tests/eval/pipeline/`, `tests/eval/harness/`). Full design and metrics: [`docs/research/document_collateral_retrieval_2026.md` §6](../../../docs/research/document_collateral_retrieval_2026.md).
6+
7+
## Files
8+
9+
| File | Role |
10+
|---|---|
11+
| `phase1_plan.json` | Committed stratification plan (machine-checked input). Mirror of `tests/eval/pipeline/phase1_plan.json`, keyed on `query_type × difficulty` with doc-type coverage constraints. |
12+
| `golden_v0.schema.json` | JSON Schema (draft 2020-12) for a final prose `GoldenLabel`. Extends the code record: `query_type` replaces `task_type`; `expected_doc_spans` replace `expected_entities`/`expected_files`; traceability/synthesis add `expected_trace_path` / `expected_doc_types`. |
13+
| `examples.jsonl` | Three placeholder records (one per query type) that validate against the schema. `method: "template_placeholder"`, `source_verified: false` — illustrative only, **not** labels. |
14+
15+
## Query types & stratification (target: 60)
16+
17+
| Query type | easy | medium | hard | total |
18+
|---|:--:|:--:|:--:|:--:|
19+
| `fact_lookup` | 8 | 8 | 4 | 20 |
20+
| `traceability` | 0 | 8 | 12 | 20 |
21+
| `synthesis` | 2 | 8 | 10 | 20 |
22+
23+
- **fact_lookup** — answer in one passage of one doc; the local-first / precise-retrieval sweet spot.
24+
- **traceability** — multi-hop across the SDLC chain (Problem Statement → PRD → HLD → LLD → Release Notes → Support); the class flat RAG cannot answer and the document graph owns. No `easy` tier by definition.
25+
- **synthesis** — aggregate/compare across many docs (e.g. "summarize all healthcare case studies", "what changed v2→v3").
26+
27+
## Cross-field gates (enforced by the harness, not the JSON Schema)
28+
29+
- `line_range` is `[start, end]` with `start <= end` and both within the file at the recorded SHA.
30+
- Every `doc_id` + `heading_path` resolves against a fresh parse of the corpus.
31+
- traceability: `expected_trace_path` spans ≥ 3 distinct doc types; every node resolves in the document graph.
32+
- synthesis: `expected_doc_spans` cover ≥ 3 distinct documents.
33+
34+
## Scoring (when the corpus exists)
35+
36+
Reuse `tests/eval/harness/scorer.py` with prose extensions:
37+
- **Retrieval:** `recall@k` (primary — a missed span = a wrong generated answer), `nDCG@10`, `MRR`.
38+
- **Traceability:** path-completeness (fraction of `expected_trace_path` recovered).
39+
- **Synthesis:** document-coverage over `expected_doc_spans`.
40+
- **Generation:** faithfulness/groundedness + citation accuracy over `must_mention_facts` / `must_not_mention_facts`.
41+
- **Routing:** re-calibrate `sufficiency_score` against prose answer-correctness — do **not** port the code corpus's 0.8 threshold; re-measure (the code finding was over-confident).
42+
43+
## Bootstrap procedure (blocked on corpus)
44+
45+
1. Point the corpus at a sample doc set (the only missing input).
46+
2. Run the three-role Author / Oracle / Adversary pipeline; the Oracle reads documents instead of code.
47+
3. Mechanical gate resolves `doc_id` + `heading_path` + `line_range` and `feature_id`/`requirement_id` joins.
48+
4. Stratified human spot-check (15%), then bless `prose_golden_v1.0.json` with a `meta.json` recording per-doc SHAs (same drift guard as the code set).

tests/eval/prose/examples.jsonl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{"query_id":"pq_example_fact","query_text":"What retry policy does the Atlas rate-limiting feature specify?","query_type":"fact_lookup","difficulty":"easy","expected_doc_spans":[{"doc_id":"prd/atlas-rate-limiting.md","doc_type":"prd","heading_path":"PRD > Requirements > Rate Limiting","line_range":[412,448],"role":"primary"}],"expected_trace_path":[],"expected_doc_types":["prd"],"must_mention_facts":["The retry policy is exponential backoff capped at 5 retries.","The base backoff interval is 200ms."],"must_not_mention_facts":["Retries are unbounded.","The policy is defined in the billing service."],"correct":true,"validation":{"source_verified":false,"human_reviewed":false,"method":"template_placeholder"},"schema_version":"0.1.0"}
2+
{"query_id":"pq_example_trace","query_text":"Trace the Atlas rate-limiting feature from its product requirement through to the customer-facing support article.","query_type":"traceability","difficulty":"hard","expected_doc_spans":[{"doc_id":"prd/atlas-rate-limiting.md","doc_type":"prd","heading_path":"PRD > Requirements > Rate Limiting","line_range":[412,448],"role":"primary"},{"doc_id":"hld/atlas-gateway.md","doc_type":"hld","heading_path":"HLD > Components > GatewayThrottler","line_range":[88,132],"role":"primary"},{"doc_id":"lld/atlas-rate-limiter.md","doc_type":"lld","heading_path":"LLD > Algorithm > Token Bucket","line_range":[40,96],"role":"primary"},{"doc_id":"release_notes/atlas-3.2.md","doc_type":"release_notes","heading_path":"Release Notes 3.2 > New Features","line_range":[12,20],"role":"supporting"},{"doc_id":"support_manual/atlas-429-troubleshooting.md","doc_type":"support_manual","heading_path":"Support > Errors > HTTP 429","line_range":[5,60],"role":"supporting"}],"expected_trace_path":["feature:atlas-rate-limiting","prd/atlas-rate-limiting.md","hld/atlas-gateway.md","lld/atlas-rate-limiter.md","release_notes/atlas-3.2.md","support_manual/atlas-429-troubleshooting.md"],"expected_doc_types":["prd","hld","lld","release_notes","support_manual"],"must_mention_facts":["Requirement REQ-RL-01 in the PRD is implemented by the GatewayThrottler component described in the HLD.","The LLD specifies a token-bucket algorithm for throttling.","Atlas 3.2 release notes announce the rate-limiting feature.","The support manual documents the HTTP 429 troubleshooting flow for end users."],"must_not_mention_facts":["The feature is implemented in the billing service.","Rate limiting shipped in Atlas 2.x."],"correct":true,"validation":{"source_verified":false,"human_reviewed":false,"method":"template_placeholder"},"schema_version":"0.1.0"}
3+
{"query_id":"pq_example_synth","query_text":"Summarize the common customer outcomes reported across the healthcare client case studies.","query_type":"synthesis","difficulty":"medium","expected_doc_spans":[{"doc_id":"case_study/northwind-health.md","doc_type":"case_study","heading_path":"Case Study > Results","line_range":[60,110],"role":"primary"},{"doc_id":"case_study/acme-care.md","doc_type":"case_study","heading_path":"Case Study > Results","line_range":[55,98],"role":"primary"},{"doc_id":"case_study/medix.md","doc_type":"case_study","heading_path":"Case Study > Outcomes","line_range":[70,120],"role":"primary"}],"expected_trace_path":[],"expected_doc_types":["case_study"],"must_mention_facts":["At least three healthcare case studies report reduced patient-onboarding time.","Two or more report improved compliance-audit pass rates."],"must_not_mention_facts":["The case studies are drawn from the fintech sector."],"correct":true,"validation":{"source_verified":false,"human_reviewed":false,"method":"template_placeholder"},"schema_version":"0.1.0"}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"$id": "https://knowcode.dev/schemas/prose/golden_v0.schema.json",
4+
"title": "Prose GoldenLabel",
5+
"description": "Final committed record for the SDLC document-collateral retrieval golden set. Extends the code GoldenLabel (tests/eval/golden/golden_v1.0.json): query_type replaces task_type; expected_doc_spans replace expected_entities/expected_files; traceability and synthesis add expected_trace_path / expected_doc_types. See docs/research/document_collateral_retrieval_2026.md section 6.",
6+
"type": "object",
7+
"additionalProperties": false,
8+
"required": [
9+
"query_id",
10+
"query_text",
11+
"query_type",
12+
"difficulty",
13+
"expected_doc_spans",
14+
"must_mention_facts",
15+
"must_not_mention_facts",
16+
"validation",
17+
"schema_version"
18+
],
19+
"properties": {
20+
"query_id": {
21+
"type": "string",
22+
"pattern": "^pq[0-9]{3,}$|^pq_[a-z0-9_]+$",
23+
"description": "e.g. 'pq001' or 'pq_example_trace'."
24+
},
25+
"query_text": { "type": "string", "minLength": 8 },
26+
"query_type": { "enum": ["fact_lookup", "traceability", "synthesis"] },
27+
"difficulty": { "enum": ["easy", "medium", "hard"] },
28+
"expected_doc_spans": {
29+
"type": "array",
30+
"minItems": 1,
31+
"items": { "$ref": "#/$defs/docSpan" },
32+
"description": "Prose analogue of expected_entities + expected_files: the passages a correct retrieval must surface."
33+
},
34+
"expected_trace_path": {
35+
"type": "array",
36+
"default": [],
37+
"items": {
38+
"type": "string",
39+
"pattern": "^(feature|requirement|persona|component|release|decision|client):[a-z0-9._/-]+$|^[a-z0-9._/-]+\\.md$",
40+
"description": "Ordered graph nodes for a traceability walk: typed entity refs (e.g. 'feature:atlas-rate-limiting') or document ids ('prd/atlas-rate-limiting.md')."
41+
}
42+
},
43+
"expected_doc_types": {
44+
"type": "array",
45+
"default": [],
46+
"items": { "$ref": "#/$defs/docType" },
47+
"description": "For synthesis: the collection(s) in scope (e.g. ['case_study'])."
48+
},
49+
"must_mention_facts": { "type": "array", "items": { "type": "string" } },
50+
"must_not_mention_facts": { "type": "array", "items": { "type": "string" } },
51+
"correct": { "type": "boolean" },
52+
"validation": { "$ref": "#/$defs/validation" },
53+
"provenance": { "$ref": "#/$defs/provenance" },
54+
"schema_version": { "const": "0.1.0" }
55+
},
56+
"allOf": [
57+
{
58+
"if": { "properties": { "query_type": { "const": "traceability" } } },
59+
"then": {
60+
"required": ["expected_trace_path"],
61+
"properties": {
62+
"expected_trace_path": { "minItems": 2 },
63+
"expected_doc_spans": { "minItems": 2 }
64+
}
65+
}
66+
},
67+
{
68+
"if": { "properties": { "query_type": { "const": "synthesis" } } },
69+
"then": {
70+
"required": ["expected_doc_types"],
71+
"properties": {
72+
"expected_doc_spans": { "minItems": 3 },
73+
"expected_doc_types": { "minItems": 1 }
74+
}
75+
}
76+
}
77+
],
78+
"$defs": {
79+
"docType": {
80+
"enum": [
81+
"problem_statement", "prd", "architecture", "hld", "lld",
82+
"release_notes", "user_guide", "install_guide", "support_manual",
83+
"brochure", "feature_catalog", "case_study", "whitepaper"
84+
]
85+
},
86+
"docSpan": {
87+
"type": "object",
88+
"additionalProperties": false,
89+
"required": ["doc_id", "doc_type", "heading_path", "line_range"],
90+
"properties": {
91+
"doc_id": { "type": "string", "description": "Repo-relative path of the document." },
92+
"doc_type": { "$ref": "#/$defs/docType" },
93+
"heading_path": {
94+
"type": "string",
95+
"description": "Breadcrumb of the section, e.g. 'PRD > Requirements > Rate Limiting'."
96+
},
97+
"line_range": {
98+
"type": "array",
99+
"items": { "type": "integer", "minimum": 1 },
100+
"minItems": 2,
101+
"maxItems": 2,
102+
"description": "[start, end], 1-indexed, start <= end (cross-field check enforced by the mechanical gate)."
103+
},
104+
"role": { "enum": ["primary", "supporting", "contextual"] }
105+
}
106+
},
107+
"validation": {
108+
"type": "object",
109+
"additionalProperties": false,
110+
"required": ["source_verified", "human_reviewed", "method"],
111+
"properties": {
112+
"source_verified": { "type": "boolean" },
113+
"human_reviewed": { "type": "boolean" },
114+
"method": { "type": "string" }
115+
}
116+
},
117+
"provenance": {
118+
"type": "object",
119+
"properties": {
120+
"query_author": { "type": "string" },
121+
"oracle": { "type": "string" },
122+
"adversary": { "type": "string" },
123+
"human_reviewer": { "type": ["string", "null"] },
124+
"reviewed_at": { "type": ["string", "null"] }
125+
}
126+
}
127+
}
128+
}

tests/eval/prose/phase1_plan.json

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"schema_version": "0.1.0",
3+
"dataset_version": "prose_golden_v0",
4+
"target_records": 60,
5+
"status": "spec_only_awaiting_corpus",
6+
"query_types": ["fact_lookup", "traceability", "synthesis"],
7+
"difficulty_definitions": {
8+
"easy": "Answer lives in a single passage of a single document; keyword-matchable.",
9+
"medium": "2-3 passages; one hop across sections or one cross-document reference; semantic retrieval matters.",
10+
"hard": "3+ passages spanning multiple documents or doc types; multi-hop or a cross-cutting concern."
11+
},
12+
"strata": [
13+
{ "query_type": "fact_lookup", "difficulty": "easy", "target": 8 },
14+
{ "query_type": "fact_lookup", "difficulty": "medium", "target": 8 },
15+
{ "query_type": "fact_lookup", "difficulty": "hard", "target": 4 },
16+
{ "query_type": "traceability", "difficulty": "easy", "target": 0 },
17+
{ "query_type": "traceability", "difficulty": "medium", "target": 8 },
18+
{ "query_type": "traceability", "difficulty": "hard", "target": 12 },
19+
{ "query_type": "synthesis", "difficulty": "easy", "target": 2 },
20+
{ "query_type": "synthesis", "difficulty": "medium", "target": 8 },
21+
{ "query_type": "synthesis", "difficulty": "hard", "target": 10 }
22+
],
23+
"doc_types": [
24+
"problem_statement", "prd", "architecture", "hld", "lld",
25+
"release_notes", "user_guide", "install_guide", "support_manual",
26+
"brochure", "feature_catalog", "case_study", "whitepaper"
27+
],
28+
"coverage_constraints": {
29+
"min_queries_per_doc_type_as_primary": 2,
30+
"min_distinct_doc_types_per_traceability_path": 3,
31+
"min_distinct_docs_per_synthesis_query": 3
32+
},
33+
"rationale": [
34+
"fact_lookup skews easy/medium: it is the class where precise chunking + reranking and the local-first answer have the strongest claim (mirrors LOCATE in the code set).",
35+
"traceability has no 'easy' tier: a single-document lookup is not a trace. It skews hard because it is multi-hop across the SDLC chain and is the class flat RAG cannot answer.",
36+
"synthesis skews medium/hard: aggregation/comparison over many documents; the 2 'easy' records are small single-collection summaries.",
37+
"doc-type coverage is enforced as a secondary constraint instead of a full doc_type x query_type x difficulty cross-product (which would be 117 cells for a 60-record bootstrap)."
38+
],
39+
"notes": [
40+
"SPEC ONLY. No prose corpus is present in this repository yet, so no records are generated and nothing here runs in CI.",
41+
"Mirrors tests/eval/pipeline/phase1_plan.json (the code eval plan). Reuses the three-role Author/Oracle/Adversary pipeline; the Oracle reads documents instead of code.",
42+
"See docs/research/document_collateral_retrieval_2026.md section 6 for the full evaluation plan and metrics."
43+
]
44+
}

0 commit comments

Comments
 (0)