generated from nhcarrigan/template
feat: productivity suite — task loop, workflow, theming, docs & more (#197)
## Summary A large productivity-focused feature branch delivering a suite of improvements across automation, project management, theming, performance, and documentation. ### Features - **Guided Project Workflow** (#189) — Four-phase workflow panel (Discuss → Plan → Execute → Verify) to keep projects structured from idea to completion - **Automated Task Loop** (#179) — Per-task conversation orchestration with wave-based parallel execution, blocked-task detection, and concurrency control - **Wave-Based Parallel Execution** (#191) — Tasks run in dependency-aware waves with configurable concurrency; independent tasks execute in parallel - **Auto-Commit After Task Completion** (#192) — Task Loop optionally commits after each completed task so progress is never lost - **PRD Creator** (#180) — AI-assisted PRD and task list panel that outputs `hikari-tasks.json` for the Task Loop to consume - **Project Context Panel** (#188) — Persistent `PROJECT.md`, `REQUIREMENTS.md`, `ROADMAP.md`, and `STATE.md` files injected into Claude's context automatically - **Codebase Mapper** (#190) — Generates a `CODEBASE.md` architectural summary so Claude always understands the project structure - **Community Preset Themes** (#181) — Six built-in community themes: Dracula, Catppuccin Mocha, Nord, Solarized Dark, Gruvbox Dark, and Rosé Pine - **In-App Changelog Panel** (#193) — Fetches release notes from GitHub at runtime and displays them inside the app - **Full Embedded Documentation** (#196) — Replaced the single-page help modal with a 12-page paginated docs browser featuring a sidebar TOC, prev/next navigation, keyboard navigation (arrow keys, `?` shortcut), and comprehensive coverage of every feature ### Performance & Fixes - **Lazy Loading & Virtualisation** (#194) — Virtual windowing for conversation history, markdown memoisation, and debounced search for smooth rendering of large sessions - **Ctrl+C Copy Fix** (#195) — `Ctrl+C` now copies selected text as expected; interrupt-Claude behaviour only fires when no text is selected ### UX - Back-to-workflow button in PRD Creator and Task Loop panels for easy navigation - Navigation icon cluster replaced with a single clean dropdown menu ## Closes Closes #179 Closes #180 Closes #181 Closes #188 Closes #189 Closes #190 Closes #191 Closes #192 Closes #193 Closes #194 Closes #195 Closes #196 --- ✨ This PR was created with help from Hikari~ 🌸 Reviewed-on: #197 Co-authored-by: Hikari <hikari@nhcarrigan.com> Co-committed-by: Hikari <hikari@nhcarrigan.com>
This commit was merged in pull request #197.
This commit is contained in:
+106
-9
@@ -158,6 +158,16 @@ pub struct HikariConfig {
|
||||
|
||||
#[serde(default)]
|
||||
pub custom_ui_font_family: Option<String>,
|
||||
|
||||
// Task Loop auto-commit settings
|
||||
#[serde(default)]
|
||||
pub task_loop_auto_commit: bool,
|
||||
|
||||
#[serde(default = "default_task_loop_commit_prefix")]
|
||||
pub task_loop_commit_prefix: String,
|
||||
|
||||
#[serde(default)]
|
||||
pub task_loop_include_summary: bool,
|
||||
}
|
||||
|
||||
impl Default for HikariConfig {
|
||||
@@ -201,6 +211,9 @@ impl Default for HikariConfig {
|
||||
custom_font_family: None,
|
||||
custom_ui_font_path: None,
|
||||
custom_ui_font_family: None,
|
||||
task_loop_auto_commit: false,
|
||||
task_loop_commit_prefix: "feat".to_string(),
|
||||
task_loop_include_summary: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,6 +254,10 @@ fn default_background_image_opacity() -> f32 {
|
||||
0.3
|
||||
}
|
||||
|
||||
fn default_task_loop_commit_prefix() -> String {
|
||||
"feat".to_string()
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum BudgetAction {
|
||||
@@ -258,6 +275,18 @@ pub enum Theme {
|
||||
#[serde(rename = "high-contrast")]
|
||||
HighContrast,
|
||||
Custom,
|
||||
Dracula,
|
||||
Catppuccin,
|
||||
Nord,
|
||||
Solarized,
|
||||
#[serde(rename = "solarized-light")]
|
||||
SolarizedLight,
|
||||
#[serde(rename = "catppuccin-latte")]
|
||||
CatppuccinLatte,
|
||||
#[serde(rename = "gruvbox-light")]
|
||||
GruvboxLight,
|
||||
#[serde(rename = "rose-pine-dawn")]
|
||||
RosePineDawn,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
|
||||
@@ -320,6 +349,9 @@ mod tests {
|
||||
assert!(config.custom_font_family.is_none());
|
||||
assert!(config.custom_ui_font_path.is_none());
|
||||
assert!(config.custom_ui_font_family.is_none());
|
||||
assert!(!config.task_loop_auto_commit);
|
||||
assert_eq!(config.task_loop_commit_prefix, "feat");
|
||||
assert!(!config.task_loop_include_summary);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -363,6 +395,9 @@ mod tests {
|
||||
custom_font_family: Some("MyFont".to_string()),
|
||||
custom_ui_font_path: None,
|
||||
custom_ui_font_family: None,
|
||||
task_loop_auto_commit: true,
|
||||
task_loop_commit_prefix: "fix".to_string(),
|
||||
task_loop_include_summary: true,
|
||||
};
|
||||
|
||||
let json = serde_json::to_string(&config).unwrap();
|
||||
@@ -377,22 +412,84 @@ mod tests {
|
||||
deserialized.greeting_custom_prompt,
|
||||
Some("Hello!".to_string())
|
||||
);
|
||||
assert!(deserialized.task_loop_auto_commit);
|
||||
assert_eq!(deserialized.task_loop_commit_prefix, "fix");
|
||||
assert!(deserialized.task_loop_include_summary);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_theme_serialization() {
|
||||
let dark = Theme::Dark;
|
||||
let light = Theme::Light;
|
||||
let high_contrast = Theme::HighContrast;
|
||||
|
||||
assert_eq!(serde_json::to_string(&dark).unwrap(), "\"dark\"");
|
||||
assert_eq!(serde_json::to_string(&light).unwrap(), "\"light\"");
|
||||
assert_eq!(serde_json::to_string(&Theme::Dark).unwrap(), "\"dark\"");
|
||||
assert_eq!(serde_json::to_string(&Theme::Light).unwrap(), "\"light\"");
|
||||
assert_eq!(
|
||||
serde_json::to_string(&high_contrast).unwrap(),
|
||||
serde_json::to_string(&Theme::HighContrast).unwrap(),
|
||||
"\"high-contrast\""
|
||||
);
|
||||
assert_eq!(serde_json::to_string(&Theme::Custom).unwrap(), "\"custom\"");
|
||||
assert_eq!(
|
||||
serde_json::to_string(&Theme::Dracula).unwrap(),
|
||||
"\"dracula\""
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_string(&Theme::Catppuccin).unwrap(),
|
||||
"\"catppuccin\""
|
||||
);
|
||||
assert_eq!(serde_json::to_string(&Theme::Nord).unwrap(), "\"nord\"");
|
||||
assert_eq!(
|
||||
serde_json::to_string(&Theme::Solarized).unwrap(),
|
||||
"\"solarized\""
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_string(&Theme::SolarizedLight).unwrap(),
|
||||
"\"solarized-light\""
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_string(&Theme::CatppuccinLatte).unwrap(),
|
||||
"\"catppuccin-latte\""
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_string(&Theme::GruvboxLight).unwrap(),
|
||||
"\"gruvbox-light\""
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_string(&Theme::RosePineDawn).unwrap(),
|
||||
"\"rose-pine-dawn\""
|
||||
);
|
||||
}
|
||||
|
||||
let custom = Theme::Custom;
|
||||
assert_eq!(serde_json::to_string(&custom).unwrap(), "\"custom\"");
|
||||
#[test]
|
||||
fn test_theme_deserialization() {
|
||||
assert_eq!(
|
||||
serde_json::from_str::<Theme>("\"dracula\"").unwrap(),
|
||||
Theme::Dracula
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::from_str::<Theme>("\"catppuccin\"").unwrap(),
|
||||
Theme::Catppuccin
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::from_str::<Theme>("\"nord\"").unwrap(),
|
||||
Theme::Nord
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::from_str::<Theme>("\"solarized\"").unwrap(),
|
||||
Theme::Solarized
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::from_str::<Theme>("\"solarized-light\"").unwrap(),
|
||||
Theme::SolarizedLight
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::from_str::<Theme>("\"catppuccin-latte\"").unwrap(),
|
||||
Theme::CatppuccinLatte
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::from_str::<Theme>("\"gruvbox-light\"").unwrap(),
|
||||
Theme::GruvboxLight
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::from_str::<Theme>("\"rose-pine-dawn\"").unwrap(),
|
||||
Theme::RosePineDawn
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user