Skip to content

Commit 302844b

Browse files
committed
Merge origin/main into main
2 parents ad0eadf + dadad29 commit 302844b

15 files changed

Lines changed: 337 additions & 57 deletions

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22

33
## [Unreleased]
44

5+
### Changed (plan-20260715 W0-02, 2026-08-09)
6+
7+
- **W0-02 freeze TUI-owned workflow baselines before Web migration.**
8+
Add `workflow_baseline` choice/threshold contracts, named
9+
`plan_workflow`/`plan_review`/`repair`/`user_input`/`goal_task` filters, and
10+
an INDEX inventory of baseline test names + expected outputs so later Web
11+
harness work can retarget these behaviors instead of deleting them.
12+
513
### Changed (plan-20260715 W0-01, 2026-08-09)
614

715
- **W0-01 source-anchor refresh for the Web-only migration plan.**

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "libra"
3-
version = "0.19.105"
3+
version = "0.19.106"
44
edition = "2024"
55
license = "MIT"
66
description = "AI agent-native version control system with Git on-disk compatibility, SQLite-backed metadata, and tiered cloud storage"

docs/development/plan/plan-20260715.md

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@
350350
| 状态 | 任务 |
351351
|---|---|
352352
| 已勾完(实现 + Codex PASS;部分尚未按本 loop 发布) | W1-01、W1-02、W1-03、W1-05、W1-07 |
353-
| 本 loop 正在闭合 Checkpoint A | W0-01(Codex PASS,待本切片发布)→ W0-02 → W0-03 |
353+
| 本 loop 正在闭合 Checkpoint A | W0-01(已发布 `c98c211` / v0.19.105)→ W0-02(Codex PASS,待本切片发布)→ W0-03 |
354354
| 实现中 / 未勾(仍 FAIL 或未闭合) | W1-04、W1-06、W1-08(及部分 W2 试探) |
355355

356356
**主线续做序(强制):**
@@ -572,24 +572,26 @@ R27 已消除 L 卡与条目超限;R30 进一步把仍跨 focused session、
572572
**Description:** 在迁移前为 TUI 当前独占行为补或确认测试,防止迁移时误删:IntentSpec review、Plan review、network policy、repair loop、resume、goal/task control、approval/user-input。测试只覆盖 `libra code` 行为;20260708 A0 已覆盖的 `libra agent` tracing/review/investigate 行为不在本任务内重复补测。
573573

574574
**Acceptance criteria:**
575-
- [ ] 每个 TUI-owned 行为至少有一个测试名和期望输出。
576-
- [ ] 测试不依赖真实外部 LLM,使用 `test-provider` / fixture。
577-
- [ ] 迁移后这些测试可以逐项改指 Web harness,而不是删除。
575+
- [x] 每个 TUI-owned 行为至少有一个测试名和期望输出。
576+
- [x] 测试不依赖真实外部 LLM,使用 `test-provider` / fixture。
577+
- [x] 迁移后这些测试可以逐项改指 Web harness,而不是删除。
578578

579579
**Verification:**(行为→既有 target 映射;缺映射项须补 `(new)` filter 或 fixture,不得以删除行为过关)
580-
- [ ] IntentSpec / Plan review / network policy:`LIBRA_ENABLE_TEST_PROVIDER=1 cargo test --features test-provider --test code_ui_scenarios -- --test-threads=1`(含 plan_workflow/plan_review 骨架或基线场景名)
581-
- [ ] approval / user-input:`LIBRA_ENABLE_TEST_PROVIDER=1 cargo test --features test-provider --test code_ui_remote_approval_matrix -- --test-threads=1`
582-
- [ ] resume:`LIBRA_ENABLE_TEST_PROVIDER=1 cargo test --features test-provider --test code_resume_test -- --test-threads=1`
583-
- [ ] repair / goal-task 控制面:`LIBRA_ENABLE_TEST_PROVIDER=1 cargo test --features test-provider --test code_ui_remote_state_matrix -- --test-threads=1``cargo test --test ai_goal_state_test`(或等价命名 filter;缺口须新增命名 filter 并在 INDEX 登记)
584-
- [ ] generation / CLI 入口不回归:`LIBRA_ENABLE_TEST_PROVIDER=1 cargo test --features test-provider --test code_ui_remote_generation_matrix -- --test-threads=1``cargo test --test code_cli_dispatch_test`
585-
- [ ] `tests/INDEX.md` 为上列每个行为登记「基线测试名 + 期望输出」一行(AC1 机器可读清单)
580+
- [x] IntentSpec / Plan review / network policy:`LIBRA_ENABLE_TEST_PROVIDER=1 cargo test --features test-provider --test code_ui_scenarios -- --test-threads=1`(含 plan_workflow/plan_review 骨架或基线场景名)
581+
- [x] approval / user-input:`LIBRA_ENABLE_TEST_PROVIDER=1 cargo test --features test-provider --test code_ui_remote_approval_matrix -- --test-threads=1`
582+
- [x] resume:`LIBRA_ENABLE_TEST_PROVIDER=1 cargo test --features test-provider --test code_resume_test -- --test-threads=1`
583+
- [x] repair / goal-task 控制面:`LIBRA_ENABLE_TEST_PROVIDER=1 cargo test --features test-provider --test code_ui_remote_state_matrix -- --test-threads=1``cargo test --test ai_goal_state_test`(或等价命名 filter;缺口须新增命名 filter 并在 INDEX 登记)
584+
- [x] generation / CLI 入口不回归:`LIBRA_ENABLE_TEST_PROVIDER=1 cargo test --features test-provider --test code_ui_remote_generation_matrix -- --test-threads=1``cargo test --test code_cli_dispatch_test`
585+
- [x] `tests/INDEX.md` 为上列每个行为登记「基线测试名 + 期望输出」一行(AC1 机器可读清单)
586586

587587
**Dependencies:** W0-01.
588588

589589
**Files likely touched:** `tests/code_ui_scenarios.rs`, `tests/code_ui_remote_generation_matrix.rs`, `tests/code_ui_remote_approval_matrix.rs`, `tests/code_resume_test.rs`, `tests/code_ui_remote_state_matrix.rs`, `tests/ai_goal_state_test.rs`, `tests/fixtures/code_ui/*`, `tests/INDEX.md`.
590590

591591
**Estimated scope:** M.
592592

593+
**实现轮 Codex review(2026-08-09,model=`gpt-5.6-terra`****PASS**(r1,无 findings)。冻结 `workflow_baseline` 选择集与 repair 阈值文案;`code_ui_scenarios``plan_workflow`/`plan_review`/`repair`/`user_input`/`goal_task` 命名 filter;`code_ui_remote_state_matrix` 补 repair filter;`tests/INDEX.md` 登记基线测试名+期望输出。验证:scenarios 29/29、approval 14/14、resume 11/11、state 17/17、generation 10/10、`ai_goal_state_test` 32/32、`code_cli_dispatch_test` 11/11。
594+
593595
### Task W0-03: 定义 Web-only completion gate
594596

595597
**Description:** 把“可以删除 TUI”的完成定义写成机器可验收 gate,避免 Phase 4 前误切默认入口。

install.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ $ErrorActionPreference = "Stop"
2222
# One of the release version surfaces. `compat_version_surface_sync` pins it
2323
# to Cargo.toml: this value is substituted verbatim into the download URL, so
2424
# a stale value silently installs an old binary when -Version is not given.
25-
$DefaultVersion = "v0.19.105"
25+
$DefaultVersion = "v0.19.106"
2626
$ExeName = "libra.exe"
2727
$ReleaseAsset = "libra-windows-amd64.exe"
2828

install.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ INSTALL_DIR="${LIBRA_INSTALL_DIR:-$LIBRA_HOME/bin}"
1818
# user opts in with LIBRA_ALLOW_FALLBACK=1. Default behaviour is fail-fast so
1919
# offline installs cannot silently regress to a stale version. Bump this on
2020
# every release so the opt-in fallback remains useful.
21-
DEFAULT_VERSION="v0.19.105"
21+
DEFAULT_VERSION="v0.19.106"
2222

2323
# ─── theme (Dusk) ────────────────────────────────────────────────────────────
2424
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ] && [ -z "${LIBRA_NO_TUI:-}" ] && [ "${TERM:-dumb}" != "dumb" ]; then

src/internal/tui/app.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11175,11 +11175,10 @@ Use this failure evidence as the source of truth:\n{report}",
1117511175
}
1117611176

1117711177
fn automatic_plan_repair_threshold_message(report: &str, attempts: u8, max_attempts: u8) -> String {
11178-
format!(
11179-
"Automatic plan repair stopped after {attempts} failed repair attempts (automatic threshold: {max_attempts}).\n\
11180-
Developer confirmation is required before more automatic correction.\n\
11181-
{report}\n\
11182-
Reply `continue` or `/plan continue <max-attempts>` to allow more automatic repair attempts, describe specific Plan repair guidance, or use `/plan cancel` to stop."
11178+
crate::internal::tui::workflow_baseline::plan_repair_threshold_baseline_message(
11179+
report,
11180+
attempts,
11181+
max_attempts,
1118311182
)
1118411183
}
1118511184

src/internal/tui/bottom_pane.rs

Lines changed: 72 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -861,41 +861,68 @@ impl BottomPane {
861861

862862
/// Render the post-plan dialog (Execute Plan / Modify Plan / Cancel).
863863
fn render_post_plan_dialog(&self, area: Rect, buf: &mut Buffer) -> Option<Position> {
864-
self.render_choice_dialog(
865-
area,
866-
buf,
867-
&[
868-
("Execute Plan", "Run the Scheduler"),
869-
("Modify Plan", "Edit the plan"),
870-
("Cancel", "Return to chat"),
871-
],
872-
)
864+
self.render_choice_dialog(area, buf, &Self::post_plan_options())
873865
}
874866

875867
/// Render the network policy dialog shown after the developer approves the plan.
876868
fn render_network_policy_dialog(&self, area: Rect, buf: &mut Buffer) -> Option<Position> {
877-
self.render_choice_dialog(
878-
area,
879-
buf,
880-
&[
881-
("Network: Deny", "Run shell/gates offline"),
882-
("Network: Allow", "Shell/gates may use network"),
883-
("Back", "Return to plan choices"),
884-
],
885-
)
869+
self.render_choice_dialog(area, buf, &Self::network_policy_options())
886870
}
887871

888872
/// Render the IntentSpec dialog (Confirm / Modify / Cancel).
889873
fn render_intent_review_dialog(&self, area: Rect, buf: &mut Buffer) -> Option<Position> {
890-
self.render_choice_dialog(
891-
area,
892-
buf,
893-
&[
894-
("Confirm Intent", "Generate plan"),
895-
("Modify Intent", "Revise spec"),
896-
("Cancel", "Return to chat"),
897-
],
898-
)
874+
self.render_choice_dialog(area, buf, &Self::intent_review_options())
875+
}
876+
877+
fn intent_review_options() -> [(&'static str, &'static str); 3] {
878+
[
879+
(
880+
super::workflow_baseline::INTENT_REVIEW_CHOICES[0],
881+
super::workflow_baseline::INTENT_REVIEW_HELP[0],
882+
),
883+
(
884+
super::workflow_baseline::INTENT_REVIEW_CHOICES[1],
885+
super::workflow_baseline::INTENT_REVIEW_HELP[1],
886+
),
887+
(
888+
super::workflow_baseline::INTENT_REVIEW_CHOICES[2],
889+
super::workflow_baseline::INTENT_REVIEW_HELP[2],
890+
),
891+
]
892+
}
893+
894+
fn post_plan_options() -> [(&'static str, &'static str); 3] {
895+
[
896+
(
897+
super::workflow_baseline::POST_PLAN_CHOICES[0],
898+
super::workflow_baseline::POST_PLAN_HELP[0],
899+
),
900+
(
901+
super::workflow_baseline::POST_PLAN_CHOICES[1],
902+
super::workflow_baseline::POST_PLAN_HELP[1],
903+
),
904+
(
905+
super::workflow_baseline::POST_PLAN_CHOICES[2],
906+
super::workflow_baseline::POST_PLAN_HELP[2],
907+
),
908+
]
909+
}
910+
911+
fn network_policy_options() -> [(&'static str, &'static str); 3] {
912+
[
913+
(
914+
super::workflow_baseline::NETWORK_POLICY_CHOICES[0],
915+
super::workflow_baseline::NETWORK_POLICY_HELP[0],
916+
),
917+
(
918+
super::workflow_baseline::NETWORK_POLICY_CHOICES[1],
919+
super::workflow_baseline::NETWORK_POLICY_HELP[1],
920+
),
921+
(
922+
super::workflow_baseline::NETWORK_POLICY_CHOICES[2],
923+
super::workflow_baseline::NETWORK_POLICY_HELP[2],
924+
),
925+
]
899926
}
900927

901928
fn render_choice_dialog(
@@ -1803,9 +1830,12 @@ mod tests {
18031830
.map(|y| row_text(&plan_buf, y, plan_area.width))
18041831
.collect::<Vec<_>>()
18051832
.join("\n");
1806-
assert!(plan_text.contains("Execute Plan"));
1807-
assert!(plan_text.contains("Modify Plan"));
1808-
assert!(plan_text.contains("Cancel"));
1833+
for label in crate::internal::tui::workflow_baseline::POST_PLAN_CHOICES {
1834+
assert!(
1835+
plan_text.contains(label),
1836+
"post-plan dialog missing baseline choice {label:?}: {plan_text}"
1837+
);
1838+
}
18091839
assert!(!plan_text.contains("Network: Deny"));
18101840
assert!(!plan_text.contains("Network: Allow"));
18111841
assert!(!plan_text.contains("Execute Spec"));
@@ -1819,9 +1849,12 @@ mod tests {
18191849
.map(|y| row_text(&network_buf, y, plan_area.width))
18201850
.collect::<Vec<_>>()
18211851
.join("\n");
1822-
assert!(network_text.contains("Network: Deny"));
1823-
assert!(network_text.contains("Network: Allow"));
1824-
assert!(network_text.contains("Back"));
1852+
for label in crate::internal::tui::workflow_baseline::NETWORK_POLICY_CHOICES {
1853+
assert!(
1854+
network_text.contains(label),
1855+
"network-policy dialog missing baseline choice {label:?}: {network_text}"
1856+
);
1857+
}
18251858
assert!(!network_text.contains("Execute Plan"));
18261859
assert!(!network_text.contains("Modify Plan"));
18271860

@@ -1834,8 +1867,12 @@ mod tests {
18341867
.map(|y| row_text(&intent_buf, y, area.width))
18351868
.collect::<Vec<_>>()
18361869
.join("\n");
1837-
assert!(intent_text.contains("Confirm Intent"));
1838-
assert!(intent_text.contains("Modify Intent"));
1870+
for label in crate::internal::tui::workflow_baseline::INTENT_REVIEW_CHOICES {
1871+
assert!(
1872+
intent_text.contains(label),
1873+
"intent-review dialog missing baseline choice {label:?}: {intent_text}"
1874+
);
1875+
}
18391876
assert!(!intent_text.contains("Execute Plan"));
18401877
assert!(!intent_text.contains("Modify Plan"));
18411878
}

src/internal/tui/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ mod terminal;
7070
mod theme;
7171
// Animated welcome screen.
7272
mod welcome_shader;
73+
// W0-02 frozen IntentSpec / Plan / network / repair baseline contracts.
74+
pub mod workflow_baseline;
7375

7476
// Curated public surface: only types that callers outside the module need.
7577
pub use agent_run_pane::{
@@ -83,3 +85,7 @@ pub use history_cell::{AssistantHistoryCell, DiffHistoryCell, HistoryCell, PlanU
8385
pub use slash_command::{BuiltinCommand, parse_builtin};
8486
pub use status_indicator::StatusIndicator;
8587
pub use terminal::{Tui, TuiEvent, init as tui_init, restore as tui_restore};
88+
pub use workflow_baseline::{
89+
INTENT_REVIEW_CHOICES, NETWORK_POLICY_CHOICES, POST_PLAN_CHOICES,
90+
plan_repair_threshold_baseline_message,
91+
};
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//! W0-02 frozen TUI-owned workflow contracts.
2+
//!
3+
//! These labels and repair hints are the machine-readable baseline for
4+
//! IntentSpec review, Plan review, network policy, and the automatic plan
5+
//! repair threshold. Later Web harness work (W2-16 / W3-02 / W3-15) must
6+
//! **retarget** these contracts, not delete the behaviors they pin.
7+
8+
/// IntentSpec review dialog choices shown while
9+
/// [`crate::internal::tui::AgentStatus::AwaitingIntentReviewChoice`].
10+
pub const INTENT_REVIEW_CHOICES: &[&str] = &["Confirm Intent", "Modify Intent", "Cancel"];
11+
12+
/// Post-plan dialog choices shown while
13+
/// [`crate::internal::tui::AgentStatus::AwaitingPostPlanChoice`].
14+
pub const POST_PLAN_CHOICES: &[&str] = &["Execute Plan", "Modify Plan", "Cancel"];
15+
16+
/// Network policy dialog choices shown while
17+
/// [`crate::internal::tui::AgentStatus::AwaitingNetworkPolicyChoice`].
18+
pub const NETWORK_POLICY_CHOICES: &[&str] = &["Network: Deny", "Network: Allow", "Back"];
19+
20+
/// Help line fragments for each IntentSpec review choice.
21+
pub const INTENT_REVIEW_HELP: &[&str] = &["Generate plan", "Revise spec", "Return to chat"];
22+
23+
/// Help line fragments for each post-plan choice.
24+
pub const POST_PLAN_HELP: &[&str] = &["Run the Scheduler", "Edit the plan", "Return to chat"];
25+
26+
/// Help line fragments for each network policy choice.
27+
pub const NETWORK_POLICY_HELP: &[&str] = &[
28+
"Run shell/gates offline",
29+
"Shell/gates may use network",
30+
"Return to plan choices",
31+
];
32+
33+
/// Frozen threshold message when automatic plan repair stops for developer
34+
/// confirmation. Callers must keep the `/plan continue` affordance.
35+
pub fn plan_repair_threshold_baseline_message(
36+
report: &str,
37+
attempts: u8,
38+
max_attempts: u8,
39+
) -> String {
40+
format!(
41+
"Automatic plan repair stopped after {attempts} failed repair attempts (automatic threshold: {max_attempts}).\n\
42+
Developer confirmation is required before more automatic correction.\n\
43+
{report}\n\
44+
Reply `continue` or `/plan continue <max-attempts>` to allow more automatic repair attempts, describe specific Plan repair guidance, or use `/plan cancel` to stop."
45+
)
46+
}
47+
48+
#[cfg(test)]
49+
mod tests {
50+
use super::*;
51+
52+
#[test]
53+
fn workflow_baseline_choice_sets_are_phase_specific() {
54+
assert_eq!(INTENT_REVIEW_CHOICES.len(), 3);
55+
assert_eq!(POST_PLAN_CHOICES.len(), 3);
56+
assert_eq!(NETWORK_POLICY_CHOICES.len(), 3);
57+
assert!(INTENT_REVIEW_CHOICES.contains(&"Confirm Intent"));
58+
assert!(POST_PLAN_CHOICES.contains(&"Execute Plan"));
59+
assert!(NETWORK_POLICY_CHOICES.contains(&"Network: Deny"));
60+
assert!(!INTENT_REVIEW_CHOICES.iter().any(|c| c.contains("Execute")));
61+
assert!(!POST_PLAN_CHOICES.iter().any(|c| c.contains("Network")));
62+
assert!(!NETWORK_POLICY_CHOICES.iter().any(|c| c.contains("Execute")));
63+
}
64+
65+
#[test]
66+
fn plan_repair_threshold_baseline_keeps_plan_continue_affordance() {
67+
let message = plan_repair_threshold_baseline_message("boom", 3, 3);
68+
assert!(message.contains("Automatic plan repair stopped after 3 failed repair attempts"));
69+
assert!(message.contains("/plan continue"));
70+
assert!(message.contains("boom"));
71+
}
72+
}

0 commit comments

Comments
 (0)