diff --git a/editor/src/CapabilityDiscoveryPanels.h b/editor/src/CapabilityDiscoveryPanels.h index 694ad91..a08e6d5 100644 --- a/editor/src/CapabilityDiscoveryPanels.h +++ b/editor/src/CapabilityDiscoveryPanels.h @@ -1,6 +1,8 @@ #pragma once // Step 586: Capability Discovery Panels +#include "ProductizationValidationUtil.h" + #include #include #include @@ -20,8 +22,10 @@ public: std::string* error) { if (!error) return false; error->clear(); - if (categoryId.empty()) return fail(error, "category_id_missing"); - if (title.empty()) return fail(error, "category_title_missing"); + if (!hasRequiredProductIds(categoryId, title)) { + if (categoryId.empty()) return fail(error, "category_id_missing"); + return fail(error, "category_title_missing"); + } if (categories_.count(categoryId) != 0) return fail(error, "category_duplicate"); CapabilityCategory c; c.categoryId = categoryId; diff --git a/editor/src/ProductizationValidationUtil.h b/editor/src/ProductizationValidationUtil.h new file mode 100644 index 0000000..7a68668 --- /dev/null +++ b/editor/src/ProductizationValidationUtil.h @@ -0,0 +1,18 @@ +#pragma once +// Sprint 33 refactor: shared productization validation helpers + +#include + +inline bool hasRequiredProductIds(const std::string& a, const std::string& b) { + return !a.empty() && !b.empty(); +} + +inline bool isValidHexColor7(const std::string& c) { + if (c.size() != 7 || c[0] != '#') return false; + for (size_t i = 1; i < c.size(); ++i) { + const char x = c[i]; + const bool hex = (x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F'); + if (!hex) return false; + } + return true; +} diff --git a/editor/src/ValueForwardOnboardingFlow.h b/editor/src/ValueForwardOnboardingFlow.h index 2e441ad..fef7586 100644 --- a/editor/src/ValueForwardOnboardingFlow.h +++ b/editor/src/ValueForwardOnboardingFlow.h @@ -1,6 +1,8 @@ #pragma once // Step 584: Value-Forward Onboarding Flow +#include "ProductizationValidationUtil.h" + #include #include @@ -33,7 +35,7 @@ public: std::string* error) { if (!state || !error) return false; error->clear(); - if (profileId.empty()) { + if (!hasRequiredProductIds(profileId, "profile")) { *error = "profile_id_missing"; return false; } diff --git a/editor/src/WorkflowVisualizationV2.h b/editor/src/WorkflowVisualizationV2.h index a0b0232..f57d1b3 100644 --- a/editor/src/WorkflowVisualizationV2.h +++ b/editor/src/WorkflowVisualizationV2.h @@ -1,6 +1,8 @@ #pragma once // Step 585: Workflow Visualization 2.0 +#include "ProductizationValidationUtil.h" + #include #include #include @@ -40,9 +42,11 @@ public: std::string* error) { if (!graph || !error) return false; error->clear(); - if (node.nodeId.empty()) return fail(error, "node_id_missing"); - if (node.label.empty()) return fail(error, "node_label_missing"); - if (!isValidColor(node.accentColorHex)) return fail(error, "node_color_invalid"); + if (!hasRequiredProductIds(node.nodeId, node.label)) { + if (node.nodeId.empty()) return fail(error, "node_id_missing"); + return fail(error, "node_label_missing"); + } + if (!isValidHexColor7(node.accentColorHex)) return fail(error, "node_color_invalid"); if (findNode(*graph, node.nodeId) != nullptr) return fail(error, "node_duplicate"); graph->nodes.push_back(node); return true; @@ -94,16 +98,6 @@ private: return false; } - static bool isValidColor(const std::string& c) { - if (c.size() != 7 || c[0] != '#') return false; - for (size_t i = 1; i < c.size(); ++i) { - const char x = c[i]; - const bool hex = (x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F'); - if (!hex) return false; - } - return true; - } - static const WorkflowNodeVisual* findNode(const WorkflowVisualizationGraph& graph, const std::string& nodeId) { for (const auto& node : graph.nodes) if (node.nodeId == nodeId) return &node; diff --git a/progress.md b/progress.md index 2d4025f..46ac523 100644 --- a/progress.md +++ b/progress.md @@ -11304,3 +11304,39 @@ operational-hardening readiness into final program-level outcome signals. - **New tests in this sprint plan:** 112/112 passing - **Phase 33a (584-588):** 56/56 passing - **Phase 33b (589-593):** 56/56 passing + +### Sprint 33 End Refactor Pass (Architecture Compliance) +**Status:** PASS (112/112 tests revalidated) + +Performed a focused post-sprint refactor to centralize repeated productization +validation logic across onboarding/workflow/capability modules. + +**Files added:** +- `editor/src/ProductizationValidationUtil.h` - shared productization validation helpers: + - shared non-empty dual-id/title guard + - shared `#RRGGBB` hex-color validation helper + +**Files modified:** +- `editor/src/ValueForwardOnboardingFlow.h` - switched onboarding profile validation to shared product-id helper +- `editor/src/WorkflowVisualizationV2.h` - switched node id/label + color validation to shared productization helpers +- `editor/src/CapabilityDiscoveryPanels.h` - switched category id/title validation to shared product-id helper + +**Verification run:** +- `cmake --build editor/build-native --target step584_test step585_test step586_test step587_test step588_test step589_test step590_test step591_test step592_test step593_test` - PASS +- `./editor/build-native/step584_test` - PASS (12/12) +- `./editor/build-native/step585_test` - PASS (12/12) +- `./editor/build-native/step586_test` - PASS (12/12) +- `./editor/build-native/step587_test` - PASS (12/12) +- `./editor/build-native/step588_test` - PASS (8/8) +- `./editor/build-native/step589_test` - PASS (12/12) +- `./editor/build-native/step590_test` - PASS (12/12) +- `./editor/build-native/step591_test` - PASS (12/12) +- `./editor/build-native/step592_test` - PASS (12/12) +- `./editor/build-native/step593_test` - PASS (8/8) + +**Architecture gate check:** +- `editor/src/ProductizationValidationUtil.h` within header-size limit (`18` <= `600`) +- `editor/src/ValueForwardOnboardingFlow.h` within header-size limit (`107` <= `600`) +- `editor/src/WorkflowVisualizationV2.h` within header-size limit (`112` <= `600`) +- `editor/src/CapabilityDiscoveryPanels.h` within header-size limit (`90` <= `600`) +- Shared validation centralization reduces duplicated product-surface guard logic and remains aligned with `ARCHITECTURE.md`