Step 115: wire orchestrator
This commit is contained in:
@@ -218,6 +218,7 @@ All 38 steps implemented and passing. Each step has a corresponding test (`step1
|
||||
- [x] Step 112: **IMPLEMENTED** — Breadcrumb navigation with scope roles (1/1 tests pass)
|
||||
- [x] Step 113: **IMPLEMENTED** — Project-wide search panel with regex and glob filters (3/3 tests pass)
|
||||
- [x] Step 114: **IMPLEMENTED** — Go-to-line popup with :line:col parsing (4/4 tests pass)
|
||||
- [x] Step 115: **IMPLEMENTED** — Orchestrator wired for structured mutations; Emacs config path setting (3/3 tests pass)
|
||||
|
||||
---
|
||||
|
||||
@@ -315,6 +316,7 @@ vcpkg's imgui 1.91.9 removed the `sdl2-binding` feature (only `sdl3-binding` exi
|
||||
**Step 112:** Compile and pass (1/1)
|
||||
**Step 113:** Compile and pass (3/3)
|
||||
**Step 114:** Compile and pass (4/4)
|
||||
**Step 115:** Compile and pass (3/3)
|
||||
|
||||
---
|
||||
|
||||
@@ -366,7 +368,7 @@ vcpkg's imgui 1.91.9 removed the `sdl2-binding` feature (only `sdl3-binding` exi
|
||||
|
||||
## What's Next
|
||||
|
||||
Sprint 4 in progress. Step 114 (go-to-line) done. Next: Step 115 (wire orchestrator).
|
||||
Sprint 4 in progress. Step 115 (wire orchestrator) done. Next: Step 116 (project save/load).
|
||||
|
||||
---
|
||||
|
||||
@@ -442,3 +444,4 @@ Sprint 4 in progress. Step 114 (go-to-line) done. Next: Step 115 (wire orchestra
|
||||
| 2026-02-09 | Codex | Step 112: Breadcrumb navigation with scope roles. 1/1 tests pass. |
|
||||
| 2026-02-09 | Codex | Step 113: Project-wide search panel with regex and glob filters. 3/3 tests pass. |
|
||||
| 2026-02-09 | Codex | Step 114: Go-to-line popup with :line:col parsing. 4/4 tests pass. |
|
||||
| 2026-02-09 | Codex | Step 115: Orchestrator wired for structured mutations; Emacs config path setting. 3/3 tests pass. |
|
||||
|
||||
@@ -618,6 +618,10 @@ add_executable(step114_test tests/step114_test.cpp)
|
||||
target_include_directories(step114_test PRIVATE src)
|
||||
target_link_libraries(step114_test PRIVATE nlohmann_json::nlohmann_json)
|
||||
|
||||
add_executable(step115_test tests/step115_test.cpp)
|
||||
target_include_directories(step115_test PRIVATE src)
|
||||
target_link_libraries(step115_test PRIVATE nlohmann_json::nlohmann_json)
|
||||
|
||||
find_package(SDL2 CONFIG REQUIRED)
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(glad CONFIG REQUIRED)
|
||||
|
||||
@@ -23,6 +23,9 @@ public:
|
||||
|
||||
const std::vector<LSPServerConfig>& getLSPServers() const { return lspServers_; }
|
||||
std::vector<LSPServerConfig>& getLSPServersMutable() { return lspServers_; }
|
||||
const std::string& getEmacsConfigPath() const { return emacsConfigPath_; }
|
||||
void setEmacsConfigPath(const std::string& path) { emacsConfigPath_ = path; }
|
||||
std::string& getEmacsConfigPathMutable() { return emacsConfigPath_; }
|
||||
|
||||
LSPServerConfig* getServer(const std::string& language) {
|
||||
for (auto& s : lspServers_) {
|
||||
@@ -63,6 +66,7 @@ public:
|
||||
|
||||
private:
|
||||
std::vector<LSPServerConfig> lspServers_;
|
||||
std::string emacsConfigPath_;
|
||||
|
||||
void loadDefaults() {
|
||||
lspServers_.push_back(makeConfig("python", "pylsp", {}));
|
||||
@@ -72,6 +76,14 @@ private:
|
||||
lspServers_.push_back(makeConfig("javascript", "typescript-language-server", {"--stdio"}));
|
||||
lspServers_.push_back(makeConfig("typescript", "typescript-language-server", {"--stdio"}));
|
||||
lspServers_.push_back(makeConfig("java", "jdtls", {}));
|
||||
|
||||
const char* home = std::getenv("USERPROFILE");
|
||||
if (!home) home = std::getenv("HOME");
|
||||
if (home) {
|
||||
emacsConfigPath_ = (std::filesystem::path(home) / ".emacs.d").string();
|
||||
} else {
|
||||
emacsConfigPath_ = ".emacs.d";
|
||||
}
|
||||
}
|
||||
|
||||
static LSPServerConfig makeConfig(const std::string& lang,
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "Breadcrumbs.h"
|
||||
#include "ProjectSearch.h"
|
||||
#include "GoToLine.h"
|
||||
#include "Orchestrator.h"
|
||||
#include "ast/Serialization.h"
|
||||
#include "ast/Generator.h"
|
||||
#include "ast/Annotation.h"
|
||||
@@ -160,6 +161,8 @@ struct EditorState {
|
||||
std::vector<EditorDiagnostic> whetstoneDiagnostics;
|
||||
SettingsManager settings;
|
||||
bool showLspSettings = false;
|
||||
Orchestrator orchestrator;
|
||||
bool orchestratorDirty = true;
|
||||
ASTMutationAPI mutator;
|
||||
std::vector<MemoryStrategyInference::Suggestion> suggestions;
|
||||
bool showSuggestionPopup = false;
|
||||
@@ -334,6 +337,7 @@ struct EditorState {
|
||||
state->bufferMode = mode;
|
||||
activeBuffer = state.get();
|
||||
bufferStates[path] = std::move(state);
|
||||
orchestratorDirty = true;
|
||||
if (path.rfind("(untitled", 0) != 0) watcher.watch(path);
|
||||
if (lsp && path.rfind("(untitled", 0) != 0) {
|
||||
lsp->didOpen(toFileUri(path), language, content, activeBuffer->lspVersion);
|
||||
@@ -420,6 +424,7 @@ struct EditorState {
|
||||
if (!buffers.hasBuffer(path)) return;
|
||||
buffers.switchToBuffer(path);
|
||||
activeBuffer = bufferStates[path].get();
|
||||
orchestratorDirty = true;
|
||||
symbolsPending = true;
|
||||
symbolsLastChange = ImGui::GetTime();
|
||||
if (lsp) lsp->clearDocumentSymbols();
|
||||
@@ -473,6 +478,35 @@ struct EditorState {
|
||||
registerCommands();
|
||||
}
|
||||
|
||||
void syncOrchestratorFromActive() {
|
||||
if (!active()) return;
|
||||
if (!isStructured()) return;
|
||||
Module* ast = active()->sync.getAST();
|
||||
if (!ast) return;
|
||||
orchestrator.setAST(cloneModule(ast));
|
||||
orchestratorDirty = false;
|
||||
}
|
||||
|
||||
void applyOrchestratorToActive() {
|
||||
if (!active()) return;
|
||||
if (!isStructured()) return;
|
||||
Module* ast = orchestrator.getAST();
|
||||
if (!ast) return;
|
||||
active()->sync.setAST(cloneModule(ast));
|
||||
active()->incrementalOptimizer.setRoot(active()->sync.getAST());
|
||||
refreshActiveTextFromAST();
|
||||
orchestratorDirty = false;
|
||||
}
|
||||
|
||||
Module* mutationAST() {
|
||||
if (!active()) return nullptr;
|
||||
if (!isStructured()) return nullptr;
|
||||
if (orchestratorDirty || !orchestrator.getAST()) {
|
||||
syncOrchestratorFromActive();
|
||||
}
|
||||
return orchestrator.getAST();
|
||||
}
|
||||
|
||||
void registerCommand(const std::string& id,
|
||||
const std::string& label,
|
||||
const std::string& shortcut,
|
||||
@@ -591,6 +625,7 @@ struct EditorState {
|
||||
active()->sync.syncNow();
|
||||
active()->incrementalOptimizer.setRoot(active()->sync.getAST());
|
||||
}
|
||||
orchestratorDirty = true;
|
||||
active()->highlightsDirty = true;
|
||||
}
|
||||
|
||||
@@ -603,6 +638,7 @@ struct EditorState {
|
||||
active()->sync.syncNow();
|
||||
active()->incrementalOptimizer.setRoot(active()->sync.getAST());
|
||||
}
|
||||
orchestratorDirty = true;
|
||||
active()->highlightsDirty = true;
|
||||
active()->generatedHighlightsDirty = true;
|
||||
active()->modified = true;
|
||||
@@ -624,6 +660,7 @@ struct EditorState {
|
||||
active()->sync.syncNow();
|
||||
active()->incrementalOptimizer.setRoot(active()->sync.getAST());
|
||||
}
|
||||
orchestratorDirty = true;
|
||||
active()->highlightsDirty = true;
|
||||
active()->generatedHighlightsDirty = true;
|
||||
}
|
||||
@@ -637,6 +674,7 @@ struct EditorState {
|
||||
active()->sync.syncNow();
|
||||
active()->incrementalOptimizer.setRoot(active()->sync.getAST());
|
||||
}
|
||||
orchestratorDirty = true;
|
||||
active()->highlightsDirty = true;
|
||||
active()->generatedHighlightsDirty = true;
|
||||
}
|
||||
@@ -2114,6 +2152,10 @@ int main(int, char**) {
|
||||
if (state.showLspSettings) {
|
||||
ImGui::Begin("LSP Servers", &state.showLspSettings);
|
||||
ImGui::PushFont(uiFont);
|
||||
ImGui::TextUnformatted("Emacs Config");
|
||||
ImGui::SetNextItemWidth(320);
|
||||
InputTextStr("Config Path", &state.settings.getEmacsConfigPathMutable(), ImGuiInputTextFlags_None);
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("Auto-Detect")) {
|
||||
state.settings.autoDetect();
|
||||
}
|
||||
@@ -2201,7 +2243,7 @@ int main(int, char**) {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Apply")) {
|
||||
state.refactorError.clear();
|
||||
Module* ast = state.activeAST();
|
||||
Module* ast = state.mutationAST();
|
||||
RefactorPlan plan;
|
||||
if (state.refactorAction == 1) {
|
||||
plan = buildRenameVariablePlan(ast, state.refactorNameA, state.refactorNameB);
|
||||
@@ -2221,7 +2263,7 @@ int main(int, char**) {
|
||||
} else {
|
||||
state.outputLog += "Refactor applied (" +
|
||||
std::to_string(res.appliedCount) + " mutations).\n";
|
||||
state.refreshActiveTextFromAST();
|
||||
state.applyOrchestratorToActive();
|
||||
state.showRefactorPopup = false;
|
||||
}
|
||||
}
|
||||
@@ -2651,7 +2693,7 @@ int main(int, char**) {
|
||||
ImGui::TextWrapped("%s", state.suggestionPopup.reason.c_str());
|
||||
ImGui::Text("Confidence: %.2f", state.suggestionPopup.confidence);
|
||||
if (ImGui::Button("Apply")) {
|
||||
Module* ast = state.active() ? state.active()->sync.getAST() : nullptr;
|
||||
Module* ast = state.mutationAST();
|
||||
if (ast) {
|
||||
ASTNode* target = findNodeById(ast, state.suggestionPopup.nodeId);
|
||||
if (target) {
|
||||
@@ -2665,6 +2707,7 @@ int main(int, char**) {
|
||||
state.mutator.setRoot(ast);
|
||||
auto res2 = state.mutator.insertNode(target->id, "annotations", anno);
|
||||
if (!res2.error.empty()) state.outputLog += res2.error + "\n";
|
||||
state.applyOrchestratorToActive();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2748,12 +2791,13 @@ int main(int, char**) {
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupContextWindow("AnnotationContext", ImGuiPopupFlags_MouseButtonRight)) {
|
||||
Module* ast = state.active() ? state.active()->sync.getAST() : nullptr;
|
||||
Module* ast = state.mutationAST();
|
||||
int lineZero = state.active() ? std::max(0, state.active()->cursorLine - 1) : 0;
|
||||
ASTNode* target = ast ? findAnnotationTarget(ast, lineZero) : nullptr;
|
||||
if (!target) {
|
||||
ImGui::TextDisabled("No annotatable symbol on this line.");
|
||||
} else {
|
||||
bool mutated = false;
|
||||
ImGui::Text("Target: %s", nodeDisplayName(target).c_str());
|
||||
ImGui::Separator();
|
||||
|
||||
@@ -2766,6 +2810,7 @@ int main(int, char**) {
|
||||
state.mutator.setRoot(ast);
|
||||
auto res = state.mutator.insertNode(target->id, "annotations", anno);
|
||||
if (!res.error.empty()) state.outputLog += res.error + "\n";
|
||||
if (res.error.empty()) mutated = true;
|
||||
}
|
||||
}
|
||||
if (ImGui::MenuItem("@Owner(Single)")) {
|
||||
@@ -2776,6 +2821,7 @@ int main(int, char**) {
|
||||
state.mutator.setRoot(ast);
|
||||
auto res = state.mutator.insertNode(target->id, "annotations", anno);
|
||||
if (!res.error.empty()) state.outputLog += res.error + "\n";
|
||||
if (res.error.empty()) mutated = true;
|
||||
}
|
||||
}
|
||||
if (ImGui::MenuItem("@Deallocate(Explicit)")) {
|
||||
@@ -2786,6 +2832,7 @@ int main(int, char**) {
|
||||
state.mutator.setRoot(ast);
|
||||
auto res = state.mutator.insertNode(target->id, "annotations", anno);
|
||||
if (!res.error.empty()) state.outputLog += res.error + "\n";
|
||||
if (res.error.empty()) mutated = true;
|
||||
}
|
||||
}
|
||||
if (ImGui::MenuItem("@Lifetime(RAII)")) {
|
||||
@@ -2796,6 +2843,7 @@ int main(int, char**) {
|
||||
state.mutator.setRoot(ast);
|
||||
auto res = state.mutator.insertNode(target->id, "annotations", anno);
|
||||
if (!res.error.empty()) state.outputLog += res.error + "\n";
|
||||
if (res.error.empty()) mutated = true;
|
||||
}
|
||||
}
|
||||
if (ImGui::MenuItem("@Allocate(Static)")) {
|
||||
@@ -2806,6 +2854,7 @@ int main(int, char**) {
|
||||
state.mutator.setRoot(ast);
|
||||
auto res = state.mutator.insertNode(target->id, "annotations", anno);
|
||||
if (!res.error.empty()) state.outputLog += res.error + "\n";
|
||||
if (res.error.empty()) mutated = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
@@ -2819,27 +2868,37 @@ int main(int, char**) {
|
||||
if (anno->conceptType == "ReclaimAnnotation") {
|
||||
if (ImGui::MenuItem("Tracing")) {
|
||||
state.mutator.setRoot(ast);
|
||||
state.mutator.setProperty(anno->id, "strategy", "Tracing");
|
||||
auto res = state.mutator.setProperty(anno->id, "strategy", "Tracing");
|
||||
if (!res.error.empty()) state.outputLog += res.error + "\n";
|
||||
if (res.error.empty()) mutated = true;
|
||||
}
|
||||
} else if (anno->conceptType == "OwnerAnnotation") {
|
||||
if (ImGui::MenuItem("Single")) {
|
||||
state.mutator.setRoot(ast);
|
||||
state.mutator.setProperty(anno->id, "strategy", "Single");
|
||||
auto res = state.mutator.setProperty(anno->id, "strategy", "Single");
|
||||
if (!res.error.empty()) state.outputLog += res.error + "\n";
|
||||
if (res.error.empty()) mutated = true;
|
||||
}
|
||||
} else if (anno->conceptType == "DeallocateAnnotation") {
|
||||
if (ImGui::MenuItem("Explicit")) {
|
||||
state.mutator.setRoot(ast);
|
||||
state.mutator.setProperty(anno->id, "strategy", "Explicit");
|
||||
auto res = state.mutator.setProperty(anno->id, "strategy", "Explicit");
|
||||
if (!res.error.empty()) state.outputLog += res.error + "\n";
|
||||
if (res.error.empty()) mutated = true;
|
||||
}
|
||||
} else if (anno->conceptType == "LifetimeAnnotation") {
|
||||
if (ImGui::MenuItem("RAII")) {
|
||||
state.mutator.setRoot(ast);
|
||||
state.mutator.setProperty(anno->id, "strategy", "RAII");
|
||||
auto res = state.mutator.setProperty(anno->id, "strategy", "RAII");
|
||||
if (!res.error.empty()) state.outputLog += res.error + "\n";
|
||||
if (res.error.empty()) mutated = true;
|
||||
}
|
||||
} else if (anno->conceptType == "AllocateAnnotation") {
|
||||
if (ImGui::MenuItem("Static")) {
|
||||
state.mutator.setRoot(ast);
|
||||
state.mutator.setProperty(anno->id, "strategy", "Static");
|
||||
auto res = state.mutator.setProperty(anno->id, "strategy", "Static");
|
||||
if (!res.error.empty()) state.outputLog += res.error + "\n";
|
||||
if (res.error.empty()) mutated = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
@@ -2855,6 +2914,7 @@ int main(int, char**) {
|
||||
state.mutator.setRoot(ast);
|
||||
auto res = state.mutator.deleteNode(anno->id);
|
||||
if (!res.error.empty()) state.outputLog += res.error + "\n";
|
||||
if (res.error.empty()) mutated = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
@@ -2877,6 +2937,7 @@ int main(int, char**) {
|
||||
state.mutator.setRoot(ast);
|
||||
auto res = state.mutator.deleteNode(lineConflict.childAnnoId);
|
||||
if (!res.error.empty()) state.outputLog += res.error + "\n";
|
||||
if (res.error.empty()) mutated = true;
|
||||
}
|
||||
if (ImGui::MenuItem("Match parent strategy")) {
|
||||
state.mutator.setRoot(ast);
|
||||
@@ -2884,10 +2945,14 @@ int main(int, char**) {
|
||||
"strategy",
|
||||
lineConflict.parentStrategy);
|
||||
if (!res.error.empty()) state.outputLog += res.error + "\n";
|
||||
if (res.error.empty()) mutated = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (mutated) {
|
||||
state.applyOrchestratorToActive();
|
||||
}
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
@@ -2986,7 +3051,7 @@ int main(int, char**) {
|
||||
// Optimization controls
|
||||
if (ImGui::BeginTabItem("Optimize")) {
|
||||
ImGui::PushFont(uiFont);
|
||||
Module* ast = state.active() ? state.active()->sync.getAST() : nullptr;
|
||||
Module* ast = state.mutationAST();
|
||||
if (!state.active()) {
|
||||
ImGui::TextDisabled("(no active buffer)");
|
||||
} else if (state.active()->bufferMode == BufferManager::BufferMode::Text) {
|
||||
@@ -3045,7 +3110,7 @@ int main(int, char**) {
|
||||
}
|
||||
state.optimizeFoldSummary = summary;
|
||||
state.outputLog += summary + "\n";
|
||||
if (nodes > 0) state.refreshActiveTextFromAST();
|
||||
if (nodes > 0) state.applyOrchestratorToActive();
|
||||
std::string afterText = state.active()->editBuf;
|
||||
state.openDiff(beforeText, afterText, false, 1, {tid});
|
||||
}
|
||||
@@ -3089,7 +3154,7 @@ int main(int, char**) {
|
||||
}
|
||||
state.optimizeDeadCodeSummary = summary;
|
||||
state.outputLog += summary + "\n";
|
||||
if (nodes > 0) state.refreshActiveTextFromAST();
|
||||
if (nodes > 0) state.applyOrchestratorToActive();
|
||||
std::string afterText = state.active()->editBuf;
|
||||
state.openDiff(beforeText, afterText, false, 2, {tid});
|
||||
}
|
||||
@@ -3138,7 +3203,7 @@ int main(int, char**) {
|
||||
}
|
||||
state.optimizeApplySummary = summary;
|
||||
state.outputLog += summary + "\n";
|
||||
if (totalNodes > 0) state.refreshActiveTextFromAST();
|
||||
if (totalNodes > 0) state.applyOrchestratorToActive();
|
||||
std::string afterText = state.active()->editBuf;
|
||||
state.openDiff(beforeText, afterText, false, 3, {tidFold, tidDce});
|
||||
}
|
||||
@@ -3157,7 +3222,7 @@ int main(int, char**) {
|
||||
if (ImGui::BeginTabItem("Transforms")) {
|
||||
ImGui::PushFont(uiFont);
|
||||
auto* buf = state.active();
|
||||
Module* ast = buf ? buf->sync.getAST() : nullptr;
|
||||
Module* ast = state.mutationAST();
|
||||
if (!buf) {
|
||||
ImGui::TextDisabled("(no active buffer)");
|
||||
} else if (buf->bufferMode == BufferManager::BufferMode::Text) {
|
||||
@@ -3176,7 +3241,7 @@ int main(int, char**) {
|
||||
while (inc.undoLast()) {
|
||||
any = true;
|
||||
}
|
||||
if (any) state.refreshActiveTextFromAST();
|
||||
if (any) state.applyOrchestratorToActive();
|
||||
}
|
||||
if (!hasHistory) ImGui::EndDisabled();
|
||||
ImGui::Separator();
|
||||
@@ -3193,7 +3258,7 @@ int main(int, char**) {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Undo")) {
|
||||
if (inc.undoTransform(h.transformId)) {
|
||||
state.refreshActiveTextFromAST();
|
||||
state.applyOrchestratorToActive();
|
||||
}
|
||||
}
|
||||
ImGui::Text("Affected: %d", (int)h.affectedNodeIds.size());
|
||||
@@ -3218,7 +3283,7 @@ int main(int, char**) {
|
||||
if (ImGui::BeginTabItem("Diff")) {
|
||||
ImGui::PushFont(uiFont);
|
||||
auto* buf = state.active();
|
||||
Module* ast = buf ? buf->sync.getAST() : nullptr;
|
||||
Module* ast = state.mutationAST();
|
||||
if (!buf) {
|
||||
ImGui::TextDisabled("(no active buffer)");
|
||||
} else if (buf->bufferMode == BufferManager::BufferMode::Text) {
|
||||
@@ -3238,7 +3303,7 @@ int main(int, char**) {
|
||||
} else {
|
||||
state.outputLog += "Refactor applied (" +
|
||||
std::to_string(res.appliedCount) + " mutations).\n";
|
||||
state.refreshActiveTextFromAST();
|
||||
state.applyOrchestratorToActive();
|
||||
}
|
||||
} else {
|
||||
buf->incrementalOptimizer.setRoot(ast);
|
||||
@@ -3250,7 +3315,7 @@ int main(int, char**) {
|
||||
buf->incrementalOptimizer.applyTransform("constant-fold");
|
||||
buf->incrementalOptimizer.applyTransform("dead-code-elim");
|
||||
}
|
||||
state.refreshActiveTextFromAST();
|
||||
state.applyOrchestratorToActive();
|
||||
}
|
||||
}
|
||||
state.diff.active = false;
|
||||
@@ -3271,7 +3336,7 @@ int main(int, char**) {
|
||||
it != state.diff.transformIds.rend(); ++it) {
|
||||
buf->incrementalOptimizer.undoTransform(*it);
|
||||
}
|
||||
state.refreshActiveTextFromAST();
|
||||
state.applyOrchestratorToActive();
|
||||
}
|
||||
state.diff.active = false;
|
||||
}
|
||||
|
||||
39
editor/tests/step115_test.cpp
Normal file
39
editor/tests/step115_test.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
// Step 115 TDD Test: Orchestrator wiring + Emacs config setting
|
||||
#include "Orchestrator.h"
|
||||
#include "SettingsManager.h"
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
static void expect(bool cond, const std::string& name, int& passed, int& failed) {
|
||||
if (cond) {
|
||||
std::cout << "Test " << (passed + failed + 1) << " PASS: " << name << "\n";
|
||||
++passed;
|
||||
} else {
|
||||
std::cout << "Test " << (passed + failed + 1) << " FAIL: " << name << "\n";
|
||||
++failed;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
int passed = 0;
|
||||
int failed = 0;
|
||||
|
||||
{
|
||||
Orchestrator orch;
|
||||
auto mod = std::make_unique<Module>("m1", "Main", "python");
|
||||
orch.setAST(std::move(mod));
|
||||
expect(orch.getAST() != nullptr && orch.getAST()->name == "Main", "orchestrator stores AST", passed, failed);
|
||||
}
|
||||
|
||||
{
|
||||
SettingsManager settings;
|
||||
std::string path = settings.getEmacsConfigPath();
|
||||
bool ok = !path.empty() && path.find(".emacs.d") != std::string::npos;
|
||||
expect(ok, "emacs config default", passed, failed);
|
||||
settings.setEmacsConfigPath("C:/custom/emacs");
|
||||
expect(settings.getEmacsConfigPath() == "C:/custom/emacs", "emacs config set", passed, failed);
|
||||
}
|
||||
|
||||
std::cout << "\n=== Step 115 Results: " << passed << " passed, " << failed << " failed ===\n";
|
||||
return failed == 0 ? 0 : 1;
|
||||
}
|
||||
@@ -352,7 +352,7 @@ Whetstone-specific AST navigation.
|
||||
Wire the orchestrator, serialization, session management, and prepare
|
||||
AST extensions for Sprint 5.
|
||||
|
||||
- [ ] **Step 115: Wire Orchestrator**
|
||||
- [x] **Step 115: Wire Orchestrator**
|
||||
Connect `Orchestrator.h` to the GUI. All AST mutations go through the
|
||||
orchestrator's undo/redo journal (replacing TextEditor's simple stack).
|
||||
Orchestrator manages the canonical AST state. GUI reads from it.
|
||||
|
||||
Reference in New Issue
Block a user