Sprint 32: end-of-sprint architecture refactor pass

This commit is contained in:
Bill
2026-02-17 11:16:39 -07:00
parent 7384660e31
commit 7de00387cc
5 changed files with 97 additions and 57 deletions

View File

@@ -1,10 +1,9 @@
#pragma once
// Step 581: Acceptance-Criteria Binding
#include "IntakeTextUtil.h"
#include "TaskitemConfidenceAmbiguity.h"
#include <algorithm>
#include <cctype>
#include <string>
#include <vector>
@@ -61,23 +60,9 @@ public:
private:
static std::string makeTestSkeleton(const std::string& taskId, const std::string& checkText) {
return "test_" + sanitize(taskId) + "_" + sanitize(checkText);
}
static std::string sanitize(const std::string& text) {
std::string out;
bool lastUnderscore = false;
for (char c : text) {
if (std::isalnum(static_cast<unsigned char>(c))) {
out.push_back(static_cast<char>(std::tolower(static_cast<unsigned char>(c))));
lastUnderscore = false;
} else if (!lastUnderscore) {
out.push_back('_');
lastUnderscore = true;
}
}
while (!out.empty() && out.front() == '_') out.erase(out.begin());
while (!out.empty() && out.back() == '_') out.pop_back();
return out.empty() ? "check" : out;
const std::string a = intakeSanitizeToken(taskId, '_');
const std::string b = intakeSanitizeToken(checkText, '_');
return "test_" + (a.empty() ? std::string("task") : a) + "_" +
(b.empty() ? std::string("check") : b);
}
};

View File

@@ -0,0 +1,48 @@
#pragma once
// Sprint 32 refactor: shared intake text normalization helpers
#include <algorithm>
#include <cctype>
#include <string>
inline std::string intakeToLower(const std::string& value) {
std::string out = value;
std::transform(out.begin(), out.end(), out.begin(), [](unsigned char c) {
return static_cast<char>(std::tolower(c));
});
return out;
}
inline std::string intakeCompactLowerAlnumSpaces(const std::string& text) {
std::string out;
bool lastSpace = false;
for (char c : text) {
if (std::isalnum(static_cast<unsigned char>(c))) {
out.push_back(static_cast<char>(std::tolower(static_cast<unsigned char>(c))));
lastSpace = false;
} else if (!lastSpace) {
out.push_back(' ');
lastSpace = true;
}
}
while (!out.empty() && out.front() == ' ') out.erase(out.begin());
while (!out.empty() && out.back() == ' ') out.pop_back();
return out;
}
inline std::string intakeSanitizeToken(const std::string& text, char separator) {
std::string out;
bool lastSep = false;
for (char c : intakeToLower(text)) {
if (std::isalnum(static_cast<unsigned char>(c))) {
out.push_back(c);
lastSep = false;
} else if (!lastSep) {
out.push_back(separator);
lastSep = true;
}
}
while (!out.empty() && out.front() == separator) out.erase(out.begin());
while (!out.empty() && out.back() == separator) out.pop_back();
return out;
}

View File

@@ -1,6 +1,8 @@
#pragma once
// Step 574: Markdown Spec Parser
#include "IntakeTextUtil.h"
#include <algorithm>
#include <cctype>
#include <sstream>
@@ -71,7 +73,7 @@ public:
item.line = lineNo;
if (item.text.empty()) continue;
const std::string lowerTitle = toLower(currentSection.title);
const std::string lowerTitle = intakeToLower(currentSection.title);
if (contains(lowerTitle, "goal")) {
spec.goals.push_back(item);
} else if (contains(lowerTitle, "constraint")) {
@@ -101,14 +103,6 @@ private:
return text.find(needle) != std::string::npos;
}
static std::string toLower(const std::string& value) {
std::string out = value;
std::transform(out.begin(), out.end(), out.begin(), [](unsigned char c) {
return static_cast<char>(std::tolower(c));
});
return out;
}
static std::string trimLeft(const std::string& value) {
std::size_t i = 0;
while (i < value.size() && std::isspace(static_cast<unsigned char>(value[i]))) ++i;
@@ -124,19 +118,7 @@ private:
}
static std::string makeAnchor(const std::string& title) {
std::string anchor;
bool previousDash = false;
for (char c : toLower(title)) {
if (std::isalnum(static_cast<unsigned char>(c))) {
anchor.push_back(c);
previousDash = false;
} else if (!previousDash) {
anchor.push_back('-');
previousDash = true;
}
}
while (!anchor.empty() && anchor.front() == '-') anchor.erase(anchor.begin());
while (!anchor.empty() && anchor.back() == '-') anchor.pop_back();
std::string anchor = intakeSanitizeToken(title, '-');
return anchor.empty() ? "section" : anchor;
}
};

View File

@@ -1,9 +1,9 @@
#pragma once
// Step 575: Requirement Normalization and Conflict Detection
#include "IntakeTextUtil.h"
#include "MarkdownSpecParser.h"
#include <algorithm>
#include <cctype>
#include <map>
#include <set>
@@ -81,20 +81,7 @@ private:
}
static std::string normalizeText(const std::string& text) {
std::string out;
bool lastSpace = false;
for (char c : text) {
if (std::isalnum(static_cast<unsigned char>(c))) {
out.push_back(static_cast<char>(std::tolower(static_cast<unsigned char>(c))));
lastSpace = false;
} else {
if (!lastSpace) out.push_back(' ');
lastSpace = true;
}
}
while (!out.empty() && out.front() == ' ') out.erase(out.begin());
while (!out.empty() && out.back() == ' ') out.pop_back();
return out;
return intakeCompactLowerAlnumSpaces(text);
}
static bool isAmbiguous(const std::string& normalizedText) {

View File

@@ -10913,3 +10913,41 @@ signals into phase/sprint outcomes with closure diagnostics.
- **New tests in this sprint plan:** 112/112 passing
- **Phase 32a (574-578):** 56/56 passing
- **Phase 32b (579-583):** 56/56 passing
### Sprint 32 End Refactor Pass (Architecture Compliance)
**Status:** PASS (112/112 tests revalidated)
Performed a focused post-sprint refactor to centralize intake text
normalization/sanitization logic used by markdown parsing, requirement
normalization, and acceptance test-skeleton generation.
**Files added:**
- `editor/src/IntakeTextUtil.h` - shared intake text helpers:
- lowercase normalization helper
- compact alnum-space normalization helper
- generic token sanitization helper with configurable separators
**Files modified:**
- `editor/src/MarkdownSpecParser.h` - switched heading/lowercase/anchor normalization paths to shared intake text helpers
- `editor/src/RequirementNormalizationConflictDetector.h` - switched requirement text canonicalization to shared compact-normalization helper
- `editor/src/AcceptanceCriteriaBinding.h` - switched test-skeleton token sanitization to shared intake token sanitizer
**Verification run:**
- `cmake --build editor/build-native --target step574_test step575_test step576_test step577_test step578_test step579_test step580_test step581_test step582_test step583_test` - PASS
- `./editor/build-native/step574_test` - PASS (12/12)
- `./editor/build-native/step575_test` - PASS (12/12)
- `./editor/build-native/step576_test` - PASS (12/12)
- `./editor/build-native/step577_test` - PASS (12/12)
- `./editor/build-native/step578_test` - PASS (8/8)
- `./editor/build-native/step579_test` - PASS (12/12)
- `./editor/build-native/step580_test` - PASS (12/12)
- `./editor/build-native/step581_test` - PASS (12/12)
- `./editor/build-native/step582_test` - PASS (12/12)
- `./editor/build-native/step583_test` - PASS (8/8)
**Architecture gate check:**
- `editor/src/IntakeTextUtil.h` within header-size limit (`48` <= `600`)
- `editor/src/MarkdownSpecParser.h` within header-size limit (`124` <= `600`)
- `editor/src/RequirementNormalizationConflictDetector.h` within header-size limit (`153` <= `600`)
- `editor/src/AcceptanceCriteriaBinding.h` within header-size limit (`68` <= `600`)
- Shared normalization centralization reduces duplicated string-normalization logic and stays aligned with `ARCHITECTURE.md`