Step 509: add docking reliability audit and deterministic layout rules
This commit is contained in:
@@ -3460,4 +3460,12 @@ target_link_libraries(step508_test PRIVATE
|
||||
tree_sitter_javascript tree_sitter_typescript
|
||||
tree_sitter_java tree_sitter_rust tree_sitter_go)
|
||||
|
||||
# Step 12: Dear ImGui shell scaffolding created (main.cpp exists but not built due to dependencies)
|
||||
add_executable(step509_test tests/step509_test.cpp)
|
||||
target_include_directories(step509_test PRIVATE src)
|
||||
target_link_libraries(step509_test PRIVATE
|
||||
nlohmann_json::nlohmann_json
|
||||
unofficial::tree-sitter::tree-sitter
|
||||
tree_sitter_python tree_sitter_cpp tree_sitter_elisp
|
||||
tree_sitter_javascript tree_sitter_typescript
|
||||
tree_sitter_java tree_sitter_rust tree_sitter_go)
|
||||
|
||||
|
||||
283
editor/src/DockingReliability.h
Normal file
283
editor/src/DockingReliability.h
Normal file
@@ -0,0 +1,283 @@
|
||||
#pragma once
|
||||
// Step 509: Docking Reliability Audit + Deterministic Layout Rules
|
||||
// Headless guardrails for panel drift/visibility issues and deterministic
|
||||
// startup/session-restore layout behavior.
|
||||
|
||||
#include "PanelManager.h"
|
||||
#include "LayoutManager.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
|
||||
struct DockingIssue {
|
||||
std::string code;
|
||||
std::string message;
|
||||
std::string panelId;
|
||||
std::string severity = "warning";
|
||||
};
|
||||
|
||||
struct DockingAuditResult {
|
||||
bool stable = true;
|
||||
bool repaired = false;
|
||||
PanelManager state;
|
||||
std::vector<DockingIssue> issues;
|
||||
std::string fingerprintBefore;
|
||||
std::string fingerprintAfter;
|
||||
};
|
||||
|
||||
class DockingReliability {
|
||||
public:
|
||||
static DockingAuditResult auditAndRepair(const PanelManager& input,
|
||||
bool deterministicReset = false) {
|
||||
DockingAuditResult out;
|
||||
out.state = input;
|
||||
out.fingerprintBefore = layoutFingerprint(input);
|
||||
|
||||
ensurePanelsPresent(out.state, out);
|
||||
clampLayout(out.state, out);
|
||||
repairCriticalVisibility(out.state, out);
|
||||
repairEditorDockDrift(out.state, out);
|
||||
repairFocusState(out.state, out);
|
||||
|
||||
if (deterministicReset) {
|
||||
applyDeterministicReset(out.state, out);
|
||||
}
|
||||
|
||||
out.fingerprintAfter = layoutFingerprint(out.state);
|
||||
out.stable = out.issues.empty();
|
||||
out.repaired = out.fingerprintBefore != out.fingerprintAfter;
|
||||
return out;
|
||||
}
|
||||
|
||||
static PanelManager deterministicStateFromPreset(LayoutPreset preset) {
|
||||
LayoutManager lm;
|
||||
lm.setPreset(preset);
|
||||
const LayoutConfig& cfg = lm.getConfig();
|
||||
|
||||
PanelManager state;
|
||||
int order = 0;
|
||||
for (const auto& panel : cfg.panels) {
|
||||
state.registerPanel(panel.id, panel.id,
|
||||
toDockPosition(panel.direction),
|
||||
"", "layout", order++);
|
||||
state.setVisible(panel.id, panel.visible);
|
||||
}
|
||||
|
||||
state.layout().leftWidth = ratioOr(state, DockDirection::Left, 20.0f);
|
||||
state.layout().rightWidth = ratioOr(state, DockDirection::Right, 20.0f);
|
||||
state.layout().bottomHeight = ratioOr(state, DockDirection::Bottom, 25.0f);
|
||||
state.layout().centerWidth =
|
||||
100.0f - state.layout().leftWidth - state.layout().rightWidth;
|
||||
|
||||
if (state.hasPanel("Editor")) state.focusPanel("Editor");
|
||||
return auditAndRepair(state, true).state;
|
||||
}
|
||||
|
||||
static PanelManager reconcileFromSession(const PanelManager& saved,
|
||||
LayoutPreset preset) {
|
||||
PanelManager merged = deterministicStateFromPreset(preset);
|
||||
for (const auto& p : saved.getPanelList()) {
|
||||
if (!merged.hasPanel(p.id)) continue;
|
||||
merged.setVisible(p.id, p.isVisible);
|
||||
merged.movePanelToDock(p.id, p.currentDock);
|
||||
}
|
||||
if (!saved.getFocusedPanel().empty() && merged.hasPanel(saved.getFocusedPanel())) {
|
||||
merged.focusPanel(saved.getFocusedPanel());
|
||||
}
|
||||
return auditAndRepair(merged, false).state;
|
||||
}
|
||||
|
||||
static std::string layoutFingerprint(const PanelManager& state) {
|
||||
std::ostringstream oss;
|
||||
auto panels = state.getPanelList();
|
||||
oss << "L:" << rounded(state.layout().leftWidth)
|
||||
<< ",R:" << rounded(state.layout().rightWidth)
|
||||
<< ",B:" << rounded(state.layout().bottomHeight)
|
||||
<< ",C:" << rounded(state.layout().centerWidth)
|
||||
<< "|";
|
||||
for (const auto& p : panels) {
|
||||
oss << p.id << ":" << dockPositionToString(p.currentDock)
|
||||
<< ":" << (p.isVisible ? "1" : "0")
|
||||
<< ":" << p.order << ";";
|
||||
}
|
||||
oss << "F:" << state.getFocusedPanel();
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
private:
|
||||
static int rounded(float v) {
|
||||
return static_cast<int>(std::round(v));
|
||||
}
|
||||
|
||||
static bool isCriticalPanelId(const std::string& id) {
|
||||
return id == "code-editor" || id == "Editor";
|
||||
}
|
||||
|
||||
static DockPosition toDockPosition(DockDirection d) {
|
||||
switch (d) {
|
||||
case DockDirection::Left: return DockPosition::Left;
|
||||
case DockDirection::Right: return DockPosition::Right;
|
||||
case DockDirection::Bottom: return DockPosition::Bottom;
|
||||
case DockDirection::Top: return DockPosition::CenterTop;
|
||||
case DockDirection::Center: return DockPosition::CenterTop;
|
||||
}
|
||||
return DockPosition::CenterTop;
|
||||
}
|
||||
|
||||
static float ratioOr(const PanelManager& state,
|
||||
DockDirection dir,
|
||||
float fallback) {
|
||||
// Reconstruct from panel width hints if present in the source config
|
||||
// is not available. Use conservative defaults for deterministic startup.
|
||||
(void)state;
|
||||
(void)dir;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
static void addIssue(DockingAuditResult& out,
|
||||
const std::string& code,
|
||||
const std::string& message,
|
||||
const std::string& panelId = "",
|
||||
const std::string& severity = "warning") {
|
||||
DockingIssue i;
|
||||
i.code = code;
|
||||
i.message = message;
|
||||
i.panelId = panelId;
|
||||
i.severity = severity;
|
||||
out.issues.push_back(i);
|
||||
}
|
||||
|
||||
static void ensurePanelsPresent(PanelManager& state,
|
||||
DockingAuditResult& out) {
|
||||
if (state.panelCount() == 0) {
|
||||
state.registerDefaults();
|
||||
addIssue(out, "D001", "Session contained no panels; restored default panel set", "", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.hasPanel("code-editor") && !state.hasPanel("Editor")) {
|
||||
state.registerPanel("code-editor", "Code Editor", DockPosition::CenterTop, "", "editor", 1);
|
||||
addIssue(out, "D002", "Critical editor panel missing; inserted fallback code-editor", "code-editor", "error");
|
||||
}
|
||||
}
|
||||
|
||||
static void clampLayout(PanelManager& state,
|
||||
DockingAuditResult& out) {
|
||||
bool touched = false;
|
||||
auto& l = state.layout();
|
||||
|
||||
if (l.leftWidth < 5.0f) {
|
||||
l.leftWidth = 5.0f;
|
||||
touched = true;
|
||||
}
|
||||
if (l.leftWidth > 45.0f) {
|
||||
l.leftWidth = 45.0f;
|
||||
touched = true;
|
||||
}
|
||||
if (l.rightWidth < 5.0f) {
|
||||
l.rightWidth = 5.0f;
|
||||
touched = true;
|
||||
}
|
||||
if (l.rightWidth > 45.0f) {
|
||||
l.rightWidth = 45.0f;
|
||||
touched = true;
|
||||
}
|
||||
if (l.bottomHeight < 10.0f) {
|
||||
l.bottomHeight = 10.0f;
|
||||
touched = true;
|
||||
}
|
||||
if (l.bottomHeight > 60.0f) {
|
||||
l.bottomHeight = 60.0f;
|
||||
touched = true;
|
||||
}
|
||||
|
||||
l.centerWidth = 100.0f - l.leftWidth - l.rightWidth;
|
||||
if (l.centerWidth < 10.0f) {
|
||||
// Rebalance sides deterministically to guarantee editor viewport.
|
||||
l.leftWidth = 20.0f;
|
||||
l.rightWidth = 20.0f;
|
||||
l.centerWidth = 60.0f;
|
||||
touched = true;
|
||||
}
|
||||
|
||||
if (touched) {
|
||||
addIssue(out, "D003", "Layout ratios out of bounds; clamped to deterministic safe ranges");
|
||||
}
|
||||
}
|
||||
|
||||
static void repairCriticalVisibility(PanelManager& state,
|
||||
DockingAuditResult& out) {
|
||||
bool hasVisibleCenter = false;
|
||||
for (const auto& p : state.getVisiblePanels()) {
|
||||
if (p.currentDock == DockPosition::CenterTop ||
|
||||
p.currentDock == DockPosition::CenterBottom) {
|
||||
hasVisibleCenter = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasVisibleCenter) {
|
||||
if (state.hasPanel("code-editor")) {
|
||||
state.setVisible("code-editor", true);
|
||||
addIssue(out, "D004", "No visible center panel; forced code-editor visible", "code-editor", "error");
|
||||
} else if (state.hasPanel("Editor")) {
|
||||
state.setVisible("Editor", true);
|
||||
addIssue(out, "D004", "No visible center panel; forced Editor visible", "Editor", "error");
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& p : state.getPanelList()) {
|
||||
if (isCriticalPanelId(p.id) && !p.isVisible) {
|
||||
state.setVisible(p.id, true);
|
||||
addIssue(out, "D005", "Critical editor panel hidden; forced visible", p.id, "error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void repairEditorDockDrift(PanelManager& state,
|
||||
DockingAuditResult& out) {
|
||||
for (const auto& p : state.getPanelList()) {
|
||||
if (!isCriticalPanelId(p.id)) continue;
|
||||
if (!(p.currentDock == DockPosition::CenterTop ||
|
||||
p.currentDock == DockPosition::CenterBottom)) {
|
||||
state.movePanelToDock(p.id, p.defaultDock);
|
||||
addIssue(out, "D006", "Editor panel drifted from center; restored to default dock", p.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void repairFocusState(PanelManager& state,
|
||||
DockingAuditResult& out) {
|
||||
std::string focused = state.getFocusedPanel();
|
||||
if (!focused.empty() && state.hasPanel(focused)) return;
|
||||
|
||||
if (state.hasPanel("code-editor")) {
|
||||
state.focusPanel("code-editor");
|
||||
addIssue(out, "D007", "Focused panel invalid; restored focus to code-editor");
|
||||
return;
|
||||
}
|
||||
if (state.hasPanel("Editor")) {
|
||||
state.focusPanel("Editor");
|
||||
addIssue(out, "D007", "Focused panel invalid; restored focus to Editor");
|
||||
return;
|
||||
}
|
||||
|
||||
auto panels = state.getPanelList();
|
||||
if (!panels.empty()) {
|
||||
state.focusPanel(panels.front().id);
|
||||
addIssue(out, "D007", "Focused panel invalid; restored to first registered panel");
|
||||
}
|
||||
}
|
||||
|
||||
static void applyDeterministicReset(PanelManager& state,
|
||||
DockingAuditResult& out) {
|
||||
for (const auto& p : state.getPanelList()) {
|
||||
state.movePanelToDock(p.id, p.defaultDock);
|
||||
if (isCriticalPanelId(p.id)) state.setVisible(p.id, true);
|
||||
}
|
||||
repairFocusState(state, out);
|
||||
addIssue(out, "D008", "Deterministic reset applied", "", "info");
|
||||
}
|
||||
};
|
||||
180
editor/tests/step509_test.cpp
Normal file
180
editor/tests/step509_test.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
// Step 509: Docking Reliability Audit + Deterministic Layout Rules (12 tests)
|
||||
|
||||
#include "DockingReliability.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
static int passed = 0, failed = 0;
|
||||
#define TEST(name) { std::cout << " " << #name << "... "; }
|
||||
#define PASS() { std::cout << "PASS\n"; ++passed; }
|
||||
#define FAIL(msg) { std::cout << "FAIL: " << msg << "\n"; ++failed; }
|
||||
#define CHECK(cond, msg) if (!(cond)) { FAIL(msg); return; } else {}
|
||||
|
||||
static PanelManager makeBaseline() {
|
||||
PanelManager pm;
|
||||
pm.registerDefaults();
|
||||
pm.focusPanel("code-editor");
|
||||
return pm;
|
||||
}
|
||||
|
||||
void test_stable_default_state_has_no_issues() {
|
||||
TEST(stable_default_state_has_no_issues);
|
||||
auto result = DockingReliability::auditAndRepair(makeBaseline());
|
||||
CHECK(result.stable, "expected stable baseline state");
|
||||
CHECK(result.issues.empty(), "expected no issues");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_invalid_layout_ratios_are_clamped() {
|
||||
TEST(invalid_layout_ratios_are_clamped);
|
||||
auto pm = makeBaseline();
|
||||
pm.layout().leftWidth = -10.0f;
|
||||
pm.layout().rightWidth = 95.0f;
|
||||
pm.layout().bottomHeight = 2.0f;
|
||||
auto result = DockingReliability::auditAndRepair(pm);
|
||||
CHECK(result.state.layout().leftWidth >= 5.0f, "left not clamped");
|
||||
CHECK(result.state.layout().rightWidth <= 45.0f, "right not clamped");
|
||||
CHECK(result.state.layout().bottomHeight >= 10.0f, "bottom not clamped");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_hidden_editor_is_forced_visible() {
|
||||
TEST(hidden_editor_is_forced_visible);
|
||||
auto pm = makeBaseline();
|
||||
pm.setVisible("code-editor", false);
|
||||
auto result = DockingReliability::auditAndRepair(pm);
|
||||
CHECK(result.state.isVisible("code-editor"), "editor should be visible");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_editor_dock_drift_is_repaired() {
|
||||
TEST(editor_dock_drift_is_repaired);
|
||||
auto pm = makeBaseline();
|
||||
pm.movePanelToDock("code-editor", DockPosition::Left);
|
||||
auto result = DockingReliability::auditAndRepair(pm);
|
||||
auto p = result.state.getPanel("code-editor");
|
||||
CHECK(p.currentDock == p.defaultDock, "editor dock should reset to default");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_empty_panel_set_restores_defaults() {
|
||||
TEST(empty_panel_set_restores_defaults);
|
||||
PanelManager pm;
|
||||
auto result = DockingReliability::auditAndRepair(pm);
|
||||
CHECK(result.state.panelCount() >= 8, "expected default panels restored");
|
||||
CHECK(result.state.hasPanel("code-editor"), "expected code-editor panel");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_deterministic_reset_normalizes_drift() {
|
||||
TEST(deterministic_reset_normalizes_drift);
|
||||
auto pm = makeBaseline();
|
||||
pm.movePanelToDock("file-tree", DockPosition::Right);
|
||||
pm.movePanelToDock("code-editor", DockPosition::Bottom);
|
||||
pm.setVisible("diagnostics", false);
|
||||
auto result = DockingReliability::auditAndRepair(pm, true);
|
||||
CHECK(result.state.getPanel("file-tree").currentDock ==
|
||||
result.state.getPanel("file-tree").defaultDock,
|
||||
"file-tree should match default dock");
|
||||
CHECK(result.state.getPanel("code-editor").currentDock ==
|
||||
result.state.getPanel("code-editor").defaultDock,
|
||||
"editor should match default dock");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_deterministic_reset_has_stable_fingerprint() {
|
||||
TEST(deterministic_reset_has_stable_fingerprint);
|
||||
auto pm = makeBaseline();
|
||||
pm.movePanelToDock("workflow", DockPosition::Left);
|
||||
auto a = DockingReliability::auditAndRepair(pm, true);
|
||||
auto b = DockingReliability::auditAndRepair(a.state, true);
|
||||
CHECK(a.fingerprintAfter == b.fingerprintAfter, "fingerprint should be deterministic");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_invalid_focus_is_repaired_to_editor() {
|
||||
TEST(invalid_focus_is_repaired_to_editor);
|
||||
auto pm = makeBaseline();
|
||||
pm.focusPanel("ghost");
|
||||
auto result = DockingReliability::auditAndRepair(pm);
|
||||
CHECK(result.state.getFocusedPanel() == "code-editor", "focus should be repaired");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_missing_editor_panel_is_inserted() {
|
||||
TEST(missing_editor_panel_is_inserted);
|
||||
auto pm = makeBaseline();
|
||||
auto j = pm.toJson();
|
||||
nlohmann::json kept = nlohmann::json::array();
|
||||
for (const auto& p : j["panels"]) {
|
||||
if (p.value("id", "") != "code-editor") kept.push_back(p);
|
||||
}
|
||||
j["panels"] = kept;
|
||||
auto broken = PanelManager::fromJson(j);
|
||||
auto result = DockingReliability::auditAndRepair(broken);
|
||||
CHECK(result.state.hasPanel("code-editor"), "editor should be reinserted");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_no_visible_center_panel_is_fixed() {
|
||||
TEST(no_visible_center_panel_is_fixed);
|
||||
auto pm = makeBaseline();
|
||||
pm.setVisible("code-editor", false);
|
||||
auto result = DockingReliability::auditAndRepair(pm);
|
||||
bool hasCenter = false;
|
||||
for (const auto& p : result.state.getVisiblePanels()) {
|
||||
if (p.currentDock == DockPosition::CenterTop ||
|
||||
p.currentDock == DockPosition::CenterBottom) {
|
||||
hasCenter = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CHECK(hasCenter, "at least one center panel should be visible");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_reconcile_from_session_keeps_known_panels() {
|
||||
TEST(reconcile_from_session_keeps_known_panels);
|
||||
auto saved = makeBaseline();
|
||||
saved.movePanelToDock("Explorer", DockPosition::Right); // unknown in defaults, ignored by merge
|
||||
saved.movePanelToDock("Panel", DockPosition::Left); // unknown in defaults, ignored by merge
|
||||
auto merged = DockingReliability::reconcileFromSession(saved, LayoutPreset::VSCode);
|
||||
CHECK(merged.hasPanel("Editor"), "preset panel should exist");
|
||||
CHECK(merged.hasPanel("Explorer"), "preset explorer should exist");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_issue_codes_are_reported_for_recovery_paths() {
|
||||
TEST(issue_codes_are_reported_for_recovery_paths);
|
||||
PanelManager pm;
|
||||
auto result = DockingReliability::auditAndRepair(pm, true);
|
||||
bool hasD001 = false;
|
||||
bool hasD008 = false;
|
||||
for (const auto& i : result.issues) {
|
||||
if (i.code == "D001") hasD001 = true;
|
||||
if (i.code == "D008") hasD008 = true;
|
||||
}
|
||||
CHECK(hasD001, "expected empty-session recovery code D001");
|
||||
CHECK(hasD008, "expected deterministic reset code D008");
|
||||
PASS();
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "Step 509: Docking Reliability Audit + Deterministic Layout Rules\n";
|
||||
|
||||
test_stable_default_state_has_no_issues(); // 1
|
||||
test_invalid_layout_ratios_are_clamped(); // 2
|
||||
test_hidden_editor_is_forced_visible(); // 3
|
||||
test_editor_dock_drift_is_repaired(); // 4
|
||||
test_empty_panel_set_restores_defaults(); // 5
|
||||
test_deterministic_reset_normalizes_drift(); // 6
|
||||
test_deterministic_reset_has_stable_fingerprint(); // 7
|
||||
test_invalid_focus_is_repaired_to_editor(); // 8
|
||||
test_missing_editor_panel_is_inserted(); // 9
|
||||
test_no_visible_center_panel_is_fixed(); // 10
|
||||
test_reconcile_from_session_keeps_known_panels(); // 11
|
||||
test_issue_codes_are_reported_for_recovery_paths(); // 12
|
||||
|
||||
std::cout << "\nResults: " << passed << "/" << (passed + failed) << " passed\n";
|
||||
return failed == 0 ? 0 : 1;
|
||||
}
|
||||
43
progress.md
43
progress.md
@@ -7995,3 +7995,46 @@ following the same structure pattern as previous sprint plans:
|
||||
|
||||
These plans intentionally distribute work across multiple sprints (rather than a
|
||||
single sprint) to preserve implementation quality and maintainability.
|
||||
|
||||
### Step 509: Docking Reliability Audit + Deterministic Layout Rules
|
||||
**Status:** PASS (12/12 tests)
|
||||
|
||||
Implements a headless docking reliability guard that audits panel/layout state,
|
||||
repairs drift and hidden-critical-panel failures, and provides deterministic
|
||||
startup/session-restore normalization.
|
||||
|
||||
**Files added:**
|
||||
- `editor/src/DockingReliability.h` - docking reliability module:
|
||||
- invariant audit + repair pipeline (`auditAndRepair`)
|
||||
- deterministic reset behavior for startup/recovery paths
|
||||
- deterministic preset materialization (`deterministicStateFromPreset`)
|
||||
- session restore reconciliation (`reconcileFromSession`)
|
||||
- canonical layout fingerprinting for stability checks
|
||||
- explicit issue code taxonomy (`D001`-`D008`)
|
||||
- `editor/tests/step509_test.cpp` - 12 tests covering:
|
||||
- stable baseline (no false positives)
|
||||
- ratio clamping and center-width safety floor
|
||||
- hidden editor recovery
|
||||
- editor dock drift recovery
|
||||
- empty-session panel restoration
|
||||
- deterministic reset behavior and fingerprint stability
|
||||
- invalid focus recovery
|
||||
- missing editor insertion
|
||||
- center visibility enforcement
|
||||
- session reconciliation semantics
|
||||
- recovery issue-code emission
|
||||
|
||||
**Files modified:**
|
||||
- `editor/CMakeLists.txt` - `step509_test` target
|
||||
|
||||
**Verification run:**
|
||||
- `cmake -S editor -B editor/build-native` - PASS
|
||||
- `cmake --build editor/build-native --target step509_test` - PASS
|
||||
- `./editor/build-native/step509_test` - PASS (12/12)
|
||||
- `./editor/build-native/step508_test` - PASS (8/8) regression coverage
|
||||
|
||||
**Architecture gate check:**
|
||||
- `editor/src/DockingReliability.h` within header-size limit (`283` <= `600`)
|
||||
- `editor/tests/step509_test.cpp` within test-file size guidance (`180` lines)
|
||||
- Header-only architecture and naming conventions remain aligned with `ARCHITECTURE.md`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user