Files
whetstone_DSL/editor/tests/step1873_test.cpp
Bill de5bdd358f Close all 26 generator readiness gaps (sprints 267-270)
Sprint 268: GR-002/003/006/007/008/016/017/019/021/024 — self-containment,
  graduation thresholds, asm/ir/jvm/elixir lang coverage, semanno format.
Sprint 269: GR-005/011/013/015 — prose capture in RequirementsParser,
  GateEnforcer, ParitySkewAnalyzer, CrossArtifactConsistencyEngine.
Sprint 270: GR-009/010/012/014/018/020 — CrossFileTransactionGate,
  SemanticCompletionGate, ConstrainedProjectionGate, TokenBudgetGate,
  CppConstraintRefactorPolicy, NativeDecompositionDepthGuard.
All 50 new tests passing (steps 1873-1882, 5/5 per step).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 22:28:41 -07:00

110 lines
3.8 KiB
C++

// Step 1873 TDD: GR-005 — Prose paragraph capture in RequirementsParser
//
// Both parsers currently skip non-bullet lines in requirement sections.
// A spec with prose (non-bullet) requirements silently drops those requirements.
//
// t1: prose lines in ## Requirements section are captured
// t2: ## Features bullet list only → success and features captured
// t3: ## Goals bullets + ## Requirements prose → both captured (end-to-end)
// t4: very short prose lines (< 10 chars) are not captured
// t5: code fence marker lines (starting with `) are not captured
#include "RequirementsParser.h"
#include "ArchitectIntakeProcessor.h"
#include <iostream>
#include <string>
static int p=0,f=0;
#define T(n) { std::cout<<" "<<#n<<"... "; }
#define P() { std::cout<<"PASS\n"; ++p; }
#define F(m) { std::cout<<"FAIL: "<<m<<"\n"; ++f; }
#define C(c,m) if(!(c)){F(m);return;}
void t1(){
T(prose_lines_in_requirements_captured);
std::string md =
"## Requirements\n"
"The system must authenticate users before allowing access.\n"
"The API must be RESTful and support pagination.\n";
auto items = RequirementsParser::parse(md);
C(items.size() >= 2,
"expected at least 2 prose requirements, got " + std::to_string(items.size()));
bool foundAuth = false, foundRest = false;
for (const auto& r : items) {
if (r.sourceText.find("authenticate") != std::string::npos) foundAuth = true;
if (r.sourceText.find("RESTful") != std::string::npos) foundRest = true;
}
C(foundAuth, "auth prose requirement not captured");
C(foundRest, "RESTful prose requirement not captured");
P();
}
void t2(){
T(features_only_bullet_list_succeeds);
std::string md =
"## Features\n"
"- REST API endpoints\n"
"- rate limiting support\n";
auto result = ArchitectIntakeProcessor::process(md);
C(result.success, "expected success for features-only spec");
C(result.requirementCount >= 2,
"expected at least 2 features, got " + std::to_string(result.requirementCount));
P();
}
void t3(){
T(goals_bullets_plus_requirements_prose_both_captured);
std::string md =
"## Goals\n"
"- Provide secure access\n"
"- Support mobile clients\n"
"## Requirements\n"
"The system must implement OAuth2 for authentication.\n";
auto result = ArchitectIntakeProcessor::process(md);
C(result.success, "expected success");
// 2 goals via normalized path + 1 prose req via parsedRequirements
C(result.requirementCount >= 3,
"expected at least 3 (2 goals + 1 prose req), got " + std::to_string(result.requirementCount));
P();
}
void t4(){
T(short_prose_lines_not_captured);
std::string md =
"## Requirements\n"
"OK\n"
"Yes\n"
"- A valid bullet requirement to ensure the section works\n";
auto items = RequirementsParser::parse(md);
bool foundShort = false;
for (const auto& r : items) {
if (r.sourceText == "OK" || r.sourceText == "Yes") foundShort = true;
}
C(!foundShort, "short prose lines should not be captured as requirements");
P();
}
void t5(){
T(code_fence_marker_not_captured);
std::string md =
"## Requirements\n"
"The system must support JSON output.\n"
"```json\n"
"{ \"key\": \"value\" }\n"
"```\n";
auto items = RequirementsParser::parse(md);
bool foundFence = false;
for (const auto& r : items) {
if (r.sourceText.find("```") != std::string::npos) foundFence = true;
}
C(!foundFence, "code fence marker should not be captured as a requirement");
P();
}
int main(){
std::cout<<"Step 1873: GR-005 prose paragraph capture in RequirementsParser\n";
t1();t2();t3();t4();t5();
std::cout<<"\nResults: "<<p<<"/"<<(p+f)<<" passed\n";
return f?1:0;
}