Steps 266-268: Phase 10a — semantic annotation core + sidecar persistence (32/32 tests)

Step 266: 5 semantic annotation AST types (Intent, Complexity, Risk,
Contract, SemanticTag) with JSON roundtrip and compact AST integration.
Step 267: Sidecar AST persistence (.whetstone/<file>.ast.json) with
save/load/list RPC methods, MCP tools, and permission enforcement.
Step 268: Phase 10a integration tests — multi-file sidecar workflow,
all 5 types in compact view, idempotent roundtrip, source isolation.

Also includes Sprint 10 plan, GUI/installer polish, and Emacs integration fixes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Bill
2026-02-12 16:01:56 +00:00
parent c36fd92045
commit 976161dc4a
36 changed files with 2999 additions and 69 deletions

View File

@@ -56,10 +56,16 @@ static void renderBottomPanel(EditorState& state) {
ImGui::SetNextWindowFocus();
state.ui.focusTarget = FocusRegion::None;
}
if (state.ui.requestBottomCollapse) {
ImGui::SetNextWindowCollapsed(true, ImGuiCond_Always);
}
// ---------------------------------------------------------------
// Bottom panel — Output / AST / Highlighted Preview / Terminal
// ---------------------------------------------------------------
ImGui::Begin("Panel");
if (state.ui.requestBottomCollapse) {
state.ui.requestBottomCollapse = false;
}
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows)) {
state.ui.focusedRegion = FocusRegion::Bottom;
}

View File

@@ -338,7 +338,7 @@ static void renderCommandPalette(EditorState& state) {
bool selected = (displayIndex == state.commandSelected);
std::string rowId = "##cmd_recent_" + std::to_string(displayIndex);
if (ImGui::Selectable(rowId.c_str(), selected,
ImGuiSelectableFlags_SpanAvailWidth,
0,
ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing()))) {
state.commandSelected = displayIndex;
accept = true;
@@ -375,7 +375,7 @@ static void renderCommandPalette(EditorState& state) {
bool selected = (displayIndex == state.commandSelected);
std::string rowId = "##cmd_" + std::to_string(displayIndex);
if (ImGui::Selectable(rowId.c_str(), selected,
ImGuiSelectableFlags_SpanAvailWidth,
0,
ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing()))) {
state.commandSelected = displayIndex;
accept = true;
@@ -502,7 +502,7 @@ static void renderCommandPalette(EditorState& state) {
bool selected = (i == state.commandSelected);
std::string rowId = "##file_" + std::to_string(i);
if (ImGui::Selectable(rowId.c_str(), selected,
ImGuiSelectableFlags_SpanAvailWidth,
0,
ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing()))) {
state.commandSelected = i;
accept = true;

View File

@@ -29,6 +29,18 @@ static void renderExplorerPanel(EditorState& state) {
state.refreshFileTree();
if (state.fileTreeRoot.path.empty()) {
ImGui::TextDisabled("(no workspace)");
ImGui::Spacing();
ImGui::TextWrapped("Open a folder to browse project files.");
if (ImGui::Button("Open Folder")) {
auto path = FileDialog::openFolder({"Open Folder", state.workspaceRoot});
if (!path.empty()) {
state.workspaceRoot = path;
state.fileTreeDirty = true;
state.search.projectSearch.setRoot(state.workspaceRoot);
state.lastDialogPath = path;
state.refreshBuildSystem();
}
}
} else {
RenderFileTree(state.fileTreeRoot, state);
}

View File

@@ -131,6 +131,10 @@ static void renderMenuBar(EditorState& state) {
state.ui.layoutPreset = LayoutPreset::Emacs;
if (ImGui::MenuItem("JetBrains", nullptr, state.ui.layoutPreset == LayoutPreset::JetBrains))
state.ui.layoutPreset = LayoutPreset::JetBrains;
ImGui::Separator();
if (ImGui::MenuItem("Reset Layout")) {
state.ui.requestLayoutReset = true;
}
ImGui::EndMenu();
}
ImGui::EndMenu();

View File

@@ -93,7 +93,7 @@ static void renderStatusBar(EditorState& state) {
// Left cluster: mode, language, encoding, line ending
std::string modeLabel = state.active()
? (state.active()->bufferMode == BufferManager::BufferMode::Text ? "Text" : "Structured")
? (state.active()->bufferMode == BufferManager::BufferMode::Text ? "Text Mode" : "Structured Mode")
: "-";
if (ImGui::Button(modeLabel.c_str())) {
toggleBufferMode(state);