Skip to content

Improve code command#350

Merged
genedna merged 27 commits into
libra-tools:mainfrom
genedna:main
Apr 21, 2026
Merged

Improve code command#350
genedna merged 27 commits into
libra-tools:mainfrom
genedna:main

Conversation

@genedna

@genedna genedna commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

No description provided.

genedna and others added 5 commits April 8, 2026 08:53
Signed-off-by: Quanyi Ma <eli@patch.sh>
Signed-off-by: Quanyi Ma <eli@patch.sh>
- Remove Rename Notice section
- Add full ASCII Phase 0-4 architecture diagram showing Codex and
  generic provider interaction with Libra Scheduler control flow
- Add src/internal/ai module restructuring recommendations covering
  deletions (claudecode/), new modules (workflow_runtime/), refactors,
  extensions, and target-state module tree
- Elevate generic provider to first-class citizen alongside Codex
- Document WorkflowRuntime shared layer and TaskExecutor trait design
- Add Phase 3/4 state machines with rollback conditions
- Add Query Index and Rebuild/Read contract section
- Define shared function boundary (8 must-share, 4 adapter-only)
- Upgrade validation from acceptance criteria to 4-layer test strategy
  (Unit / Integration / E2E isomorphism / Failure injection)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Eli Ma <eli@patch.sh>
# Conflicts:
#	src/command/cloud.rs
#	src/internal/config.rs
Signed-off-by: Quanyi Ma <eli@patch.sh>
Copilot AI review requested due to automatic review settings April 12, 2026 18:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an embedded “Libra Code UI” web experience (served by the Rust binary) and updates the agent workflow documentation, alongside a broad set of Rust import/utility refactors and dependency bumps.

Changes:

  • Add an Axum-based embedded web server exposing /api/code/* + serving the bundled web UI.
  • Introduce a Next.js UI (Code Session page + thread mock UI) with Base UI/shadcn styling utilities.
  • Refactor multiple Rust modules (imports, config/vault helpers, warning tracking), and bump crate/web versions.

Reviewed changes

Copilot reviewed 80 out of 84 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
web/src/lib/utils.ts Adds cn() helper for Tailwind + class merging.
web/src/components/ui/separator.tsx Base UI separator wrapper component.
web/src/components/ui/input.tsx Base UI input wrapper component.
web/src/components/ui/button.tsx Base UI button wrapper with variants (CVA).
web/src/components/ui/badge.tsx Badge component using Base UI useRender.
web/src/components/ui/avatar.tsx Avatar component set (root/image/fallback/group).
web/src/components/thread/thread-sidebar.tsx Thread sidebar UI scaffold.
web/src/components/thread/thread-page.tsx Thread page layout and change list rendering.
web/src/components/thread/thread-page.module.css Scrollbar + topology + hover styling.
web/src/components/thread/thread-layout.tsx Thread layout shell components.
web/src/components/thread/thread-item-card.tsx Featured + compact change cards.
web/src/components/thread/thread-header.tsx Thread header + toolbar using UI components.
web/src/components/thread/thread-data.ts Mock data models + sample content for thread UI.
web/src/components/code-session/code-session-page.tsx Main Code UI session page (SSE + controller + transcript).
web/src/app/page.tsx Switch home page to render CodeSessionPage + metadata.
web/src/app/layout.tsx Swap to Google fonts and update app metadata.
web/src/app/globals.css Tailwind v4 theme vars + shadcn/tw-animate imports.
web/package.json Add UI deps (Base UI, shadcn, lucide, etc.) + bump versions.
web/components.json Adds shadcn registry/config metadata.
src/utils/util.rs Import refactors; reuse emit_legacy_stderr; config usage adjustments.
src/utils/test.rs Import refactors; deterministic identity seeding via ConfigKv.
src/utils/error.rs Import refactors; record warnings through output helpers.
src/utils/d1_client.rs Use resolve_env import alias.
src/utils/convert.rs Use InitError import and simplify error mapping.
src/utils/client_storage.rs Import refactors; use DATABASE/try_get_storage_path helpers.
src/internal/vault.rs Use try_get_storage_path import alias.
src/internal/tui/bottom_pane.rs Import UserInputQuestion type alias for readability.
src/internal/protocol/https_client.rs Use emit_warning import alias.
src/internal/config.rs Import refactors; use vault helpers + storage path helpers.
src/internal/ai/web/mod.rs New embedded web server module (assets + /api/code/*).
src/internal/ai/tools/handlers/shell.rs Import refactors; use sandbox helpers + is_sub_path.
src/internal/ai/tools/handlers/read_file.rs Import ToolPayload and simplify match.
src/internal/ai/tools/handlers/mod.rs Simplify parse_arguments and reuse ToolResult/ToolError imports.
src/internal/ai/tools/handlers/list_dir.rs Import ToolPayload and simplify match.
src/internal/ai/tools/handlers/grep_files.rs Import ToolPayload and simplify match.
src/internal/ai/tools/handlers/apply_patch.rs Import sandbox approval types; simplify approval flow code.
src/internal/ai/session/state.rs Import Message for type aliasing in history conversion.
src/internal/ai/providers/gemini/client.rs Alias generic HTTP client type for provider client.
src/internal/ai/orchestrator/planner.rs Import Check type for task metadata.
src/internal/ai/orchestrator/persistence.rs Import refactors; add artifact params + usage summary aliasing.
src/internal/ai/orchestrator/mod.rs Import ToolLoopConfig alias.
src/internal/ai/orchestrator/gate.rs Use sandbox run_shell_command import alias.
src/internal/ai/orchestrator/executor.rs Import refactors; ACL/network types simplified.
src/internal/ai/orchestrator/acl.rs Import ToolAcl alias and simplify signatures.
src/internal/ai/mod.rs Expose new web module.
src/internal/ai/mcp/resource.rs Import normalize_commit_anchor alias.
src/internal/ai/intentspec/repair.rs Import QualityGates alias; simplify insertion.
src/internal/ai/hooks/runtime.rs Import refactors; use SessionStore, emit_warning, ConfigKv aliasing.
src/internal/ai/claudecode/project_settings.rs Use util::ROOT_DIR alias in root resolution.
src/internal/ai/claudecode/mod.rs Import refactors; use TUI/event types + intentspec enums via aliases.
src/internal/ai/claudecode/managed_run.rs Import refactors; use IoFootprintParams/UserInputOption aliases.
src/internal/ai/claudecode/extraction.rs Import IntentSpec alias for artifact structs.
src/internal/ai/agent/runtime/tool_loop.rs Import HookAction alias for hook gating.
src/command/stash.rs Import load_object directly for reuse.
src/command/shortlog.rs Import require_repo helper for repo presence checks.
src/command/reflog.rs Import parse_date + format_stat_output aliases.
src/command/rebase.rs Use emit_warning import alias for warnings.
src/command/push.rs Import LFSClient alias.
src/command/open.rs Import LIBRA_TEST_ENV + require_repo aliases.
src/command/mod.rs Use emit_warning import alias during prompt flushing.
src/command/merge.rs Stable error codes import cleanup; use info_println alias.
src/command/log.rs Import tag module + TagObject alias for decoration.
src/command/init.rs Import get_db_conn_instance_for_path; stable code aliasing.
src/command/grep.rs Import record_warning alias.
src/command/fetch.rs Import ConfigKvEntry, vault helpers, and try_get_storage_path alias.
src/command/config.rs Import db/vault helpers; add JSON emit helper aliasing.
src/command/commit.rs Import save_object_to_storage directly.
src/command/cloud.rs Import restore args alias + branch/head aliases; use emit_warning.
src/command/clone.rs Import DiscoveryResult + db connection alias.
src/command/checkout.rs Use info_println alias.
src/command/cat_file.rs Import parse_commit_msg alias.
src/command/branch.rs Import get_reachable_commits + require_repo aliases; info_println.
src/command/bisect.rs Use info_println alias throughout bisect output.
src/cli.rs Import ConfigKv + db aliases for hash kind init.
docs/agent/ai-object-model-reference.md Update phase mapping to include ContextFrame/ToolInvocation early.
docs/agent/agent-workflow.md Revise workflow phases (intent/plan-set review loops, composite DAG).
Cargo.toml Bump crate version + git-internal dependency.
Cargo.lock Lockfile updates for dependency bumps.
Comments suppressed due to low confidence (1)

src/utils/util.rs:33

  • Repo convention is to justify intentional panics from unwrap()/expect() with // INVARIANT: (and reserve // SAFETY: for unsafe blocks). Update this module-level comment accordingly so it matches the established convention.

Comment on lines +1 to +4
import * as React from "react"
import { Input as InputPrimitive } from "@base-ui/react/input"

import { cn } from "@/lib/utils"
Comment on lines +1 to +5
import { Button as ButtonPrimitive } from "@base-ui/react/button"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"

Comment on lines +1 to +6
import { mergeProps } from "@base-ui/react/merge-props"
import { useRender } from "@base-ui/react/use-render"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"

Comment on lines +175 to +178
let storage_root = resolve_storage_root(&state.working_dir);
let desc_path = storage_root.join("description");
let description = std::fs::read_to_string(&desc_path).unwrap_or_default();

Comment on lines +94 to 96
pub fn to_history(&self) -> Vec<Message> {
use crate::internal::ai::completion::Message;

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ddd3f3a86f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/command/code.rs
/// Rejects all TUI-specific flags when running in a non-TUI mode (web-only or stdio).
/// This ensures users get clear errors instead of silently ignored flags.
fn reject_non_tui_flags(args: &CodeArgs, mode: &str) -> Result<(), String> {
reject_mode_flag(args.provider != CodeProvider::Gemini, "--provider", mode)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Allow codex provider in web-mode validation

validate_mode_args always calls reject_non_tui_flags for --web, and reject_non_tui_flags rejects any provider other than Gemini here, which makes libra code --web --provider codex fail argument validation before it can reach the codex web runtime in execute_web_only. This makes the new codex web-control path effectively unreachable; web-mode validation should allow codex (and its related flags) instead of treating it like a non-TUI-only rejection.

Useful? React with 👍 / 👎.

Comment thread src/internal/tui/app.rs
Comment on lines +2551 to +2554
let interaction_id = pending
.plan_id
.clone()
.unwrap_or_else(|| "post-plan-choice".to_string());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve post-plan interaction with the same fallback id

When a plan cannot be persisted (plan_id == None), the browser interaction is created with fallback id plan-{turn} (in the plan completion path), but handle_post_plan_choice resolves post-plan-choice instead, so the pending interaction is never resolved in Code UI for that case. This leaves stale pending interaction state in the browser flow whenever plan persistence fails; use the exact emitted interaction id (or store it in PendingPostPlan) for resolution/cleanup.

Useful? React with 👍 / 👎.

Comment on lines +157 to +159
let id = ConfigKv::get("libra.repoid")
.await
.ok()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Read repo metadata using the session working directory

This endpoint reads repository config via global ConfigKv convenience methods that are bound to the process DB path, not state.working_dir. If libra code is launched with --cwd/--repo from another directory, /api/repo can return repo id/remote-derived name from the wrong repository (or empty data). Open a connection for state.working_dir and use the *_with_conn config helpers so metadata always reflects the active code session.

Useful? React with 👍 / 👎.

Comment thread src/internal/ai/web/mod.rs Fixed
genedna added 11 commits April 15, 2026 20:27
Signed-off-by: Quanyi Ma <eli@patch.sh>
Signed-off-by: Quanyi Ma <eli@patch.sh>
Signed-off-by: Quanyi Ma <eli@patch.sh>
Signed-off-by: Quanyi Ma <eli@patch.sh>
Signed-off-by: Quanyi Ma <eli@patch.sh>
Signed-off-by: Quanyi Ma <eli@patch.sh>
Signed-off-by: Quanyi Ma <eli@patch.sh>
Signed-off-by: Quanyi Ma <eli@patch.sh>
Signed-off-by: Quanyi Ma <eli@patch.sh>
Signed-off-by: Quanyi Ma <eli@patch.sh>
Signed-off-by: Quanyi Ma <eli@patch.sh>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ed2718ce6c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/internal/tui/app.rs
Comment on lines +993 to +996
code_ui_session.resolve_interaction(&interaction_id).await;
code_ui_session
.set_status(CodeUiSessionStatus::ExecutingTool)
.await;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep user-input interaction pending until final question

submit_user_input_answer resolves the browser interaction and flips the session status to executing_tool unconditionally, even when done is false and there are more questions left in the same request_user_input flow. In multi-question prompts this makes the Code UI mark the interaction as finished after the first answer, so observers lose visibility into remaining required inputs and see an incorrect runtime state. Only resolve the interaction and transition status after the final question is answered.

Useful? React with 👍 / 👎.

&working_dir_clone,
)
.await;
oneshot_rx.await.unwrap_or(true)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Fail closed when approval response channel drops

In interactive approval mode, oneshot_rx.await.unwrap_or(true) treats channel errors as approval. If the controller/runtime drops before sending a decision, the request is silently approved and execution continues, which can authorize mutating operations without an explicit user choice. This path should fail closed (deny/abort) instead of defaulting to true.

Useful? React with 👍 / 👎.

Signed-off-by: Quanyi Ma <eli@patch.sh>
Copilot AI review requested due to automatic review settings April 15, 2026 14:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR migrates libra code toward a managed runtime contract: removing the legacy claudecode provider path, introducing new runtime/projection contracts (phases, prompts, hardening), and adding SQLite schema + repositories to persist and resume canonical thread state.

Changes:

  • Add AI runtime contract modules (phases 3/4, prompt builders, hardening, execution environment) plus an embedded Axum web server for Code UI APIs.
  • Extend SQLite bootstrap + add an idempotent migration for new runtime read-model tables (scheduler selected plan set, validation/risk/decision records, provider metadata).
  • Refactor imports/call sites across CLI and AI subsystems; update docs to reflect --resume <thread_id> and removal of claudecode.

Reviewed changes

Copilot reviewed 90 out of 147 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/internal/protocol/https_client.rs Minor auth warning emission refactor via imported emit_warning.
src/internal/model/mod.rs Exposes new SeaORM entities for runtime contract tables.
src/internal/model/ai_validation_report.rs Adds SeaORM entity for validation reports.
src/internal/model/ai_thread_provider_metadata.rs Adds SeaORM entity for provider thread metadata.
src/internal/model/ai_scheduler_selected_plan.rs Adds SeaORM entity for selected plan set rows.
src/internal/model/ai_risk_score_breakdown.rs Adds SeaORM entity for risk score breakdowns.
src/internal/model/ai_decision_proposal.rs Adds SeaORM entity for decision proposals.
src/internal/db.rs Applies new idempotent runtime-contract migration on connect.
src/internal/config.rs Import cleanup + vault/util helpers used directly.
src/internal/ai/web/mod.rs New embedded Axum server for static UI + /api/code/* endpoints, SSE, error mapping.
src/internal/ai/tools/handlers/shell.rs Import cleanup + sandbox request call simplification + is_sub_path usage.
src/internal/ai/tools/handlers/read_file.rs Uses ToolPayload directly for payload matching.
src/internal/ai/tools/handlers/mod.rs Simplifies parse_arguments signature/paths.
src/internal/ai/tools/handlers/list_dir.rs Uses ToolPayload directly for payload matching.
src/internal/ai/tools/handlers/grep_files.rs Uses ToolPayload directly for payload matching.
src/internal/ai/tools/handlers/apply_patch.rs Imports sandbox approval types directly; simplifies approval path.
src/internal/ai/session/store.rs Adds thread-id based resume, legacy metadata backfill + tests.
src/internal/ai/session/state.rs Uses imported Message type in to_history.
src/internal/ai/runtime/prompt_builders.rs New prompt builders + plan-mode instruction constants + tests.
src/internal/ai/runtime/phase4.rs New risk aggregation + decision proposal store.
src/internal/ai/runtime/phase3.rs New validation pipeline + persistence store helpers.
src/internal/ai/runtime/mod.rs New runtime module surface + prompt builder entrypoints + tests.
src/internal/ai/runtime/hardening.rs New tool boundary policy + redaction + audit sink contracts.
src/internal/ai/runtime/environment.rs New task worktree execution environment provider + tests.
src/internal/ai/runtime/contracts.rs New workflow contracts/types, CAS validation helpers + tests.
src/internal/ai/providers/gemini/client.rs Uses local alias for generic HTTP client type.
src/internal/ai/projection/scheduler.rs Adds scheduler repository with CAS, selected plan set support, row conversions.
src/internal/ai/projection/resolver.rs Adds projection resolver to load or rebuild thread bundles.
src/internal/ai/projection/mod.rs Re-exports resolver + scheduler repository/CAS error types.
src/internal/ai/orchestrator/planner.rs Uses imported Check type in task meta.
src/internal/ai/orchestrator/persistence.rs Import cleanup + uses new MCP ArtifactParams and tool output helpers.
src/internal/ai/orchestrator/mod.rs Exposes workspace internally + uses ToolLoopConfig directly.
src/internal/ai/orchestrator/gate.rs Imports run_shell_command directly.
src/internal/ai/orchestrator/executor.rs Migrates worktree lifecycle to ExecutionEnvironmentProvider; updates dagrs API usage.
src/internal/ai/orchestrator/acl.rs Uses imported ToolAcl type.
src/internal/ai/node_adapter.rs Uses Output::execution_failed for failures (dagrs API update).
src/internal/ai/mod.rs Removes claudecode module; adds runtime and web modules.
src/internal/ai/mcp/resource.rs Import cleanup + uses normalize_commit_anchor directly.
src/internal/ai/intentspec/repair.rs Uses imported QualityGates.
src/internal/ai/hooks/runtime.rs Imports SessionStore, ConfigKv, emit_warning directly.
src/internal/ai/agent/runtime/tool_loop.rs Uses imported HookAction.
src/command/worktree-fuse.rs Control-flow cleanup; changes mount-handle unmount error handling.
src/command/stash.rs Import cleanup for load_object access.
src/command/shortlog.rs Uses imported require_repo.
src/command/reflog.rs Uses imported parse_date + format_stat_output.
src/command/rebase.rs Uses imported emit_warning.
src/command/push.rs Imports LFS client type directly.
src/command/open.rs Uses imported require_repo + LIBRA_TEST_ENV.
src/command/mod.rs Uses imported emit_warning for flush warnings.
src/command/merge.rs Uses imported stable error codes + info_println.
src/command/log.rs Imports tag module + TagObject directly.
src/command/init.rs Imports stable error codes + get_db_conn_instance_for_path.
src/command/grep.rs Uses imported record_warning.
src/command/fetch.rs Uses vault helpers directly + try_get_storage_path.
src/command/config.rs Imports DB/vault helpers directly; emits JSON via imported helper.
src/command/commit.rs Uses imported save_object_to_storage.
src/command/cloud.rs Import cleanup + emits warnings via imported helper.
src/command/clone.rs Imports DB connection + DiscoveryResult directly.
src/command/checkout.rs Uses imported info_println.
src/command/cat_file.rs Uses imported parse_commit_msg.
src/command/branch.rs Uses imported get_reachable_commits, require_repo, and info_println.
src/command/bisect.rs Uses imported info_println.
src/cli.rs Adds argv parse hints for removed claudecode flags; uses imported ConfigKv + db helper.
sql/sqlite_20260415_ai_runtime_contract.sql New idempotent runtime-contract migration DDL.
sql/sqlite_20260309_init.sql Bootstrap schema extended with runtime-contract tables.
docs/improvement/config.md Clarifies provider env work is owned by code.md plan.
docs/improvement/README.md Reframes AI Agent plan tracking + follow-ups.
docs/commands/code.md Updates CLI to --resume <thread_id> + removes claudecode provider references.
docs/agent/ai-object-model-reference.md Updates scheduler model to selected_plan_ids[] + phase mapping notes.
docs/agent/agent-workflow.md Updates workflow narrative for intent/plan review loops + plan set selection.
benches/ai_runtime_baseline.rs Adds baseline “smoke” benchmark-style test harness.
README.md Removes claudecode runtime docs; documents migration + canonical resume.
Cargo.toml Bumps crate + dependency versions (incl. dagrs).
src/internal/ai/claudecode/prompts/30-interaction.txt Removed legacy Claude Code prompt asset.
src/internal/ai/claudecode/prompts/20-structured-output.txt Removed legacy Claude Code prompt asset.
src/internal/ai/claudecode/prompts/10-plan-mode.txt Removed legacy Claude Code prompt asset.
src/internal/ai/claudecode/prompts/00-intro.txt Removed legacy Claude Code prompt asset.
src/internal/ai/claudecode/plan_checkpoint.rs Removed legacy Claude Code plan checkpoint helper.
src/internal/ai/claudecode/extraction.rs Removed legacy Claude Code extraction CLI support.

Ok(()) => return Ok(()),
Err(e) => {
let ioe: io::Error = e.into();
let ioe: io::Error = e;
Comment on lines +93 to 94
emit_warning("authentication required, retrying...");
AUTH.lock().unwrap().replace(ask_basic_auth());

let storage_root = resolve_storage_root(&state.working_dir);
let desc_path = storage_root.join("description");
let description = std::fs::read_to_string(&desc_path).unwrap_or_default();
Comment on lines +298 to +306
impl From<anyhow::Error> for WebApiError {
fn from(value: anyhow::Error) -> Self {
Self {
status: StatusCode::INTERNAL_SERVER_ERROR,
code: "INTERNAL_ERROR".to_string(),
message: value.to_string(),
}
}
}
Comment on lines +275 to +280
fn code_ui_event_to_sse(event: code_ui::CodeUiEventEnvelope) -> Event {
Event::default()
.event(event.event_type.clone())
.json_data(event)
.unwrap_or_else(|_| Event::default().event("session_updated"))
}
Comment on lines +690 to +697
std::thread::sleep(std::time::Duration::from_millis(10));

let mut canonical = SessionState::new("/repo/main");
canonical.summary = "canonical".to_string();
canonical
.metadata
.insert("thread_id".to_string(), serde_json::json!(thread_id));
store.save(&canonical).unwrap();
Comment on lines +451 to +502
for plan_head in &state.current_plan_heads {
ai_scheduler_plan_head::ActiveModel {
thread_id: Set(thread_id.clone()),
plan_id: Set(plan_head.plan_id.to_string()),
ordinal: Set(plan_head.ordinal),
}
.insert(db)
.await
.with_context(|| {
format!(
"Failed to insert scheduler plan head {} for thread {}",
plan_head.plan_id, state.thread_id
)
})?;
}

for selected_plan in &state.selected_plan_ids {
ai_scheduler_selected_plan::ActiveModel {
thread_id: Set(thread_id.clone()),
plan_id: Set(selected_plan.plan_id.to_string()),
ordinal: Set(selected_plan.ordinal),
}
.insert(db)
.await
.with_context(|| {
format!(
"Failed to insert selected scheduler plan {} for thread {}",
selected_plan.plan_id, state.thread_id
)
})?;
}

for frame in &state.live_context_window {
ai_live_context_window::ActiveModel {
thread_id: Set(thread_id.clone()),
context_frame_id: Set(frame.context_frame_id.to_string()),
position: Set(frame.position),
source_kind: Set(frame.source_kind.as_row_value().to_string()),
pin_kind: Set(frame
.pin_kind
.as_ref()
.map(|pin| pin.as_row_value().to_string())),
inserted_at: Set(frame.inserted_at.timestamp()),
}
.insert(db)
.await
.with_context(|| {
format!(
"Failed to insert live context frame {} for thread {}",
frame.context_frame_id, state.thread_id
)
})?;

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 700316dc7f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/command/code.rs
Comment on lines +1084 to +1086
match policy {
CodeApprovalPolicy::Never => "accept",
CodeApprovalPolicy::OnFailure

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Map --approval-policy never to deny in Codex mode

CodeApprovalPolicy::Never is defined as “never prompt; dangerous commands are rejected,” but approval_policy_to_codex currently converts it to "accept". In the Codex approval flow, "accept" auto-approves pending approvals, so users who select --approval-policy never will unintentionally allow mutating operations instead of blocking them. This should map to a deny/decline mode so the CLI contract remains safe and consistent.

Useful? React with 👍 / 👎.

Comment on lines +660 to +664
if existing.client_id != client_id {
return Err(CodeUiApiError::conflict(
"CONTROLLER_CONFLICT",
"Another browser currently controls this session".to_string(),
));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Require proof of control before reissuing controller token

When a browser lease already exists, attach_browser_controller trusts only the provided client_id and reuses that lease. Since the active client_id is exposed in session snapshots (controller.ownerLabel), another local client can copy it, call attach, and obtain the valid controller token without presenting the old token, then send messages/interactions as the controller. Lease renewal should require the current token (or equivalent proof) instead of client-id matching alone.

Useful? React with 👍 / 👎.

Signed-off-by: Quanyi Ma <eli@patch.sh>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c30bae6665

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/command/code.rs
true,
CodeUiInitialController::Unclaimed,
)
.await?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Ensure Codex child is cleaned up on runtime init errors

After start_managed_codex_server succeeds, this await? can return early if Code UI bootstrap fails, but no shutdown runs on that path and ManagedCodexServer has no Drop cleanup, so the spawned Codex app-server is left running in the background. This leaks processes/ports and can leave an unintended local control surface alive after the CLI reports failure; wrap startup in a guard (or implement Drop) so child shutdown happens on every error path (same pattern is present in the TUI Codex startup path).

Useful? React with 👍 / 👎.

Comment on lines +199 to +201
while let Some(relative_start) = lower[cursor..].find(marker) {
let marker_start = cursor + relative_start;
let value_start = marker_start + marker.len();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid mixed-index slicing in Unicode redaction

redact_marker searches in input.to_lowercase() but then reuses those byte offsets to slice the original input; with Unicode case folding, byte positions diverge (e.g. /İ), which can either panic on invalid/out-of-bounds slicing or leave part of the secret unredacted. This breaks the hardening guarantee for non-ASCII logs and should be replaced with a case-insensitive scan that keeps indices in the original string.

Useful? React with 👍 / 👎.

Signed-off-by: Quanyi Ma <eli@patch.sh>
Copilot AI review requested due to automatic review settings April 15, 2026 15:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR refactors and extends the libra code workflow by introducing a stable runtime contract layer (DB schema + runtime modules), adding an embedded web server/API, and hardening tool execution with policy + audit/redaction while removing the legacy claudecode provider path.

Changes:

  • Added AI runtime contract modules (phases 3/4, hardening, prompt builders, environment boundary) plus supporting DB schema/entities and migration.
  • Introduced embedded Axum web server for the Code UI and expanded session persistence utilities (thread-id lookup + metadata backfill).
  • Implemented tool-boundary hardening (policy decisions + audit/redaction) and updated orchestration/execution plumbing to newer dagrs APIs; removed claudecode prompt/runtime artifacts and updated docs.

Reviewed changes

Copilot reviewed 93 out of 150 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/internal/protocol/https_client.rs Refactors warning emission import usage in HTTPS auth retry flow.
src/internal/model/mod.rs Registers new SeaORM entities for AI runtime-contract tables.
src/internal/model/ai_validation_report.rs Adds SeaORM entity for validation reports.
src/internal/model/ai_thread_provider_metadata.rs Adds SeaORM entity for provider thread metadata.
src/internal/model/ai_scheduler_selected_plan.rs Adds SeaORM entity for selected plan-set storage.
src/internal/model/ai_risk_score_breakdown.rs Adds SeaORM entity for per-thread risk scoring breakdowns.
src/internal/model/ai_decision_proposal.rs Adds SeaORM entity for decision proposal summaries.
src/internal/db.rs Applies new runtime-contract migration SQL on connection establishment.
src/internal/config.rs Refactors imports and vault/config helpers to use shorter paths.
src/internal/ai/web/mod.rs Introduces embedded Axum server with static assets + /api/code/* endpoints.
src/internal/ai/tools/registry.rs Adds tool-boundary hardening integration (policy decisions + audit/redaction) with tests.
src/internal/ai/tools/handlers/shell.rs Refactors sandbox helper imports and path checks.
src/internal/ai/tools/handlers/read_file.rs Simplifies payload matching/imports to use ToolPayload.
src/internal/ai/tools/handlers/mod.rs Simplifies parse_arguments using local ToolResult/ToolError.
src/internal/ai/tools/handlers/list_dir.rs Simplifies payload matching/imports to use ToolPayload.
src/internal/ai/tools/handlers/grep_files.rs Simplifies payload matching/imports to use ToolPayload.
src/internal/ai/tools/handlers/apply_patch.rs Refactors sandbox approval imports and approval decision matching.
src/internal/ai/session/store.rs Adds thread-id lookup and legacy metadata backfill preview/apply with tests.
src/internal/ai/session/state.rs Uses imported Message type alias in history conversion.
src/internal/ai/runtime/prompt_builders.rs Adds prompt builders + stable plan-mode instruction constants with tests.
src/internal/ai/runtime/phase4.rs Adds phase 4 risk aggregation + decision proposal persistence layer.
src/internal/ai/runtime/phase3.rs Adds phase 3 validation report model + persistence layer for runtime-derived records.
src/internal/ai/runtime/mod.rs Introduces shared runtime module exports and prompt-builder entrypoints.
src/internal/ai/runtime/hardening.rs Adds tool boundary policy runtime, audit sinks, and secret redaction utility.
src/internal/ai/runtime/environment.rs Adds task execution environment provider (worktree provision/sync/cleanup) with tests.
src/internal/ai/runtime/contracts.rs Adds runtime contract types for workflow phases, projections, execution, and validation helpers.
src/internal/ai/providers/gemini/client.rs Refactors Gemini client aliasing to use a local HttpClient import.
src/internal/ai/projection/scheduler.rs Expands scheduler projection to persist/load selected plan sets and live context state.
src/internal/ai/projection/resolver.rs Adds projection resolver for load-or-rebuild thread bundle reads.
src/internal/ai/projection/mod.rs Re-exports new projection resolver and scheduler repository/CAS error types.
src/internal/ai/orchestrator/types.rs Adds persisted derived-record IDs for validation/decision stages.
src/internal/ai/orchestrator/planner.rs Refactors Check import in planner task metadata.
src/internal/ai/orchestrator/persistence.rs Persists validation/decision derived records and updates MCP resource params usage.
src/internal/ai/orchestrator/mod.rs Exposes workspace module to crate and refactors ToolLoopConfig import.
src/internal/ai/orchestrator/gate.rs Refactors sandbox shell runner import usage.
src/internal/ai/orchestrator/executor.rs Updates orchestration execution to new env provider + newer dagrs APIs and error output methods.
src/internal/ai/orchestrator/acl.rs Refactors ToolAcl import usage for ACL checks.
src/internal/ai/node_adapter.rs Updates node action outputs to execution_failed for newer dagrs API.
src/internal/ai/mod.rs Removes claudecode module and adds runtime + web modules.
src/internal/ai/mcp/resource.rs Refactors commit anchor normalization import usage.
src/internal/ai/intentspec/repair.rs Refactors QualityGates import usage for bugfix repair.
src/internal/ai/hooks/runtime.rs Refactors imports and uses SessionStore/ConfigKv/emit_warning directly.
src/internal/ai/history.rs Exposes database_connection() accessor for derived-record persistence.
src/internal/ai/claudecode/prompts/30-interaction.txt Removes legacy Claude Code prompt augmentation rules.
src/internal/ai/claudecode/prompts/20-structured-output.txt Removes legacy Claude Code structured-output prompt rules.
src/internal/ai/claudecode/prompts/10-plan-mode.txt Removes legacy Claude Code plan-mode prompt rules.
src/internal/ai/claudecode/prompts/00-intro.txt Removes legacy Claude Code prompt intro.
src/internal/ai/claudecode/plan_checkpoint.rs Removes legacy Claude Code plan checkpoint prompting implementation.
src/internal/ai/claudecode/extraction.rs Removes legacy Claude Code extraction/intent resolution CLI support.
src/internal/ai/agent/runtime/tool_loop.rs Refactors hook action import and block handling.
src/command/worktree-fuse.rs Refactors control flow and mount-handle lock/unmount logic.
src/command/stash.rs Refactors imports and uses load_object directly.
src/command/shortlog.rs Uses require_repo() helper directly.
src/command/reflog.rs Refactors imports for date parsing and stat formatting.
src/command/rebase.rs Refactors warnings emission to use imported emit_warning.
src/command/push.rs Refactors LFS client import usage.
src/command/open.rs Uses imported require_repo and LIBRA_TEST_ENV.
src/command/mod.rs Uses imported emit_warning for stdout flush warning.
src/command/merge.rs Refactors stable error code imports and uses info_println macro directly.
src/command/log.rs Refactors tag listing imports and TagObject matching.
src/command/init.rs Refactors stable error code imports and DB connection helper import usage.
src/command/grep.rs Uses imported record_warning() for warnings bookkeeping.
src/command/fetch.rs Refactors imports for vault helpers, ConfigKvEntry, and try_get_storage_path().
src/command/commit.rs Refactors to call save_object_to_storage directly.
src/command/cloud.rs Refactors imports (branch/head/restore) and uses imported emit_warning.
src/command/clone.rs Refactors imports for DB connection and protocol discovery type usage.
src/command/checkout.rs Refactors to use info_println macro directly.
src/command/cat_file.rs Refactors to use imported parse_commit_msg.
src/command/branch.rs Refactors to use imported helpers and require_repo().
src/command/bisect.rs Refactors to use info_println macro directly.
src/cli.rs Adds parse-error hints for removed claudecode flags and refactors imports for DB/config.
sql/sqlite_20260415_ai_runtime_contract.sql Introduces idempotent migration for runtime-contract tables.
sql/sqlite_20260309_init.sql Extends bootstrap schema with runtime-contract tables.
docs/improvement/config.md Clarifies provider env migration scope and points to code专项计划.
docs/improvement/README.md Updates improvement plan scope and adds AI Agent专项计划 linkage.
docs/commands/code.md Updates docs for --resume <thread_id> and removes claudecode provider references.
docs/agent/ai-object-model-reference.md Updates scheduler model to selected plan set heads and expands phase mapping notes.
docs/agent/agent-workflow.md Updates workflow phases, selected plan set semantics, and stage gating details.
benches/ai_runtime_baseline.rs Adds a baseline smoke harness for runtime-related micro workloads.
README.md Documents removal of claudecode and migration to canonical --resume <thread_id>.
Cargo.toml Bumps crate version and updates dependencies (git-internal, dagrs).

Comment on lines +297 to +301
let lower = input.to_lowercase();
let mut cursor = 0;
let mut output = String::with_capacity(input.len());

while let Some(relative_start) = lower[cursor..].find(marker) {

let storage_root = resolve_storage_root(&state.working_dir);
let desc_path = storage_root.join("description");
let description = std::fs::read_to_string(&desc_path).unwrap_or_default();
Comment on lines +300 to +303
Self {
status: StatusCode::INTERNAL_SERVER_ERROR,
code: "INTERNAL_ERROR".to_string(),
message: value.to_string(),
Comment on lines +219 to +222
hardening.flush_audit().await.map_err(|error| {
ToolError::ExecutionFailed(format!("failed to flush tool audit sink: {error}"))
})?;
return result;
Comment on lines +208 to +213
/// Preview non-destructive legacy metadata backfill for existing sessions.
pub fn preview_legacy_metadata_backfill(&self) -> io::Result<SessionMetadataBackfillReport> {
self.legacy_metadata_backfill_report(false)
}

/// Apply non-destructive legacy metadata backfill for existing sessions.
}
crate::utils::error::emit_warning("authentication required, retrying...");
emit_warning("authentication required, retrying...");
AUTH.lock().unwrap().replace(ask_basic_auth());

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 709f0c3a21

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

"model": args.model,
"modelProvider": args.model_provider,
"personality": args.personality,
"sandbox": SandboxMode::WorkspaceWrite,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Enforce read-only context in Codex sandbox setup

The Codex startup request hard-codes SandboxMode::WorkspaceWrite here, so --context review/--context research does not preserve the read-only safety contract that other providers enforce. In practice, a user can select a review/research context and still get write-capable Codex execution, which can cause unintended workspace mutations. Please map Codex sandbox mode from the selected context (or reject non-dev contexts for Codex until this is supported).

Useful? React with 👍 / 👎.

Comment thread src/command/code.rs Outdated

let working_dir = resolve_code_working_dir(&args)?;

if args.provider == CodeProvider::Codex {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor --resume in Codex mode or reject it explicitly

This early return sends all Codex runs down a separate path before the TUI resume-loading logic executes, so --resume <thread_id> is accepted by CLI parsing but not actually applied for --provider codex. The result is a silent fresh-session start instead of continuing the requested thread, which breaks expected continuity for users relying on resume. Either propagate the resume thread into Codex startup or return a clear usage error for unsupported combinations.

Useful? React with 👍 / 👎.

Signed-off-by: Quanyi Ma <eli@patch.sh>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

https://github.com/web3infra-foundation/libra/blob/b8ddfbf9450ee29bf47c0ea73588947847b2a0ca/src/internal/tui/bottom_pane.rs#L679-L682
P1 Badge Honor is_secret by masking user-input text in TUI

UserInputQuestion.is_secret is captured but never used in rendering, and the freeform path always calls render_input_area, which displays the raw buffer. For request_user_input prompts that intentionally mark a field secret (e.g., passwords/tokens), the typed value is shown in clear text in the terminal, which can leak sensitive data via screen sharing or local observation. The active question’s is_secret flag should drive masked rendering (and cursor math) while still submitting the original value.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +500 to +503
let id = first_non_empty([input.id.as_deref()])
.map(str::to_string)
.unwrap_or_else(|| "input".to_string());
let header = first_non_empty([input.header.as_deref(), input.title.as_deref()])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject or uniquify fallback IDs for user input questions

When a question omits id, deserialization assigns the constant fallback "input"; downstream answer collection is keyed by question id (HashMap), so multi-question prompts with missing/duplicate ids silently overwrite earlier answers and return incomplete data to the model. Because this parser intentionally accepts lenient shapes, it should either generate unique fallback ids per question or fail fast on non-unique ids before prompting.

Useful? React with 👍 / 👎.

Signed-off-by: Quanyi Ma <eli@patch.sh>
Copilot AI review requested due to automatic review settings April 19, 2026 15:45
Signed-off-by: Quanyi Ma <eli@patch.sh>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR modernizes Libra’s AI runtime workflow and tooling by removing the legacy Claude Code managed provider, improving Ollama support (streaming timeouts + optional cloud auth), adding projection repositories/resolvers, and introducing a libra graph TUI for inspecting thread version graphs.

Changes:

  • Ollama client: streaming-friendly timeouts, OLLAMA_API_KEY bearer auth for direct ollama.com, and updated defaults/docs.
  • AI projection runtime: scheduler CAS repository + resolver, thread-targeted rebuild, selected plan set support, and new SQL tables.
  • Tooling/CLI/docs: add libra graph, tighten tool policy (deny git via shell, add run_libra_vcs), and remove claudecode module/provider guidance.

Reviewed changes

Copilot reviewed 79 out of 180 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/internal/ai/providers/ollama/client.rs Ollama streaming timeouts + optional cloud bearer auth + tests.
src/internal/ai/providers/mod.rs Update Ollama default URL documentation.
src/internal/ai/providers/gemini/client.rs Refactor type alias import for Gemini client.
src/internal/ai/projection/scheduler.rs Add scheduler DB repository, CAS semantics, and selected plan set persistence.
src/internal/ai/projection/resolver.rs New projection resolver for load/rebuild thread bundles.
src/internal/ai/projection/rebuild.rs Add targeted thread rebuild/materialization and selected-plan persistence.
src/internal/ai/projection/mod.rs Export new resolver and scheduler repository types.
src/internal/ai/orchestrator/types.rs Add derived-records persistence and initial plan override.
src/internal/ai/orchestrator/policy.rs Deny git shell usage; add run_libra_vcs; enforce touchFiles write contract.
src/internal/ai/orchestrator/planner.rs Import Check directly for planner task metadata.
src/internal/ai/orchestrator/mod.rs Use approved initial plan on first iteration; make workspace module crate-visible; misc imports/tests.
src/internal/ai/orchestrator/gate.rs Use re-exported run_shell_command.
src/internal/ai/orchestrator/acl.rs Import ToolAcl directly to simplify signatures.
src/internal/ai/node_adapter.rs Standardize execution-failed outputs; add thinking field in tool loop config.
src/internal/ai/mod.rs Remove claudecode module; add runtime/web modules.
src/internal/ai/mcp/server.rs Add optional working dir for MCP server.
src/internal/ai/mcp/resource.rs Add run_libra_vcs MCP tool + commit anchor resolution support.
src/internal/ai/intentspec/review.rs New IntentSpec markdown review renderer + tests.
src/internal/ai/intentspec/repair.rs Ensure libra.vcs ACL rule via repair path.
src/internal/ai/intentspec/profiles.rs Add default libra.vcs allow rule.
src/internal/ai/intentspec/mod.rs Export new review renderer.
src/internal/ai/intentspec/draft.rs Custom DraftCheck deserialization with inferred id/kind + tests.
src/internal/ai/hooks/runtime.rs Prefer direct imports (SessionStore, ConfigKv, emit_warning).
src/internal/ai/history.rs Expose database_connection() accessor.
src/internal/ai/completion/request.rs Add stream event + thinking controls to provider-neutral completion requests.
src/internal/ai/completion/mod.rs Re-export new request types.
src/internal/ai/claudecode/prompts/30-interaction.txt Removed legacy Claude Code prompt rules.
src/internal/ai/claudecode/prompts/20-structured-output.txt Removed legacy Claude Code prompt rules.
src/internal/ai/claudecode/prompts/10-plan-mode.txt Removed legacy Claude Code prompt rules.
src/internal/ai/claudecode/prompts/00-intro.txt Removed legacy Claude Code prompt rules.
src/internal/ai/claudecode/plan_checkpoint.rs Removed legacy Claude Code plan checkpoint flow.
src/internal/ai/claudecode/extraction.rs Removed legacy Claude Code intent extraction commands.
src/internal/ai/claudecode/audit_objects.rs Removed Claude-native audit projections.
src/internal/ai/agent/runtime/tool_loop.rs Forward streaming completion events and pass thinking controls.
src/command/worktree-fuse.rs Refactor conditionals and mount handle removal logic.
src/command/stash.rs Simplify imports and use load_object directly.
src/command/shortlog.rs Use require_repo() import.
src/command/reflog.rs Simplify imports and reuse log formatting/date parsing.
src/command/rebase.rs Use emit_warning import consistently.
src/command/push.rs Use LFSClient import directly.
src/command/open.rs Use LIBRA_TEST_ENV and require_repo() imports.
src/command/mod.rs Add graph module; use emit_warning import.
src/command/merge.rs Simplify stable error code imports and output printing.
src/command/log.rs Use tag module imports directly.
src/command/init.rs Use StableErrorCode and get_db_conn_instance_for_path imports directly.
src/command/grep.rs Use record_warning() import directly.
src/command/fetch.rs Import vault/config helpers directly; use try_get_storage_path.
src/command/config.rs Import db/vault helpers directly; use emit_json_data, LIBRA_TEST_ENV, try_get_storage_path.
src/command/commit.rs Use save_object_to_storage import directly.
src/command/cloud.rs Import restore/head/branch + emit_warning directly; restore worktree after cloud restore.
src/command/clone.rs Import discovery/db helpers directly.
src/command/checkout.rs Use info_println import directly.
src/command/cat_file.rs Use parse_commit_msg import directly.
src/command/branch.rs Use get_reachable_commits, require_repo, info_println imports directly.
src/command/bisect.rs Use info_println import directly.
src/cli.rs Add graph command + better repo preflight + claudecode removal hints + tests.
sql/sqlite_20260415_ai_runtime_contract.sql New AI runtime contract migration tables (selected plan + validation/risk/decision + provider metadata).
sql/sqlite_20260309_init.sql Extend init schema with selected plan + validation/risk/decision + provider metadata tables.
docs/improvement/config.md Clarify provider env follow-up ownership under code.md plan.
docs/improvement/README.md Reclassify AI agent items under dedicated plan; update follow-up sections.
docs/commands/graph.md New documentation for libra graph.
docs/commands/code.md Update code command docs for managed runtime migration, resume semantics, Ollama thinking, and graph.
docs/commands/README.md Add libra graph to command list.
docs/agent/ai-object-model-reference.md Update scheduler selected plan model to selected plan set.
docs/agent/agent-workflow.md Update workflow phases and selected plan set semantics.
benches/ai_runtime_baseline.rs Add baseline timing smoke harness.
README.md Document graph command and remove legacy claudecode provider instructions.
Cargo.toml Bump crate version and dependency versions.

Comment on lines +83 to +86
provider: OllamaProvider {
cloud_api: is_ollama_cloud_base_url(base_url),
api_key,
},
}

/// Creates an Ollama client with an explicit API key.
pub fn with_base_url_and_api_key(base_url: &str, api_key: Option<String>) -> Self {
}

#[test]
fn test_client_new_local() {
let client = Client::new_local();
assert_eq!(client.base_url, DEFAULT_BASE_URL);
assert_eq!(client.base_url, "http://127.0.0.1:11434/v1");
active_run_id: None,
live_context_window: Vec::new(),
metadata: None,
updated_at: chrono::Utc::now(),
Comment on lines +443 to +449
/// Runtime-owned derived records emitted from validation and decision stages.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct PersistedDerivedRecords {
pub validation_report_id: Uuid,
pub risk_score_breakdown_id: Uuid,
pub decision_proposal_id: Uuid,
}
Comment on lines +91 to +97
#[serde(rename = "timeoutSeconds", default)]
timeout_seconds: Option<u64>,
#[serde(rename = "expectedExitCode", default)]
expected_exit_code: Option<i32>,
#[serde(default = "default_true")]
required: bool,
#[serde(rename = "artifactsProduced", default)]
Comment on lines +156 to 165
let (stream_tx, mut stream_rx) = tokio::sync::mpsc::unbounded_channel();
let request = CompletionRequest {
preamble: config.preamble.clone(),
chat_history: history.clone(),
temperature: config.temperature,
thinking: config.thinking,
tools: tools.clone(),
stream_events: Some(stream_tx),
..Default::default()
};
Comment on lines +1011 to +1029
let child = Command::new(executable)
.arg(command)
.args(&args)
.current_dir(&working_dir)
.stdin(Stdio::null())
.output();

match timeout(Duration::from_secs(LIBRA_VCS_TIMEOUT_SECONDS), child).await {
Ok(Ok(output)) => Ok(format_libra_vcs_output(command, &args, output)),
Ok(Err(err)) => Err(ErrorData::internal_error(
format!("failed to run Libra VCS command '{command}': {err}"),
None,
)),
Err(_) => Ok(CallToolResult::error(vec![Content::text(format!(
"Libra VCS command timed out after {}s: {}",
LIBRA_VCS_TIMEOUT_SECONDS,
format_libra_vcs_invocation(command, &args)
))])),
}

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5d9be1b8cf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +302 to +304
"run_libra_vcs" => {
let params: RunLibraVcsParams = parse_args(&arguments)?;
self.server.run_libra_vcs_impl(params).await

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Route run_libra_vcs through runtime approval/sandbox checks

This branch forwards run_libra_vcs directly to run_libra_vcs_impl without consulting invocation.runtime_context (sandbox policy / approval mediation). Since the new allowlist includes mutating commands like add, commit, and switch, the agent can perform repository writes through this path even when libra code is running in read-only contexts (e.g. review/research), which breaks the read-only safety contract and enables unintended mutations. Please gate this tool with the same runtime sandbox+approval enforcement used for shell mutations, or reject mutating VCS subcommands when the context is read-only.

Useful? React with 👍 / 👎.

Comment on lines +1024 to +1028
Err(_) => Ok(CallToolResult::error(vec![Content::text(format!(
"Libra VCS command timed out after {}s: {}",
LIBRA_VCS_TIMEOUT_SECONDS,
format_libra_vcs_invocation(command, &args)
))])),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Kill timed-out run_libra_vcs child process

On timeout, this path returns an error message but does not terminate the spawned libra subprocess. Because the command is launched via Command::output() and no explicit kill/wait happens in the timeout branch, long-running commands can continue in the background after the tool reports timeout, causing leaked processes and ongoing side effects. Switch to managing a Child handle and explicitly kill + wait on timeout.

Useful? React with 👍 / 👎.

Signed-off-by: Quanyi Ma <eli@patch.sh>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 192611c0c0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1011 to +1016
let child = Command::new(executable)
.arg(command)
.args(&args)
.current_dir(&working_dir)
.stdin(Stdio::null())
.output();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Cap run_libra_vcs output instead of buffering full stdout

run_libra_vcs_impl launches allowlisted commands with Command::output(), which buffers all stdout/stderr in memory before returning. Commands like log or show can emit very large output on real repositories, so a single tool call can consume unbounded memory and destabilize or crash the MCP process before the timeout path is reached. Please switch to a streamed child process read with explicit byte limits (similar to the shell handler’s output cap) and truncate safely.

Useful? React with 👍 / 👎.

Comment on lines +197 to +200
let current_snapshot = runtime.snapshot().await;
let initial_event = ensure_session_updated_event(&current_snapshot)?;
let receiver = runtime.subscribe();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Subscribe to code events before snapshotting session state

The SSE handler snapshots session state and only then subscribes to the broadcast channel, which creates a race window where an update can occur between those two operations; that update is then missed, and if no later event arrives the browser remains stale. Register the subscriber first and then emit a snapshot/event derived from the latest state so no transition is dropped during connection setup.

Useful? React with 👍 / 👎.

Signed-off-by: Quanyi Ma <eli@patch.sh>
Copilot Bot review requested due to automatic review settings April 19, 2026 18:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR updates the AI agent/runtime “code” workflow to be provider-neutral and projection-driven, adding a dedicated thread graph inspector while tightening tool policy and removing the legacy Claude Code managed runtime.

Changes:

  • Introduces scheduler projection persistence (selected plan set, live context window, CAS updates) and a projection resolver for load/rebuild flows.
  • Adds libra graph TUI command and documentation for inspecting canonical AI thread graphs.
  • Hardens runtime/tooling policy (deny git via shell, add run_libra_vcs ACL/action mapping), plus new completion streaming/thinking plumbing.

Reviewed changes

Copilot reviewed 76 out of 180 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/internal/ai/projection/scheduler.rs Adds DB-backed scheduler state repository + CAS updates, selected plan set persistence, and enum ↔ row conversions.
src/internal/ai/projection/resolver.rs Adds resolver to load a thread bundle and optionally rebuild projections.
src/internal/ai/projection/rebuild.rs Adds targeted rebuild/materialize APIs and persists selected plan set rows.
src/internal/ai/projection/mod.rs Exposes new resolver and scheduler repository types.
src/internal/ai/orchestrator/types.rs Extends persisted execution with derived records + adds observer hooks and initial plan support.
src/internal/ai/orchestrator/policy.rs Denies git usage via shell, adds run_libra_vcs action mapping, and tightens write-contract validation.
src/internal/ai/orchestrator/planner.rs Simplifies Check type usage in planner metadata.
src/internal/ai/orchestrator/mod.rs Adds initial plan support and observer callbacks for verification/decision.
src/internal/ai/orchestrator/gate.rs Imports run_shell_command directly.
src/internal/ai/orchestrator/acl.rs Refactors ACL signatures to use ToolAcl type alias/import.
src/internal/ai/node_adapter.rs Uses Output::execution_failed consistently and sets tool-loop thinking config to None.
src/internal/ai/mod.rs Removes legacy claudecode module and adds runtime/web modules.
src/internal/ai/mcp/server.rs Adds optional working dir to MCP server constructors.
src/internal/ai/mcp/resource.rs Adds run_libra_vcs MCP tool, HEAD commit anchor resolution, and argument validation.
src/internal/ai/intentspec/review.rs Adds Markdown renderer for IntentSpec review flow + tests.
src/internal/ai/intentspec/repair.rs Adds libra.vcs ACL rule repair helper and QualityGates import cleanup.
src/internal/ai/intentspec/profiles.rs Adds default libra.vcs allow rule in security profile.
src/internal/ai/intentspec/mod.rs Exposes IntentSpec review builder.
src/internal/ai/intentspec/draft.rs Adds custom DraftCheck deserialization with derived IDs/kinds + tests.
src/internal/ai/hooks/runtime.rs Refactors imports and uses shared helpers (emit_warning, ConfigKv, SessionStore).
src/internal/ai/history.rs Exposes database_connection() accessor.
src/internal/ai/completion/request.rs Adds streaming event sink + provider-neutral thinking mode to requests.
src/internal/ai/completion/mod.rs Re-exports new completion request types.
src/internal/ai/claudecode/prompts/00-intro.txt Removes legacy Claude Code prompt bundle file.
src/internal/ai/claudecode/prompts/10-plan-mode.txt Removes legacy Claude Code prompt bundle file.
src/internal/ai/claudecode/prompts/20-structured-output.txt Removes legacy Claude Code prompt bundle file.
src/internal/ai/claudecode/prompts/30-interaction.txt Removes legacy Claude Code prompt bundle file.
src/internal/ai/claudecode/plan_checkpoint.rs Removes legacy Claude Code plan checkpoint logic.
src/internal/ai/claudecode/extraction.rs Removes legacy Claude Code extraction CLI utilities.
src/internal/ai/claudecode/audit_objects.rs Removes legacy Claude Code derived audit read models.
src/internal/ai/agent/runtime/tool_loop.rs Forwards provider streaming events and adds thinking option to tool loop config.
src/command/worktree-fuse.rs Refactors control flow around restore/unmount and mount-handle lookup.
src/command/stash.rs Uses load_object directly via module import reshuffle.
src/command/shortlog.rs Uses require_repo() via import for consistency.
src/command/reflog.rs Imports log formatting + date parsing helpers directly.
src/command/rebase.rs Uses emit_warning via import for consistency.
src/command/push.rs Imports LFSClient directly.
src/command/open.rs Uses require_repo() and LIBRA_TEST_ENV via imports.
src/command/mod.rs Adds graph module and uses emit_warning via import.
src/command/merge.rs Uses stable error codes via import and info_println macro via import.
src/command/log.rs Imports tag module/types directly for decoration.
src/command/init.rs Imports DB helper directly; stable error codes via import.
src/command/grep.rs Uses record_warning() via import for consistency.
src/command/fetch.rs Imports vault/config helpers and try_get_storage_path directly.
src/command/config.rs Refactors to direct imports for DB/vault helpers + JSON output, avoids blocking in tests.
src/command/commit.rs Imports save_object_to_storage directly.
src/command/cloud.rs Refactors to direct imports and uses emit_warning.
src/command/clone.rs Imports discovery/db helpers directly.
src/command/checkout.rs Uses info_println macro via import.
src/command/cat_file.rs Imports parse_commit_msg directly.
src/command/branch.rs Uses direct import for reachable-commit helper + require_repo() and info_println.
src/command/bisect.rs Uses info_println macro via import for consistency.
src/cli.rs Adds graph command, improves code-command preflight storage selection, and provides hints for removed claudecode flags.
sql/sqlite_20260415_ai_runtime_contract.sql Adds Phase 0 contract migration tables (selected plans + validation/decision tables + provider metadata).
sql/sqlite_20260309_init.sql Updates initial schema with new AI runtime contract tables.
docs/improvement/config.md Updates config plan notes to align with code.md follow-up and runtime migration decisions.
docs/improvement/README.md Reframes AI agent work as a dedicated plan and updates remaining cleanup notes.
docs/commands/graph.md Adds documentation for new libra graph command.
docs/commands/code.md Updates libra code docs for canonical --resume <thread_id>, planning workflow, and run_libra_vcs.
docs/commands/README.md Lists libra graph in top-level command docs.
docs/agent/ai-object-model-reference.md Updates scheduler model from selected_plan_id to selected_plan_ids[] and expands workflow mapping.
docs/agent/agent-workflow.md Updates workflow phases (IntentSpec + plan review loops, staged execution/test plans).
benches/ai_runtime_baseline.rs Adds baseline “smoke” measurement harness for runtime-related operations.
README.md Documents managed runtime migration and adds graph command + updated provider notes.
Cargo.toml Bumps crate + dependency versions and adds graph module to build.

Comment on lines +212 to +217
let txn = self
.db
.begin()
.await
.context("Failed to start scheduler state CAS transaction")?;
let thread_id = next.thread_id.to_string();
Comment on lines +254 to +274
if result.rows_affected != 1 {
let actual = ai_scheduler_state::Entity::find_by_id(thread_id)
.one(&txn)
.await
.with_context(|| {
format!(
"Failed to load scheduler state {} after CAS conflict",
next.thread_id
)
})?
.map(|row| row.version);
return match actual {
Some(actual) => Err(SchedulerStateCasError::VersionConflict {
thread_id: next.thread_id,
expected: expected_version,
actual: Some(actual),
}),
None => Err(SchedulerStateCasError::Missing {
thread_id: next.thread_id,
}),
};
Comment on lines +467 to +481
for selected_plan in &state.selected_plan_ids {
ai_scheduler_selected_plan::ActiveModel {
thread_id: Set(thread_id.clone()),
plan_id: Set(selected_plan.plan_id.to_string()),
ordinal: Set(selected_plan.ordinal),
}
.insert(db)
.await
.with_context(|| {
format!(
"Failed to insert selected scheduler plan {} for thread {}",
selected_plan.plan_id, state.thread_id
)
})?;
}
Comment on lines +443 to +449
/// Runtime-owned derived records emitted from validation and decision stages.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct PersistedDerivedRecords {
pub validation_report_id: Uuid,
pub risk_score_breakdown_id: Uuid,
pub decision_proposal_id: Uuid,
}
Comment on lines +1011 to +1029
let child = Command::new(executable)
.arg(command)
.args(&args)
.current_dir(&working_dir)
.stdin(Stdio::null())
.output();

match timeout(Duration::from_secs(LIBRA_VCS_TIMEOUT_SECONDS), child).await {
Ok(Ok(output)) => Ok(format_libra_vcs_output(command, &args, output)),
Ok(Err(err)) => Err(ErrorData::internal_error(
format!("failed to run Libra VCS command '{command}': {err}"),
None,
)),
Err(_) => Ok(CallToolResult::error(vec![Content::text(format!(
"Libra VCS command timed out after {}s: {}",
LIBRA_VCS_TIMEOUT_SECONDS,
format_libra_vcs_invocation(command, &args)
))])),
}
Comment on lines +69 to +87
#[test]
fn ai_runtime_baseline_harness_smoke() {
let measurements = [
measure("100_task_dag_build", build_100_task_dag),
measure("10k_event_targeted_rebuild", targeted_rebuild_10k_events),
measure("live_context_compaction", compact_live_context_window),
measure("audit_flush_query", audit_flush_and_query),
];

for measurement in measurements {
eprintln!("{}: {:?}", measurement.name, measurement.elapsed);
assert!(
measurement.elapsed < Duration::from_secs(5),
"{} baseline smoke exceeded 5s: {:?}",
measurement.name,
measurement.elapsed
);
}
}

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

https://github.com/web3infra-foundation/libra/blob/67d3e759d8366554a0054c47eddf22bcc296a184/src/internal/ai/tools/handlers/grep_files.rs#L201
P1 Badge Surface grep traversal failures instead of swallowing them

This loop drops every WalkDir error with filter_map(|e| e.ok()), so invalid or unreadable path inputs are reported to the model as a successful empty result (No matches found) rather than an execution error. In practice, a typoed path or permission-denied directory becomes a silent failure and can mislead follow-up planning. Please propagate at least root traversal errors (and ideally per-entry errors) instead of discarding them.


https://github.com/web3infra-foundation/libra/blob/67d3e759d8366554a0054c47eddf22bcc296a184/src/internal/ai/tools/handlers/grep_files.rs#L222-L223
P2 Badge Preserve filename output when searching a single file path

When path points to a file (which this tool accepts), path.strip_prefix(search_path) resolves to an empty relative path for the matched file, so the returned result contains a blank line instead of a usable file path. That breaks callers that rely on file paths from grep_files results. Use a file-aware relative-base (for example, search_path.parent() when search_path is a file) so single-file searches still return the filename.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Signed-off-by: Quanyi Ma <eli@patch.sh>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ecce1a3197

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/command/code.rs Outdated
Comment on lines +523 to +527
&& let Some(ref cwd_path) = args.cwd
&& cwd_path.exists()
&& cwd_path.is_file()
{
args.codex_bin = cwd_path.to_string_lossy().to_string();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep --cwd strictly as a working-directory argument

In Codex TUI mode this branch rewrites an existing file passed to --cwd into args.codex_bin, so an invalid working-directory input no longer fails validation and can instead be executed as a subprocess. That makes libra code --provider codex --cwd <file> behave dangerously differently from other modes (and from CLI docs), and a typo like --cwd README.md can try to launch that file as the Codex binary. Preserve --cwd as directory-only and require --codex-bin for executable overrides.

Useful? React with 👍 / 👎.

Signed-off-by: Eli Ma <eli@patch.sh>
Copilot Bot review requested due to automatic review settings April 21, 2026 06:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR refactors Libra’s AI “code” runtime and projection layer to support a provider-neutral managed workflow, adds a thread graph inspection command, and tightens tool policy/ACL handling (including blocking direct git usage).

Changes:

  • Add projection resolver + targeted projection rebuild/materialization paths, including new scheduler selected-plan persistence.
  • Introduce MCP run_libra_vcs tool and policy enforcement to disallow git via shell, plus tighter write-contract enforcement via touchFiles.
  • Add libra graph TUI command and remove legacy claudecode provider/runtime code paths and prompts.

Reviewed changes

Copilot reviewed 75 out of 180 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/internal/ai/projection/resolver.rs New read-side resolver to load/rebuild thread + scheduler projections with freshness signaling.
src/internal/ai/projection/rebuild.rs Adds targeted rebuild/materialize APIs and persists selected plans into new table.
src/internal/ai/projection/mod.rs Exposes new resolver types and scheduler repository exports.
src/internal/ai/orchestrator/types.rs Adds phase gating types, derived-record persistence hooks, and observer callbacks.
src/internal/ai/orchestrator/policy.rs Enforces “no git via shell”, adds run_libra_vcs footprint/ACL, and centralizes write-contract validation.
src/internal/ai/orchestrator/planner.rs Simplifies check type import usage.
src/internal/ai/orchestrator/gate.rs Uses direct import of run_shell_command.
src/internal/ai/orchestrator/acl.rs Refactors ACL APIs to use ToolAcl import type.
src/internal/ai/node_adapter.rs Normalizes execution error outputs and sets default thinking config.
src/internal/ai/mod.rs Removes claudecode module; adds runtime/web modules.
src/internal/ai/mcp/server.rs Adds optional working directory for MCP server.
src/internal/ai/mcp/resource.rs Adds run_libra_vcs, HEAD commit anchor resolution, and command allowlisting/validation.
src/internal/ai/intentspec/review.rs New Markdown “IntentSpec review” renderer with tests.
src/internal/ai/intentspec/repair.rs Ensures libra.vcs ACL rule during spec repair.
src/internal/ai/intentspec/profiles.rs Adds default libra.vcs allow rule.
src/internal/ai/intentspec/mod.rs Re-exports review builder.
src/internal/ai/intentspec/draft.rs Custom DraftCheck deserialization with derived kind/id behavior + tests.
src/internal/ai/hooks/runtime.rs Imports SessionStore/ConfigKv directly and uses shared emit_warning.
src/internal/ai/history.rs Exposes database_connection() accessor.
src/internal/ai/completion/request.rs Adds streaming events + thinking controls to completion requests.
src/internal/ai/completion/mod.rs Re-exports new completion streaming/thinking types.
src/internal/ai/claudecode/snapshot_family.rs Removed legacy Claude Code snapshot family projections.
src/internal/ai/claudecode/prompts/30-interaction.txt Removed legacy Claude Code prompt fragments.
src/internal/ai/claudecode/prompts/20-structured-output.txt Removed legacy Claude Code prompt fragments.
src/internal/ai/claudecode/prompts/10-plan-mode.txt Removed legacy Claude Code prompt fragments.
src/internal/ai/claudecode/prompts/00-intro.txt Removed legacy Claude Code prompt intro.
src/internal/ai/claudecode/plan_checkpoint.rs Removed legacy Claude Code plan checkpoint prompt implementation.
src/internal/ai/claudecode/extraction.rs Removed legacy Claude Code extraction/intent persistence commands.
src/internal/ai/claudecode/common.rs Removed legacy Claude Code helper/common utilities.
src/internal/ai/claudecode/audit_objects.rs Removed legacy Claude Code derived audit object projection logic.
src/internal/ai/agent/runtime/tool_loop.rs Adds request streaming plumbing and hooks import cleanup.
src/command/worktree-fuse.rs Refactors control flow and active mount handle retrieval/unmount error handling.
src/command/stash.rs Uses load_object via module import path refactor.
src/command/shortlog.rs Imports and uses require_repo helper.
src/command/reflog.rs Imports shared date parsing + stat formatting helpers.
src/command/rebase.rs Uses shared emit_warning helper.
src/command/push.rs Imports LFSClient directly.
src/command/open.rs Uses require_repo and LIBRA_TEST_ENV imports.
src/command/mod.rs Adds graph command module and shared emit_warning import.
src/command/merge.rs Uses imported StableErrorCode + info_println macro.
src/command/log.rs Imports tag module/types for decoration.
src/command/init.rs Imports DB helpers and StableErrorCode directly.
src/command/grep.rs Uses record_warning import.
src/command/fetch.rs Imports vault helpers + try_get_storage_path and ConfigKvEntry types.
src/command/config.rs Consolidates imports and uses shared vault/db helpers + JSON emit helpers.
src/command/commit.rs Uses imported save_object_to_storage.
src/command/cloud.rs Uses imported Head/Branch/restore/emit_warning; simplifies restore flow.
src/command/clone.rs Uses imported DiscoveryResult and DB connection getter.
src/command/checkout.rs Uses info_println macro import.
src/command/cat_file.rs Uses imported parse_commit_msg.
src/command/branch.rs Uses imported get_reachable_commits, require_repo, and info_println.
src/command/bisect.rs Uses info_println macro import across status outputs.
src/cli.rs Adds graph command wiring, improves preflight repo selection, and adds parse hints for removed claudecode flags.
sql/sqlite_20260415_ai_runtime_contract.sql Adds AI runtime contract tables (selected plans, validation/risk/decision projections, provider metadata).
sql/sqlite_20260309_init.sql Extends initial schema with the same contract tables.
docs/improvement/config.md Updates config improvement plan notes re: provider env migration ownership.
docs/improvement/README.md Clarifies AI Agent plan tracking and moves provider follow-up into code.md.
docs/commands/graph.md New command documentation for libra graph.
docs/commands/code.md Updates libra code docs (resume flow, provider list, planning workflow, MCP VCS tool).
docs/commands/README.md Adds libra graph to command index.
docs/agent/ai-object-model-reference.md Updates scheduler model docs for selected plan set + phase workflow updates.
docs/agent/agent-workflow.md Updates workflow docs for plan set, phase gating, and validator routing.
benches/ai_runtime_baseline.rs Adds a baseline harness test for runtime building blocks.
README.md Adds graph command and documents managed runtime migration away from claudecode.
Cargo.toml Bumps version and updates dependencies (git-internal, dagrs).

Comment on lines +1011 to +1029
let child = Command::new(executable)
.arg(command)
.args(&args)
.current_dir(&working_dir)
.stdin(Stdio::null())
.output();

match timeout(Duration::from_secs(LIBRA_VCS_TIMEOUT_SECONDS), child).await {
Ok(Ok(output)) => Ok(format_libra_vcs_output(command, &args, output)),
Ok(Err(err)) => Err(ErrorData::internal_error(
format!("failed to run Libra VCS command '{command}': {err}"),
None,
)),
Err(_) => Ok(CallToolResult::error(vec![Content::text(format!(
"Libra VCS command timed out after {}s: {}",
LIBRA_VCS_TIMEOUT_SECONDS,
format_libra_vcs_invocation(command, &args)
))])),
}
Comment on lines +442 to +450
fn libra_vcs_action(command: &str) -> Result<&'static str, String> {
match command.trim() {
"status" | "diff" | "branch" | "log" | "show" | "show-ref" => Ok("read"),
"add" | "commit" | "switch" => Ok("write"),
"" => Err("missing run_libra_vcs command".to_string()),
other => Err(format!(
"unsupported run_libra_vcs command '{other}'; use an allowlisted Libra VCS command"
)),
}
Ok(()) => return Ok(()),
Err(e) => {
let ioe: io::Error = e.into();
let ioe: io::Error = e;
Comment on lines +902 to +913
if tasks
.iter()
.any(|task| task.header().object_id() == thread_id)
|| runs.iter().any(|run| run.task() == thread_id)
{
return Some(SelectedThread {
thread_id,
intent_ids: HashSet::new(),
plan_ids: HashSet::new(),
task_ids: HashSet::from([thread_id]),
});
}
Comment on lines +59 to +86
pub async fn load_or_rebuild_thread_bundle(
&self,
thread_id: ThreadId,
rebuilder: &ProjectionRebuilder<'_>,
) -> Result<Option<ThreadBundle>> {
let existing = self.load_thread_bundle(thread_id).await?;
if existing
.as_ref()
.is_some_and(|bundle| bundle.freshness == ProjectionFreshness::Fresh)
{
return Ok(existing);
}

match rebuilder.materialize_thread(&self.db, thread_id).await {
Ok(Some(_)) => self.load_thread_bundle(thread_id).await,
Ok(None) => Ok(existing),
Err(error) => {
if let Some(mut bundle) = existing {
bundle.freshness = ProjectionFreshness::Unavailable;
Ok(Some(bundle))
} else {
Err(error.context(format!(
"Failed to rebuild missing projection for thread {thread_id}"
)))
}
}
}
}

genedna commented Apr 21, 2026

Copy link
Copy Markdown
Contributor Author

Code Review — PR #350 "Improve code command"

Thanks for the large and well-organized refactor. The runtime/orchestrator redesign into explicit Phase 3/4 contracts, the removal of the claudecode provider surface, the new libra graph visualizer, and the browser-facing CodeUiRuntimeHandle together represent a significant step toward a clearly auditable AI execution model. This review covers ~180 files. Below is a consolidated list of findings ordered by severity, with concrete file:line references so they can be addressed inline.

Scope reviewed

  • src/command/code.rs, src/command/graph.rs, src/cli.rs
  • src/internal/ai/codex/*, src/internal/ai/orchestrator/*, src/internal/ai/runtime/*, src/internal/ai/agent/runtime/tool_loop.rs
  • src/internal/ai/tools/handlers/*, src/internal/ai/tools/registry.rs, src/internal/ai/tools/spec.rs
  • src/internal/ai/mcp/resource.rs, src/internal/ai/mcp/server.rs
  • src/internal/ai/intentspec/*
  • src/internal/ai/web/mod.rs, src/internal/ai/web/code_ui.rs
  • src/internal/tui/* (spot checks)
  • sql/sqlite_20260309_init.sql, sql/sqlite_20260415_ai_runtime_contract.sql, new models under src/internal/model/
  • tests/ai_*, tests/command/code_test.rs, tests/command/graph_test.rs, tests/helpers/*
  • web/src/components/** and benches/ai_runtime_baseline.rs

Some findings below were flagged by automated analysis and have been spot-verified; where I could not fully verify without running the change, I mark the item "worth double-checking".


Critical / Major

  1. apply_patch skips the approval policy entirely when runtime_context.approval is Nonesrc/internal/ai/tools/handlers/apply_patch.rs:70. The if let Some(approval_ctx) = … guard means the AskForApproval::Never branch (which should return an error if the patch writes outside the workspace) is never evaluated when there is no approval sink. A tool-loop configured without an approval channel will therefore happily apply patches outside the workspace. Recommend computing patch_needs_approval(policy, constrained_to_workspace) unconditionally and only using approval_ctx to dispatch the UI prompt.

  2. Non-atomic validate_path + canonicalize in the shell workdir resolversrc/internal/ai/tools/handlers/shell.rs:167-193. Symlinks can be swapped between validate_path and the second canonicalize; the safer pattern is to canonicalize once and then do the containment check on the canonical form. Since the registry forcibly rewrites working_dir (src/internal/ai/tools/registry.rs:168), the blast radius is limited to attacker-controlled args.workdir, but the fix is small.

  3. Optional FKs in the new schema lack FOREIGN KEY constraintssql/sqlite_20260415_ai_runtime_contract.sql. ai_risk_score_breakdown.validation_report_id and ai_decision_proposal.risk_score_breakdown_id reference other tables logically but have no referential integrity, so orphans are produced when the parent row is deleted. Add FOREIGN KEY (...) REFERENCES ... ON DELETE SET NULL (or CASCADE as appropriate) to match the rest of the schema.

  4. Duplicate table definition across bootstrap and migration SQLai_scheduler_selected_plan is declared in both sql/sqlite_20260309_init.sql and sql/sqlite_20260415_ai_runtime_contract.sql. Both use IF NOT EXISTS so migrations still apply cleanly, but a schema drift between the two files will be silent. Pick one source of truth and have the other include/re-run it, or comment the intentional duplication loudly.

  5. std::sync::Mutex held across async boundaries / used on the tokio path — several call sites in src/command/code.rs (around line 403 and line 1516) and in src/internal/ai/codex/mod.rs (around line 1992) take a std::sync::Mutex lock in an async function. This blocks the tokio worker and, for the codex path, the lock is also released before the subsequent find(), creating a check-then-act race on session state. Replace with tokio::sync::Mutex or restructure so the lock is held for the whole critical section.

  6. Blocking filesystem calls in async handlerssrc/internal/ai/web/mod.rs:177 (std::fs::read_to_string(&desc_path).unwrap_or_default()) and src/command/code.rs:~1615 (std::fs::create_dir_all inside init_mcp_server). On a loaded runtime these can stall the executor; use tokio::fs or wrap in spawn_blocking.

  7. Embedded web server exposes GET /api/code/session, GET /api/code/events, and GET /api/repo without authenticationsrc/internal/ai/web/mod.rs:96-111,152-210. Write endpoints gate on the "browser controller token" but reads do not. If the server ever binds to anything but 127.0.0.1, any local process or LAN peer can stream session events (including, potentially, user prompts and agent outputs). Please document the intended binding, assert it at startup, and consider requiring the controller token on reads too.

  8. inline_definitions recurses without a depth limitsrc/internal/ai/tools/handlers/mcp_bridge.rs:54-82. Although the schemas come from internal schemars types today, a future cyclic or deeply nested MCP schema would stack-overflow the process. Add a recursion budget (and break circular $ref chains).

  9. Tool-boundary policy uses prefix matching on tool namessrc/internal/ai/runtime/hardening.rs:~95,113. Rules like starts_with("list_") will match any new tool whose name happens to begin with list_ (e.g. list_secrets). This is a fragile allow-list. Prefer an explicit enum or a verified allow-list built from the registry.

  10. Unbounded channel for completion stream eventssrc/internal/ai/agent/runtime/tool_loop.rs:~167. unbounded_channel gives the model side no backpressure; a verbose tokenizer or a stalled consumer can grow memory without bound. Use a bounded channel and surface the backpressure.

  11. Secret-redaction cost is O(n·m)src/internal/ai/runtime/hardening.rs:~297. Calling to_lowercase() on the full input for every marker allocates a fresh string per marker and rewalks the buffer. Compile an aho_corasick / regex::RegexSet once per redactor and redact in a single pass.

  12. Retry feedback is injected into the next prompt without sanitizationsrc/internal/ai/orchestrator/executor.rs:~268. If the upstream failure message contained untrusted content (tool output, shell stderr), it becomes part of the next model prompt verbatim. At minimum, run the existing SecretRedactor and clamp the length before re-injecting.

  13. patch_needs_approval path interaction — see move mercury and libra #1. Once that is fixed, please add a test where runtime_context.approval is None and the patch writes outside the workspace, to lock in the behavior.

Minor

  1. Unwraps/expects in tests without the // INVARIANT: comment required by CLAUDE.md — many spots, e.g. src/command/code.rs:1910,1946,2008,2030, src/command/graph.rs:1481,1487,1496, src/cli.rs:836-856, tests/ai_hardening_contract_test.rs:100, tests/ai_schema_migration_test.rs:14. The project guideline is clear; adding the comments (or replacing with .expect("…") with a proper message) makes intent easier to audit.

  2. panic! inside test timeout / error branches hides diagnosticstests/ai_ollama_live_gate_test.rs:143, tests/ai_dagrs_081_spike_test.rs:55. Prefer assert!/Result so the assertion framework preserves context.

  3. ai_ollama_live_gate_test gated with env var but not #[ignore]tests/ai_ollama_live_gate_test.rs:43. Today it silently "passes" in CI regardless of whether the gate is satisfied. Mark it #[ignore] and invoke with --ignored when the infrastructure is available, or have it panic! if the env var is set but Ollama is unreachable.

  4. Bench uses #[test]benches/ai_runtime_baseline.rs:~70. Functionally fine, but it runs on every cargo test. Either switch to a proper criterion bench or gate behind #[cfg(feature = "bench")].

  5. Empty pub enum Relation {} on every new SeaORM modelsrc/internal/model/ai_{decision_proposal,risk_score_breakdown,scheduler_selected_plan,thread_provider_metadata,validation_report}.rs. Without DeriveRelation, you cannot do type-safe joins against ai_thread / each other. Add the relations now that the FKs are being fixed (see replace mercury with git-internal #3).

  6. ensure_runtime_thread with on_conflict.do_nothing()src/internal/ai/runtime/phase3.rs:~150. Semantics unclear when a thread row exists with stale metadata; please either document the "first writer wins" behavior or switch to do_update() with an explicit merge.

  7. Tests for the runtime contract tables don't always load the migrationtests/ai_validation_decision_flow_test.rs:~22 uses sqlite::memory: with only BOOTSTRAP_SQL. If that file doesn't include the new tables, the test is validating against a schema that never ships. Confirm the bootstrap SQL fully includes the new tables, or call ensure_ai_runtime_contract_schema explicitly.

  8. Result<T> in tests/ helpers using .unwrap() on query_one / tempdir()tests/ai_schema_migration_test.rs:14, tests/helpers/mock_codex.rs, tests/helpers/mock_completion_model.rs. Same CLAUDE.md remark as add .devcontainer #14; add .expect("…") messages or propagate.

  9. resolve_workdir / resolve_list_dir_path do path validation before canonicalization, then trim '?' suffixessrc/internal/ai/tools/handlers/list_dir.rs:103-133. The trim-then-revalidate is okay today because resolve_path re-runs containment, but the two-layer fallback makes the security argument harder to follow. A comment, or a single authoritative path-resolution helper, would help.

  10. actor_kind / actor_id accepted from tool-call arguments without allowlistsrc/internal/ai/mcp/resource.rs:~105, src/internal/ai/tools/handlers/mcp_bridge.rs:~307. If the audit trail is meant to distinguish human vs system vs agent, the caller must not be able to forge actor_kind = "human". Validate against an enum.

  11. format!("{:?}", args.provider).to_lowercase()src/command/code.rs:~593. Debug formatting is a fragile way to get the canonical provider name; implement Display or use clap::ValueEnum::to_possible_value so a #[derive(Debug)] rename doesn't silently break dispatch.

  12. unwrap_or(response) after parsing a JSON resultsrc/internal/ai/codex/mod.rs:~1440. Falling back to the raw error envelope on a missing result field can propagate an error payload as if it were success. Match both variants explicitly.

  13. derive_check_id can collidesrc/internal/ai/intentspec/draft.rs:~80. Two different shell commands that slugify to the same identifier overwrite each other silently. Either keep the full hash or assert uniqueness when inserting.

  14. Graph command: heavy repeat of .cloned().unwrap_or_default()src/command/graph.rs:553,576,594,600,813,849. Not a bug, but a small with_context helper or get_or_default inherent method would de-duplicate noticeably.

Nits / Style

  • Remove the ~70 lines of mixed Chinese/English doc comments in src/internal/ai/codex/mod.rs (around line 1075). Pick one language to keep the module readable.
  • resolve_workdir error uses path.display() but list_dir.rs returns raw lossy strings — unify the two (see 为libra log命令添加 --name-only 参数 #21 #22).
  • web/src/components/code-session/code-session-page.tsx is large (948 LoC) and could be decomposed into hooks (useSessionStream, useControllerAttach) to make state transitions easier to reason about. I did not spot any dangerouslySetInnerHTML, eval, or unsafe innerHTML usage in the new web/src/components/**, which is good.

Documentation

  • docs/commands/graph.md (new) is helpful; please also link it from the top-level README (currently README.md only mentions libra code).
  • docs/improvement/code.md (+3358) is a useful roadmap but reads like an internal planning document — consider moving it under docs/agent/ or marking it clearly as historical once the plan is shipped, so new contributors don't mistake it for user-facing guidance.
  • docs/agent/ai-object-model-reference.md mentions the new derived records; a short sequence diagram (PlanSet → ValidationReport → RiskScoreBreakdown → DecisionProposal) would help onboarding.

Testing gaps worth filling

  • Round-trip test for the new Phase 3 → Phase 4 persistence (ai_validation_report + ai_risk_score_breakdown + ai_decision_proposal) that exercises schema migration from the old bootstrap without the runtime contract migration applied.
  • Negative test for apply_patch with runtime_context.approval = None and an out-of-workspace target (see move mercury and libra #1).
  • Negative test for the shell handler with a symlinked workdir that resolves outside the working directory (fix compilation #2).
  • Test that the embedded web server rejects an unauthenticated controller attach from a non-loopback peer ([r2cn] 为 Libra 项目增加 Buck2 构建检查 Action #7) once the binding assertion is added.

Overall

This is a substantial, well-modularized refactor with real architectural wins — the runtime contract layer, the split between ToolRegistry and handlers' working dir, and the removal of the ~16 KLoC claudecode module all pay down meaningful complexity. The issues above are mostly about hardening the new surfaces (approval gating, schema referential integrity, async-blocking calls, auth on the new HTTP endpoints) and about honoring the project's own rule on unwrap/expect in tests. None of them require architectural changes; most are 1–20 line fixes.

Happy to re-review once the Critical/Major items are addressed. Nice work overall.


Generated by Claude Code

genedna commented Apr 21, 2026

Copy link
Copy Markdown
Contributor Author

Supplement — TUI & Web UI pass

Follow-up findings from the TUI / embedded web server / React client pass (in addition to the items already posted above). None of these are blockers on their own, but a few are worth fixing before this ships.

Major

  1. JSON.parse on SSE payload has no try/catchweb/src/components/code-session/code-session-page.tsx:420-425. Any malformed or truncated data: frame throws inside the listener; because there is no error boundary wrapping CodeSessionPage, the component stays mounted but stops applying updates. Wrap the parse in try/catch, log the payload, and either drop the frame or reconnect.

  2. Controller token persisted in localStorageweb/src/components/code-session/code-session-page.tsx:402, 368. The browser controller token grants write access to the agent session and currently lives in localStorage, so it survives tab close, is readable by any script on the origin, and is shared across tabs even when the user intends a single-session scope. sessionStorage (or an in-memory ref with a short-lived cookie) is a better fit for a write-capability credential.

  3. No backoff / jitter on EventSource reconnectweb/src/components/code-session/code-session-page.tsx:431-433. The onerror handler only flips UI state; the browser's default reconnect is aggressive and synchronized. When the backend restarts, every connected tab reconnects in the same window. Consider tearing down and re-creating the EventSource with an exponential + jittered delay when onerror fires.

  4. Browser lease renewal uses a 30 s setInterval that depends on session in its depsweb/src/components/code-session/code-session-page.tsx:443-463. On every session update (which arrives frequently over SSE), the effect tears down and recreates the timer. Functionally correct but wasteful; either depend on stable fields (clientId, session?.controller.kind) or drive renewal from the SSE event itself.

  5. Loopback enforcement is present but only for interactive controlsrc/command/code.rs:753-764 rejects non-loopback hosts for interactive web control, which is great. However GET /api/code/session, GET /api/code/events, and GET /api/repo are still unauthenticated (reiterating [r2cn] 为 Libra 项目增加 Buck2 构建检查 Action #7 in the earlier comment). Consider extending the loopback assertion to cover the read-only endpoints as well, or require the controller token on reads.

  6. code_ui.rs holds the session lock across .awaitsrc/internal/ai/web/code_ui.rs around lines 639-678 and 750-774. Worth double-checking that sync_controller_snapshot (and anything else called inside the critical section) never awaits on I/O; otherwise the lock becomes a scalability bottleneck for the event stream.

  7. detach_browser_controller check-then-write is not atomicsrc/internal/ai/web/code_ui.rs:~698. The handler validates client_id + token and then clears state.browser_lease. If two detach requests arrive concurrently (or detach overlaps with a new attach), state can be torn. Combine validation and mutation under a single lock hold.

Minor

  1. Send is not debounced/de-duplicatedweb/src/components/code-session/code-session-page.tsx:479-500. setSending(true) before await apiFetch guards the form button but does not prevent rapid Enter-key submissions. Track a pending-message id or disable the form until the round-trip completes.

  2. Capability badge list recomputes on every renderweb/src/components/code-session/code-session-page.tsx:~715. Object.entries(session.capabilities).map(...) is called inline; wrap the list in useMemo keyed on capability values, or extract a memoized CapabilityBadges component.

  3. static_handler joins path fragments without normalizationsrc/internal/ai/web/mod.rs:113-150. Today this is safe because WebAssets::get is a closed-set lookup, but format!("{}/index.html", path.trim_end_matches('/')) on an adversarial ..-containing URI still produces a string you'd never want to serve from disk. A quick path.contains("..") guard at the top makes the intent explicit.

Nits

  • No test coverage for CodeSessionPageweb/src/components/code-session/code-session-page.tsx. Given that attach/detach, lease renewal, token persistence, and SSE flow are all driven from this component, at least a smoke test (e.g. React Testing Library with a mock EventSource) would be worth adding.
  • Existing server-side tests exercise attach/detach and fixed-controller rejection but do not cover: expired lease auto-cleanup, concurrent attach attempts, or a race between detach and submit_message.

False positives to drop

One item that initial automation flagged but doesn't apply:

  • src/internal/tui/bottom_pane.rs:1452 (.expect("badge separator missing")) is inside #[test] fn focused_input_uses_shared_theme_colors, so per CLAUDE.md the .expect() is fine. Adding the // INVARIANT: comment (per CLAUDE.md guidance for test-code unwraps) would still be nice, but there is no render-time panic risk.

That wraps the review. Main blocking items remain #1 (apply_patch skips approval when runtime_context.approval is None), #3 (missing FOREIGN KEY on the new optional FKs), and #7 (unauthenticated GET /api/code/* reads) from the earlier comment, plus #1 and #2 in this supplement. Everything else can safely be batched.


Generated by Claude Code

Signed-off-by: Quanyi Ma <eli@patch.sh>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f0b7dacf9d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +75 to +76
.trim_end_matches(".exe")
.to_ascii_lowercase();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Normalize token before stripping .exe in git guard

The new shell git guard lowercases after trim_end_matches(".exe"), so GIT.EXE status normalizes to git.exe and bypasses all current matches ("git", /git, \\git). On case-insensitive Windows shells this defeats the policy that blocks direct git usage, allowing models to invoke git through shell instead of the controlled Libra path. Normalize case first (or add an explicit case-insensitive git.exe check) before extension stripping.

Useful? React with 👍 / 👎.

Comment thread src/internal/tui/app.rs
Comment on lines +1628 to +1632
if let Err(error) = runtime
.adapter()
.respond_interaction(&interaction_id, response)
.await
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep managed interaction pending until response send succeeds

If respond_interaction fails here (e.g., transient Codex transport error), the code only emits an error event while the interaction has already been removed from local pending state and the UI is switched to ExecutingTool. That leaves the runtime still waiting on the unresolved interaction but gives the user no way to retry from TUI, creating a stuck session path. The pending interaction should be retained/restored until the response call succeeds.

Useful? React with 👍 / 👎.

@genedna
genedna merged commit 6c0cd40 into libra-tools:main Apr 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants